23#include "ROOT/InternalIOUtils.hxx"
35const char *kTransportSeparator =
"://";
38const char *kLineBreakTokens[] = {
"",
"\r\n",
"\n",
"\r\n"};
39constexpr unsigned int kLineBreakTokenSizes[] = {0, 2, 1, 2};
41const char *kLineBreakTokens[] = {
"",
"\n",
"\n",
"\r\n"};
42constexpr unsigned int kLineBreakTokenSizes[] = {0, 1, 1, 2};
44constexpr unsigned int kLineBuffer = 128;
52 size_t copiedBytes = 0;
54 if (offsetInBuffer <
static_cast<std::uint64_t
>(
fBufferSize)) {
55 size_t bytesInBuffer = std::min(nbytes,
static_cast<size_t>(
fBufferSize - offsetInBuffer));
56 memcpy(buffer,
fBuffer + offsetInBuffer, bytesInBuffer);
57 copiedBytes = bytesInBuffer;
64std::unique_ptr<ROOT::Internal::RRawFile>
67 std::string transport = GetTransport(url);
68 if (transport ==
"file") {
70 return std::unique_ptr<RRawFile>(
new RRawFileWin(url, options));
73 if (
auto xurl = ROOT::Internal::GetEOSRedirectedXRootURL(url))
74 return Create(*xurl, options);
75 return std::unique_ptr<RRawFile>(
new RRawFileUnix(url, options));
78 if (transport ==
"http" || transport ==
"https" || transport ==
"root" || transport ==
"roots") {
79 std::string plgclass = transport.compare(0, 4,
"http") == 0 ?
"RRawFileDavix" :
"RRawFileNetXNG";
81 gROOT->GetPluginManager()->FindHandler(
"ROOT::Internal::RRawFile", std::string(url).c_str())) {
82 if (
h->LoadPlugin() == 0) {
83 return std::unique_ptr<RRawFile>(
reinterpret_cast<RRawFile *
>(
h->ExecPlugin(2, &url, &options)));
85 throw std::runtime_error(
"Cannot load plugin handler for " + plgclass);
87 throw std::runtime_error(
"Cannot find plugin handler for " + plgclass);
89 throw std::runtime_error(
"Unsupported transport protocol: " + transport);
99 SetDiscourageReadAheadImpl(!fIsBuffering);
104 for (
unsigned i = 0; i < nReq; ++i) {
111 auto idx = url.find(kTransportSeparator);
112 if (idx == std::string_view::npos)
113 return std::string(url);
114 return std::string(url.substr(idx + strlen(kTransportSeparator)));
119 if (fFileSize != kUnknownFileSize)
123 fFileSize = GetSizeImpl();
133 auto idx = url.find(kTransportSeparator);
134 if (idx == std::string_view::npos)
136 std::string transport(url.substr(0, idx));
137 std::transform(transport.begin(), transport.end(), transport.begin(), ::tolower);
143 size_t res = ReadAt(buffer, nbytes, fFilePos);
157 if (!fIsBuffering || nbytes >
static_cast<unsigned int>(fOptions.fBlockSize))
158 return ReadAtImpl(buffer, nbytes,
offset);
161 fBufferSpace.reset(
new unsigned char[kNumBlockBuffers * fOptions.fBlockSize]);
162 for (
unsigned int i = 0; i < kNumBlockBuffers; ++i) {
163 fBlockBuffers[i].fBuffer = fBufferSpace.get() + i * fOptions.fBlockSize;
164 fBlockBuffers[i].fBufferSize = 0;
168 size_t totalBytes = 0;
169 size_t copiedBytes = 0;
171 for (
unsigned int idx = fBlockBufferIdx; idx < fBlockBufferIdx + kNumBlockBuffers; ++idx) {
172 copiedBytes = fBlockBuffers[idx % kNumBlockBuffers].CopyTo(buffer, nbytes,
offset);
173 buffer =
reinterpret_cast<unsigned char *
>(buffer) + copiedBytes;
174 nbytes -= copiedBytes;
176 totalBytes += copiedBytes;
178 fBlockBufferIdx = idx;
187 RBlockBuffer *thisBuffer = &fBlockBuffers[fBlockBufferIdx % kNumBlockBuffers];
188 size_t res = ReadAtImpl(thisBuffer->
fBuffer, fOptions.fBlockSize,
offset);
191 size_t remainingBytes = std::min(res, nbytes);
192 memcpy(buffer, thisBuffer->
fBuffer, remainingBytes);
193 totalBytes += remainingBytes;
200 ReadVImpl(ioVec, nReq);
205 fIsBuffering =
value;
207 fBufferSpace.reset();
209 SetDiscourageReadAheadImpl(!fIsBuffering);
214 if (fOptions.fLineBreak == ELineBreaks::kAuto) {
216 fOptions.fLineBreak = ELineBreaks::kUnix;
217 bool res = Readln(
line);
218 if ((
line.length() > 0) && (*
line.rbegin() ==
'\r')) {
219 fOptions.fLineBreak = ELineBreaks::kWindows;
226 char buffer[kLineBuffer];
229 nbytes = Read(buffer,
sizeof(buffer));
230 std::string_view bufferView(buffer, nbytes);
231 auto idx = bufferView.find(kLineBreakTokens[
static_cast<int>(fOptions.fLineBreak)]);
232 if (idx != std::string_view::npos) {
234 line.append(buffer, idx);
235 fFilePos -= nbytes - idx;
236 fFilePos += kLineBreakTokenSizes[
static_cast<int>(fOptions.fLineBreak)];
239 line.append(buffer, nbytes);
240 }
while (nbytes > 0);
242 return !
line.empty();
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
The RRawFileUnix class uses POSIX calls to read from a mounted file system.
The RRawFileWin class uses portable C I/O calls to read from a drive.
The RRawFile provides read-only access to local and remote files.
static std::string GetLocation(std::string_view url)
Returns only the file location, e.g. "server/file" for http://server/file.
RRawFile(std::string_view url, ROptions options)
virtual void ReadVImpl(RIOVec *ioVec, unsigned int nReq)
By default implemented as a loop of ReadAt calls but can be overwritten, e.g. XRootD or DAVIX impleme...
static std::string GetTransport(std::string_view url)
Returns only the transport protocol in lower case, e.g. "http" for HTTP://server/file.
std::uint64_t GetSize()
Returns the size of the file.
static std::unique_ptr< RRawFile > Create(std::string_view url, ROptions options=ROptions())
Factory method that returns a suitable concrete implementation according to the transport in the url.
void Seek(std::uint64_t offset)
Change the cursor fFilePos.
size_t ReadAt(void *buffer, size_t nbytes, std::uint64_t offset)
Buffered read from a random position.
bool Readln(std::string &line)
Read the next line starting from the current value of fFilePos. Returns false if the end of the file ...
void EnsureOpen()
Open the file if not already open. Otherwise noop.
void ReadV(RIOVec *ioVec, unsigned int nReq)
Opens the file if necessary and calls ReadVImpl.
size_t Read(void *buffer, size_t nbytes)
Read from fFilePos offset. Returns the actual number of bytes read.
void SetBuffering(bool value)
Turn on/off buffered reads; if off, all scalar read requests go directly to the implementation.
std::string GetUrl() const
Returns the url of the file.
std::uint64_t fBufferOffset
Where in the open file does fBuffer start.
unsigned char * fBuffer
Points into the I/O buffer with data from the file, not owned.
size_t CopyTo(void *buffer, size_t nbytes, std::uint64_t offset)
Tries to copy up to nbytes starting at offset from fBuffer into buffer. Returns number of bytes copie...
size_t fBufferSize
The number of currently buffered bytes in fBuffer.
Used for vector reads from multiple offsets into multiple buffers.
std::size_t fOutBytes
The number of actually read bytes, set by ReadV()
On construction, an ROptions parameter can customize the RRawFile behavior.