|
10 | 10 | *************************************************************************/
|
11 | 11 |
|
12 | 12 | #include "TCurlFile.h"
|
| 13 | +#include "TError.h" |
| 14 | + |
| 15 | +#include <cstdint> |
| 16 | +#include <cstring> |
| 17 | +#include <vector> |
| 18 | + |
| 19 | +TCurlFile::TCurlFile(const char *url, Option_t *opt) |
| 20 | + : TFile(url, strstr(opt, "_WITHOUT_GLOBALREGISTRATION") != nullptr ? "WEB_WITHOUT_GLOBALREGISTRATION" : "WEB"), |
| 21 | + fConnection(new ROOT::Internal::RCurlConnection(url)) |
| 22 | +{ |
| 23 | + TFile::Init(kFALSE); |
| 24 | + fOffset = 0; |
| 25 | + fD = -2; // so TFile::IsOpen() will return true when in ~TFile |
| 26 | +} |
| 27 | + |
| 28 | +Long64_t TCurlFile::GetSize() const |
| 29 | +{ |
| 30 | + std::uint64_t size; |
| 31 | + auto status = fConnection->SendHeadReq(size); |
| 32 | + if (!status) |
| 33 | + return -1; |
| 34 | + return size; |
| 35 | +} |
| 36 | + |
| 37 | +void TCurlFile::Seek(Long64_t offset, ERelativeTo pos) |
| 38 | +{ |
| 39 | + switch (pos) { |
| 40 | + case kBeg: fOffset = offset + fArchiveOffset; break; |
| 41 | + case kCur: fOffset += offset; break; |
| 42 | + case kEnd: |
| 43 | + // this option is not used currently in the ROOT code |
| 44 | + if (fArchiveOffset) |
| 45 | + Error("Seek", "seeking from end in archive is not (yet) supported"); |
| 46 | + fOffset = fEND - offset; // is fEND really EOF or logical EOF? |
| 47 | + break; |
| 48 | + } |
| 49 | +} |
| 50 | + |
| 51 | +Bool_t TCurlFile::ReadBuffer(char *buf, Int_t len) |
| 52 | +{ |
| 53 | + ROOT::Internal::RCurlConnection::RUserRange range; |
| 54 | + range.fDestination = reinterpret_cast<unsigned char *>(buf); |
| 55 | + range.fOffset = fOffset; |
| 56 | + range.fLength = len; |
| 57 | + auto status = fConnection->SendRangesReq(1, &range); |
| 58 | + if (!status) { |
| 59 | + Error("TCurlFile", "can not read data: %s", status.fStatusMsg.c_str()); |
| 60 | + return kTRUE; |
| 61 | + } |
| 62 | + |
| 63 | + fOffset += range.fNBytesRecv; |
| 64 | + return kFALSE; |
| 65 | +} |
| 66 | + |
| 67 | +Bool_t TCurlFile::ReadBuffer(char *buf, Long64_t pos, Int_t len) |
| 68 | +{ |
| 69 | + ROOT::Internal::RCurlConnection::RUserRange range; |
| 70 | + range.fDestination = reinterpret_cast<unsigned char *>(buf); |
| 71 | + range.fOffset = pos; |
| 72 | + range.fLength = len; |
| 73 | + auto status = fConnection->SendRangesReq(1, &range); |
| 74 | + if (!status) { |
| 75 | + Error("TCurlFile", "can not read data: %s", status.fStatusMsg.c_str()); |
| 76 | + return kTRUE; |
| 77 | + } |
| 78 | + return kFALSE; |
| 79 | +} |
| 80 | + |
| 81 | +Bool_t TCurlFile::ReadBuffers(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf) |
| 82 | +{ |
| 83 | + if (nbuf == 0) |
| 84 | + return kFALSE; |
| 85 | + |
| 86 | + std::vector<ROOT::Internal::RCurlConnection::RUserRange> ranges; |
| 87 | + ranges.reserve(nbuf); |
| 88 | + std::size_t bufPos = 0; |
| 89 | + for (Int_t i = 0; i < nbuf; ++i) { |
| 90 | + ROOT::Internal::RCurlConnection::RUserRange r; |
| 91 | + r.fDestination = reinterpret_cast<unsigned char *>(&buf[bufPos]); |
| 92 | + r.fOffset = pos[i]; |
| 93 | + r.fLength = len[i]; |
| 94 | + ranges.emplace_back(r); |
| 95 | + bufPos += len[i]; |
| 96 | + } |
| 97 | + |
| 98 | + auto status = fConnection->SendRangesReq(nbuf, &ranges[0]); |
| 99 | + if (!status) { |
| 100 | + Error("TCurlFile", "can not read data: %s", status.fStatusMsg.c_str()); |
| 101 | + return kTRUE; |
| 102 | + } |
| 103 | + return kFALSE; |
| 104 | +} |
0 commit comments