in cpp/spectrum/io/RewindableImageSource.cpp [24:87]
std::size_t RewindableImageSource::read(
char* const destination,
const std::size_t length) {
std::size_t bytesLeftToCopy = length;
std::size_t bytesCopied = 0;
if (offset > 0) {
// buffer >> destination
const std::size_t elementsLeftInBuffer = offset;
const std::size_t elementsToCopyFromBuffer =
std::min(length, elementsLeftInBuffer);
SPECTRUM_ENFORCE_IF_NOT(buffer.size() >= offset);
std::copy_n(buffer.end() - offset, elementsToCopyFromBuffer, destination);
SPECTRUM_ENFORCE_IF_NOT(offset >= elementsToCopyFromBuffer);
SPECTRUM_ENFORCE_IF_NOT(bytesLeftToCopy >= elementsToCopyFromBuffer);
offset -= elementsToCopyFromBuffer;
bytesCopied += elementsToCopyFromBuffer;
bytesLeftToCopy -= elementsToCopyFromBuffer;
}
if (bytesLeftToCopy == 0) {
SPECTRUM_ENFORCE_IF_NOT(bytesCopied == length);
return bytesCopied;
}
SPECTRUM_ENFORCE_IF_NOT(offset == 0);
SPECTRUM_ENFORCE_IF_NOT(bytesLeftToCopy + bytesCopied == length);
if (isMarkActive) {
// imageSource >> tmp
auto tempDst = std::unique_ptr<char[]>{new char[bytesLeftToCopy]};
const char* tempDstPtr = tempDst.get();
const std::size_t innerRead =
imageSource.read(tempDst.get(), bytesLeftToCopy);
SPECTRUM_ENFORCE_IF_NOT(innerRead <= bytesLeftToCopy);
buffer.reserve(buffer.size() + innerRead);
for (std::size_t i = 0; i < innerRead; i++) {
const char c = tempDstPtr[i];
// tmp >> buffer
buffer.push_back(c);
// tmp >> destination
destination[bytesCopied + i] = c;
}
SPECTRUM_ENFORCE_IF_NOT(buffer.size() >= innerRead);
bytesCopied += innerRead;
} else {
// // imageSource >> destination
bytesCopied += imageSource.read(destination + bytesCopied, bytesLeftToCopy);
if (!buffer.empty()) {
// we are past the buffer and cannot jump back
buffer.clear();
}
}
SPECTRUM_ENFORCE_IF_NOT(bytesCopied <= length);
return bytesCopied;
}