uint32_t TBufferedTransport::readSlow(uint8_t* buf, uint32_t len) { uint32_t have = rBound_ - rBase_; // We should only take the slow path if we can't satisfy the read // with the data already in the buffer. assert(have < len); // If we have some date in the buffer, copy it out and return it. // We have to return it without attempting to read more, since we aren't // guaranteed that the underlying transport actually has more data, so // attempting to read from it could block. if (have > 0) { memcpy(buf, rBase_, have); setReadBuffer(rBuf_.get(), 0); return have; } // No data is available in our buffer. // Get more from underlying transport up to buffer size. // Note that this makes a lot of sense if len < rBufSize_ // and almost no sense otherwise. TODO(dreiss): Fix that // case (possibly including some readv hotness). setReadBuffer(rBuf_.get(), transport_->read(rBuf_.get(), rBufSize_)); // Hand over whatever we have. uint32_t give = std::min(len, static_cast<uint32_t>(rBound_ - rBase_)); memcpy(buf, rBase_, give); rBase_ += give; return give; }
uint32_t TFramedTransport::readSlow(uint8_t* buf, uint32_t len) { uint32_t want = len; uint32_t have = rBound_ - rBase_; // We should only take the slow path if we can't satisfy the read // with the data already in the buffer. assert(have < want); // If we have some data in the buffer, copy it out and return it. // We have to return it without attempting to read more, since we aren't // guaranteed that the underlying transport actually has more data, so // attempting to read from it could block. if (have > 0) { memcpy(buf, rBase_, have); setReadBuffer(rBuf_.get(), 0); return have; } // Read another frame. if (!readFrame()) { // EOF. No frame available. return 0; } // TODO(dreiss): Should we warn when reads cross frames? // Hand over whatever we have. uint32_t give = std::min(want, static_cast<uint32_t>(rBound_ - rBase_)); memcpy(buf, rBase_, give); rBase_ += give; want -= give; return (len - want); }
size_t TCPPipeSlave::readData(IO::File::Byte* buffer,size_t bufferSize) { /* Receive a data packet from the master: */ Packet* newPacket=multiplexer->receivePacket(pipeId); /* Check for error conditions: */ if(newPacket->packetSize!=0) { /* Install the new packet as the pipe's read buffer: */ if(packet!=0) multiplexer->deletePacket(packet); packet=newPacket; setReadBuffer(Packet::maxPacketSize,reinterpret_cast<Byte*>(packet->packet),false); return packet->packetSize; } else { /* Read the status packet: */ multiplexer->deletePacket(newPacket); newPacket=multiplexer->receivePacket(pipeId); Packet::Reader reader(newPacket); int errorCode=reader.read<int>(); multiplexer->deletePacket(newPacket); /* Throw an exception: */ handleReadError(errorCode); } /* Never reached; just to make compiler happy: */ return 0; }
uint32_t TBufferedTransport::readSlow(uint8_t* buf, uint32_t len) { uint32_t want = len; uint32_t have = rBound_ - rBase_; // We should only take the slow path if we can't satisfy the read // with the data already in the buffer. assert(have < want); // Copy out whatever we have. if (have > 0) { memcpy(buf, rBase_, have); want -= have; buf += have; } // Get more from underlying transport up to buffer size. // Note that this makes a lot of sense if len < rBufSize_ // and almost no sense otherwise. TODO(dreiss): Fix that // case (possibly including some readv hotness). setReadBuffer(rBuf_.get(), transport_->read(rBuf_.get(), rBufSize_)); // Hand over whatever we have. uint32_t give = std::min(want, static_cast<uint32_t>(rBound_ - rBase_)); memcpy(buf, rBase_, give); rBase_ += give; want -= give; return (len - want); }
void Framebuffer::blit(GLenum readBuffer, const std::array<GLint, 4> & srcRect, Framebuffer * destFbo, const std::vector<GLenum> & drawBuffers, const std::array<GLint, 4> & destRect, ClearBufferMask mask, GLenum filter) const { setReadBuffer(readBuffer); destFbo->setDrawBuffers(drawBuffers); implementation().blit(this, destFbo, srcRect[0], srcRect[1], srcRect[2], srcRect[3], destRect[0], destRect[1], destRect[2], destRect[3], mask, filter); }
TCPPipeSlave::~TCPPipeSlave(void) { /* Delete the current multicast packet: */ if(packet!=0) { multiplexer->deletePacket(packet); setReadBuffer(0,0,false); } }
void Framebuffer::blit(GLenum readBuffer, const std::array<GLint, 4> & srcRect, Framebuffer * destFbo, const std::vector<GLenum> & drawBuffers, const std::array<GLint, 4> & destRect, ClearBufferMask mask, GLenum filter) const { bind(GL_READ_FRAMEBUFFER); destFbo->bind(GL_DRAW_FRAMEBUFFER); setReadBuffer(readBuffer); destFbo->setDrawBuffers(drawBuffers); blit(srcRect, destRect, mask, filter); }
uint32_t TFramedTransport::readEnd() { // include framing bytes uint32_t bytes_read = static_cast<uint32_t>(rBound_ - rBuf_.get() + sizeof(uint32_t)); if (rBufSize_ > bufReclaimThresh_) { rBufSize_ = 0; rBuf_.reset(); setReadBuffer(rBuf_.get(), rBufSize_); } return bytes_read; }
SeekableFilter::~SeekableFilter(void) { /* Uninstall the buffered file's read buffer: */ setReadBuffer(0,0,false); /* Delete the buffer list: */ while(head!=0) { BufferHeader* succ=head->succ; delete[] reinterpret_cast<Byte*>(head); head=succ; } }
bool TFramedTransport::readFrame() { // TODO(dreiss): Think about using readv here, even though it would // result in (gasp) read-ahead. // Read the size of the next frame. // We can't use readAll(&sz, sizeof(sz)), since that always throws an // exception on EOF. We want to throw an exception only if EOF occurs after // partial size data. int32_t sz = -1; uint32_t size_bytes_read = 0; while (size_bytes_read < sizeof(sz)) { uint8_t* szp = reinterpret_cast<uint8_t*>(&sz) + size_bytes_read; uint32_t bytes_read = transport_->read(szp, static_cast<uint32_t>(sizeof(sz)) - size_bytes_read); if (bytes_read == 0) { if (size_bytes_read == 0) { // EOF before any data was read. return false; } else { // EOF after a partial frame header. Raise an exception. throw TTransportException(TTransportException::END_OF_FILE, "No more data to read after " "partial frame header."); } } size_bytes_read += bytes_read; } sz = ntohl(sz); if (sz < 0) { throw TTransportException("Frame size has negative value"); } // Check for oversized frame if (sz > static_cast<int32_t>(maxFrameSize_)) throw TTransportException(TTransportException::CORRUPTED_DATA, "Received an oversized frame"); // Read the frame payload, and reset markers. if (sz > static_cast<int32_t>(rBufSize_)) { rBuf_.reset(new uint8_t[sz]); rBufSize_ = sz; } transport_->readAll(rBuf_.get(), sz); setReadBuffer(rBuf_.get(), sz); return true; }
HttpFile::~HttpFile(void) { /* Skip all unread parts of the HTTP reply body: */ if(chunked) { if(!haveEof) { /* Skip all leftover chunks: */ while(true) { /* Skip the rest of the current chunk: */ pipe->skip<char>(unreadSize); /* Skip the chunk footer: */ if(pipe->getChar()!='\r'||pipe->getChar()!='\n') Misc::throwStdErr("Comm::HttpFile: Malformed HTTP chunk footer"); /* Parse the next chunk header: */ unreadSize=parseChunkHeader(*pipe); if(unreadSize==0) break; } } /* Skip any optional message trailers: */ while(pipe->getChar()!='\r') { /* Skip the line: */ while(pipe->getChar()!='\r') ; if(pipe->getChar()!='\n') Misc::throwStdErr("Comm::HttpFile: Malformed HTTP body trailer"); } if(pipe->getChar()!='\n') Misc::throwStdErr("Comm::HttpFile: Malformed HTTP body trailer"); } else if(fixedSize) { /* Skip the rest of the fixed-size message body: */ pipe->skip<char>(unreadSize); } /* Release the read buffer: */ setReadBuffer(0,0,false); }
void TFramedTransport::readFrame() { // TODO(dreiss): Think about using readv here, even though it would // result in (gasp) read-ahead. // Read the size of the next frame. int32_t sz; transport_->readAll((uint8_t*)&sz, sizeof(sz)); sz = ntohl(sz); if (sz < 0) { throw TTransportException("Frame size has negative value"); } // Read the frame payload, and reset markers. if (sz > static_cast<int32_t>(rBufSize_)) { rBuf_.reset(new uint8_t[sz]); rBufSize_ = sz; } transport_->readAll(rBuf_.get(), sz); setReadBuffer(rBuf_.get(), sz); }
const uint8_t* TBufferedTransport::borrowSlow(uint8_t* buf, uint32_t* len) { // If the request is bigger than our buffer, we are hosed. if (*len > rBufSize_) { return NULL; } // The number of bytes of data we have already. uint32_t have = rBound_ - rBase_; // The number of additional bytes we need from the underlying transport. int32_t need = *len - have; // The space from the start of the buffer to the end of our data. uint32_t offset = rBound_ - rBuf_.get(); assert(need > 0); // If we have less than half our buffer space available, shift the data // we have down to the start. If the borrow is big compared to our buffer, // this could be kind of a waste, but if the borrow is small, it frees up // space at the end of our buffer to do a bigger single read from the // underlying transport. Also, if our needs extend past the end of the // buffer, we have to do a copy no matter what. if ((offset > rBufSize_/2) || (offset + need > rBufSize_)) { memmove(rBuf_.get(), rBase_, have); setReadBuffer(rBuf_.get(), have); } // First try to fill up the buffer. uint32_t got = transport_->read(rBound_, rBufSize_ - have); rBound_ += got; need -= got; // If that fails, readAll until we get what we need. if (need > 0) { rBound_ += transport_->readAll(rBound_, need); } *len = rBound_ - rBase_; return rBase_; }
size_t HttpFile::readData(IO::File::Byte* buffer,size_t bufferSize) { /* Read depending on the reply body's transfer encoding: */ if(chunked) { /* Check if the current chunk is finished: */ if(unreadSize==0) { /* Bail out if the EOF chunk has already been read: */ if(haveEof) return 0; /* Skip the chunk footer: */ if(pipe->getChar()!='\r'||pipe->getChar()!='\n') Misc::throwStdErr("Comm::HttpFile: Malformed HTTP chunk footer"); /* Parse the next chunk header: */ unreadSize=parseChunkHeader(*pipe); } /* Set the EOF flag if this chunk has size zero: */ if(unreadSize==0) { haveEof=true; return 0; } /* Read more data directly from the pipe's read buffer: */ void* pipeBuffer; size_t pipeSize=pipe->readInBuffer(pipeBuffer,unreadSize); setReadBuffer(pipeSize,static_cast<Byte*>(pipeBuffer),false); /* Reduce the unread data size and return the read size: */ unreadSize-=pipeSize; return pipeSize; } else if(fixedSize) { /* Check for end-of-file: */ if(unreadSize==0) return 0; /* Read more data directly from the pipe's read buffer: */ void* pipeBuffer; size_t pipeSize=pipe->readInBuffer(pipeBuffer,unreadSize); setReadBuffer(pipeSize,static_cast<Byte*>(pipeBuffer),false); /* Reduce the unread data size and return the read size: */ unreadSize-=pipeSize; return pipeSize; } else { /* Read more data directly from the pipe's read buffer: */ void* pipeBuffer; size_t pipeSize=pipe->readInBuffer(pipeBuffer); setReadBuffer(pipeSize,static_cast<Byte*>(pipeBuffer),false); /* Return the read size: */ return pipeSize; } }
void Framebuffer::readPixels(const GLenum readBuffer, const std::array<GLint, 4> & rect, const GLenum format, const GLenum type, GLvoid * data) const { setReadBuffer(readBuffer); readPixels(rect, format, type, data); }
size_t SeekableFilter::readData(File::Byte* buffer,size_t bufferSize) { /* Check if the file position needs to be moved to the read position: */ if(filePos!=readPos) { if(readPos>filePos) { /* Skip forward in buffer chain from the current position: */ currentPos+=(readPos-filePos); /* Skip buffers until the current buffer offset is within the current buffer: */ while(currentPos>Offset(current->size)) { /* Check if there is a next buffer: */ if(current->succ!=0) { /* Go to the next buffer: */ currentPos-=current->size; current=current->succ; } else { /* Check for end-of-file: */ if(source->eof()) throw SeekError(readPos); /* Read more data: */ readFromSource(); } } } else { /* Skip from the beginning of the buffer chain: */ current=head; currentPos=readPos; /* Skip buffers until the current buffer offset is within the current buffer: */ while(currentPos>Offset(current->size)) { /* Go to the next buffer: */ currentPos-=current->size; current=current->succ; } } /* Update the file position: */ filePos=readPos; } /* Check if the file position is at the end of the read data: */ if(filePos==totalReadSize) { /* Check for end-of-file: */ if(source->eof()) return 0; /* Read more data: */ readFromSource(); } /* Read from the current file position: */ if(currentPos==Offset(current->size)) { /* Go to the next buffer: */ current=current->succ; currentPos=0; } size_t copySize=current->size-size_t(currentPos); setReadBuffer(copySize,reinterpret_cast<Byte*>(current+1)+currentPos,false); readPos+=copySize; filePos+=copySize; currentPos+=copySize; return copySize; }
std::vector<unsigned char> Framebuffer::readPixelsToByteArray(GLenum readBuffer, const std::array<GLint, 4> & rect, GLenum format, GLenum type) const { setReadBuffer(readBuffer); return readPixelsToByteArray(rect, format, type); }