// read one block if possible BOOL CBlockBuffer::ReadBlock(void *pv, SLONG &slSize) { // must not be inside block reading ASSERT(bb_slBlockSizeRead==0); // read header of next block in incoming buffer struct BlockHeader bh; SLONG slbhSize; slbhSize = ReadBytes(&bh, sizeof(bh)); // if the header information is not in buffer if (slbhSize < sizeof(bh)) { // unwind UnreadBytes(slbhSize); // nothing to receive return FALSE; } // if the block has not yet been received if (QueryReadBytes() < bh.bh_slSize) { // unwind UnreadBytes(slbhSize); // nothing to receive return FALSE; } // if there is too much data for the receiving memory space if (bh.bh_slSize > slSize) { // unwind UnreadBytes(slbhSize); // mark how much space we would need slSize = bh.bh_slSize; // nothing to receive ASSERT(FALSE); // this shouldn't happen return FALSE; } // if using stats if (bb_pbbsStats!=NULL) { // if block could not have been received yet, due to time limits if (bh.bh_tvFinalTime>_pTimer->GetHighPrecisionTimer()) { // unwind UnreadBytes(slbhSize); // nothing to receive return FALSE; } } // read the block slSize = ReadBytes(pv, bh.bh_slSize); ASSERT(slSize == bh.bh_slSize); // received return TRUE; }
// read one block from buffer to stream BOOL CBlockBuffer::ReadBlockToStream(CTStream &strm) { // must not be inside block reading ASSERT(bb_slBlockSizeRead==0); // read header of next block in incoming buffer struct BlockHeader bh; SLONG slbhSize; slbhSize = ReadBytes(&bh, sizeof(bh)); // if the header information is not in buffer if (slbhSize < sizeof(bh)) { // unwind UnreadBytes(slbhSize); // nothing to receive return FALSE; } // if the block has not yet been received if (QueryReadBytes() < bh.bh_slSize) { // unwind UnreadBytes(slbhSize); // nothing to receive return FALSE; } // if using stats if (bb_pbbsStats!=NULL) { // if block could not have been received yet, due to time limits if (bh.bh_tvFinalTime>_pTimer->GetHighPrecisionTimer()) { // unwind UnreadBytes(slbhSize); // nothing to receive return FALSE; } } // read from buffer to destination buffer try { SLONG slSize = ReadBytesToStream(strm, bh.bh_slSize); ASSERT(slSize == bh.bh_slSize); } catch (char *strError) { ASSERT(FALSE); CPrintF(TRANS("Buffer error reading to stream: %s\n"), strError); return FALSE; } return TRUE; }
// peek sizes of next block void CBlockBuffer::PeekBlockSize(SLONG &slExpectedSize, SLONG &slReceivedSoFar) { // if inside block reading if(bb_slBlockSizeRead>0) { // no information available slExpectedSize = 0; slReceivedSoFar = 0; // if not inside block reading } else { // read header of next block in incoming buffer struct BlockHeader bh; SLONG slbhSize; slbhSize = ReadBytes(&bh, sizeof(bh)); // unwind UnreadBytes(slbhSize); // if the header information is not in buffer if (slbhSize < sizeof(bh)) { // no information available slExpectedSize = 0; slReceivedSoFar = 0; // if the header information is present } else { // total size is size of block slExpectedSize = bh.bh_slSize; // received so far is how much is really present slReceivedSoFar = QueryReadBytes()-sizeof(struct BlockHeader); } } }
// fill buffer to contain at least iNumChars bytes past cursor bool CxdsBuffer::Fill(u32 iNumChars) { // short-circuit unnecessary fills if(m_iUnreadBytes >= iNumChars) return true; // move existing data (if any) to beginning of buffer Sync(); if(!ExpandToFit(iNumChars)) return false; // read additional data into buffer (retries if not enough is read and end-of-file is not reached) int nchrs = 0; while(nchrs >= 0 && m_iUnreadBytes < iNumChars) { nchrs = XDS_READ(m_hFile, (void*)(m_cursor + m_iUnreadBytes), m_iBufSize - UnreadBytes()); if(nchrs > 0) { AddUnreadBytes(nchrs); } } return (m_iUnreadBytes >= iNumChars); }
// unread raw block data void CBlockBuffer::UnreadRawBlock(SLONG slSize) { bb_slBlockSizeRead+=slSize; UnreadBytes(slSize); }
// read raw block data SLONG CBlockBuffer::ReadRawBlock(void *pv, SLONG slSize) { // if inside block reading if(bb_slBlockSizeRead>0) { // clamp size to prevent reading across real blocks slSize = Min(slSize, bb_slBlockSizeRead); // read the raw block SLONG slResult = ReadBytes(pv, slSize); ASSERT(slResult==slSize); // decrement block size counter bb_slBlockSizeRead-=slResult; // must not underflow ASSERT(bb_slBlockSizeRead>=0); return slResult; // if not inside block reading } else { // read header of next block in incoming buffer struct BlockHeader bh; SLONG slbhSize; slbhSize = ReadBytes(&bh, sizeof(bh)); // if the header information is not in buffer if (slbhSize < sizeof(bh)) { // unwind UnreadBytes(slbhSize); // nothing to receive return FALSE; } // if the block has not yet been received if (QueryReadBytes() < bh.bh_slSize) { // unwind UnreadBytes(slbhSize); // nothing to receive return FALSE; } // if using stats if (bb_pbbsStats!=NULL) { // if block could not have been received yet, due to time limits if (bh.bh_tvFinalTime>_pTimer->GetHighPrecisionTimer()) { // unwind UnreadBytes(slbhSize); // nothing to receive return FALSE; } } // remember block size counter bb_slBlockSizeRead = bh.bh_slSize+sizeof(struct BlockHeader); // unwind header UnreadBytes(slbhSize); // clamp size to prevent reading across real blocks slSize = Min(slSize, bb_slBlockSizeRead); // read the raw block with header SLONG slResult = ReadBytes(pv, slSize); ASSERT(slResult==slSize); // decrement block size counter bb_slBlockSizeRead-=slResult; // must not underflow ASSERT(bb_slBlockSizeRead>=0); return slResult; } }
// unread one block void CBlockBuffer::UnreadBlock(SLONG slSize) { UnreadBytes(slSize+sizeof(struct BlockHeader)); }