34 const char *kTransportSeparator =
"://";
37 const char *kLineBreakTokens[] = {
"",
"\r\n",
"\n",
"\r\n"};
38 constexpr
unsigned int kLineBreakTokenSizes[] = {0, 2, 1, 2};
40 const char *kLineBreakTokens[] = {
"",
"\n",
"\n",
"\r\n"};
41 constexpr
unsigned int kLineBreakTokenSizes[] = {0, 1, 1, 2};
43 constexpr
unsigned int kLineBuffer = 128;
46 size_t ROOT::Internal::RRawFile::RBlockBuffer::CopyTo(
void *buffer,
size_t nbytes, std::uint64_t offset)
48 if (offset < fBufferOffset)
51 size_t copiedBytes = 0;
52 std::uint64_t offsetInBuffer = offset - fBufferOffset;
53 if (offsetInBuffer < static_cast<std::uint64_t>(fBufferSize)) {
54 size_t bytesInBuffer = std::min(nbytes, static_cast<size_t>(fBufferSize - offsetInBuffer));
55 memcpy(buffer, fBuffer + offsetInBuffer, bytesInBuffer);
56 copiedBytes = bytesInBuffer;
61 ROOT::Internal::RRawFile::RRawFile(std::string_view url, ROptions options)
62 : fBlockBufferIdx(0), fBufferSpace(nullptr), fFileSize(kUnknownFileSize), fIsOpen(false), fUrl(url),
63 fOptions(options), fFilePos(0)
67 ROOT::Internal::RRawFile::~RRawFile()
69 delete[] fBufferSpace;
72 std::unique_ptr<ROOT::Internal::RRawFile>
73 ROOT::Internal::RRawFile::Create(std::string_view url, ROptions options)
75 std::string transport = GetTransport(url);
76 if (transport ==
"file") {
78 return std::unique_ptr<RRawFile>(
new RRawFileWin(url, options));
80 return std::unique_ptr<RRawFile>(
new RRawFileUnix(url, options));
83 if (transport ==
"http" || transport ==
"https") {
84 if (TPluginHandler *h = gROOT->GetPluginManager()->FindHandler(
"ROOT::Internal::RRawFile")) {
85 if (h->LoadPlugin() == 0) {
86 return std::unique_ptr<RRawFile>(
reinterpret_cast<RRawFile *
>(h->ExecPlugin(2, &url, &options)));
88 throw std::runtime_error(
"Cannot load plugin handler for RRawFileDavix");
90 throw std::runtime_error(
"Cannot find plugin handler for RRawFileDavix");
92 throw std::runtime_error(
"Unsupported transport protocol: " + transport);
95 void *ROOT::Internal::RRawFile::MapImpl(
size_t , std::uint64_t ,
98 throw std::runtime_error(
"Memory mapping unsupported");
101 void ROOT::Internal::RRawFile::UnmapImpl(
void * ,
size_t )
103 throw std::runtime_error(
"Memory mapping unsupported");
106 std::string ROOT::Internal::RRawFile::GetLocation(std::string_view url)
108 auto idx = url.find(kTransportSeparator);
109 if (idx == std::string_view::npos)
110 return std::string(url);
111 return std::string(url.substr(idx + strlen(kTransportSeparator)));
114 std::uint64_t ROOT::Internal::RRawFile::GetSize()
120 if (fFileSize == kUnknownFileSize)
121 fFileSize = GetSizeImpl();
125 std::string ROOT::Internal::RRawFile::GetTransport(std::string_view url)
127 auto idx = url.find(kTransportSeparator);
128 if (idx == std::string_view::npos)
130 std::string transport(url.substr(0, idx));
131 std::transform(transport.begin(), transport.end(), transport.begin(), ::tolower);
135 void *ROOT::Internal::RRawFile::Map(
size_t nbytes, std::uint64_t offset, std::uint64_t &mapdOffset)
140 return MapImpl(nbytes, offset, mapdOffset);
143 size_t ROOT::Internal::RRawFile::Read(
void *buffer,
size_t nbytes)
145 size_t res = ReadAt(buffer, nbytes, fFilePos);
150 size_t ROOT::Internal::RRawFile::ReadAt(
void *buffer,
size_t nbytes, std::uint64_t offset)
154 R__ASSERT(fOptions.fBlockSize >= 0);
158 if (nbytes > static_cast<unsigned int>(fOptions.fBlockSize))
159 return ReadAtImpl(buffer, nbytes, offset);
161 if (fBufferSpace ==
nullptr) {
162 fBufferSpace =
new unsigned char[kNumBlockBuffers * fOptions.fBlockSize];
163 for (
unsigned int i = 0; i < kNumBlockBuffers; ++i)
164 fBlockBuffers[i].fBuffer = fBufferSpace + i * fOptions.fBlockSize;
167 size_t totalBytes = 0;
168 size_t copiedBytes = 0;
170 for (
unsigned int idx = fBlockBufferIdx; idx < fBlockBufferIdx + kNumBlockBuffers; ++idx) {
171 copiedBytes = fBlockBuffers[idx % kNumBlockBuffers].CopyTo(buffer, nbytes, offset);
172 buffer =
reinterpret_cast<unsigned char *
>(buffer) + copiedBytes;
173 nbytes -= copiedBytes;
174 offset += copiedBytes;
175 totalBytes += copiedBytes;
177 fBlockBufferIdx = idx;
186 RBlockBuffer *thisBuffer = &fBlockBuffers[fBlockBufferIdx % kNumBlockBuffers];
187 size_t res = ReadAtImpl(thisBuffer->fBuffer, fOptions.fBlockSize, offset);
188 thisBuffer->fBufferOffset = offset;
189 thisBuffer->fBufferSize = res;
190 size_t remainingBytes = std::min(res, nbytes);
191 memcpy(buffer, thisBuffer->fBuffer, remainingBytes);
192 totalBytes += remainingBytes;
196 bool ROOT::Internal::RRawFile::Readln(std::string &line)
198 if (fOptions.fLineBreak == ELineBreaks::kAuto) {
200 fOptions.fLineBreak = ELineBreaks::kUnix;
201 bool res = Readln(line);
202 if ((line.length() > 0) && (*line.rbegin() ==
'\r')) {
203 fOptions.fLineBreak = ELineBreaks::kWindows;
204 line.resize(line.length() - 1);
210 char buffer[kLineBuffer];
213 nbytes = Read(buffer,
sizeof(buffer));
214 std::string_view bufferView(buffer, nbytes);
215 auto idx = bufferView.find(kLineBreakTokens[static_cast<int>(fOptions.fLineBreak)]);
216 if (idx != std::string_view::npos) {
218 line.append(buffer, idx);
219 fFilePos -= nbytes - idx;
220 fFilePos += kLineBreakTokenSizes[
static_cast<int>(fOptions.fLineBreak)];
223 line.append(buffer, nbytes);
224 }
while (nbytes > 0);
226 return !line.empty();
229 void ROOT::Internal::RRawFile::Seek(std::uint64_t offset)
234 void ROOT::Internal::RRawFile::Unmap(
void *region,
size_t nbytes)
237 throw std::runtime_error(
"Cannot unmap, file not open");
238 UnmapImpl(region, nbytes);