/// at most dwMinInBufferSize bytes must be decoded, except for the last bytes in stream
void ZipArchiveFile::FillOutBuffer(DWORD dwMinInBufferSize)
{
   std::vector<BYTE> vecTempOutBuffer;
   while (m_vecOutBuffer.size() < dwMinInBufferSize)
   {
      FillInputBuffer();

      // check input buffer
      if (m_bEndOfInputStream && m_vecInBuffer.empty())
      {
         // can't uncompress without data in input buffer
         m_bEndOfOutputStream = true;
         return;
      }

      // uncompress
      size_t uiUnusedInBytes = 0;
      {
         DWORD dwBytesToUncompress = dwMinInBufferSize - m_vecOutBuffer.size();

         // ensure minimum number of bytes to produce
         dwBytesToUncompress = std::max(dwBytesToUncompress, DWORD(256));

         bool bRet = m_decompressor.Uncompress(
            &m_vecInBuffer[0],
            m_vecInBuffer.size(),
            uiUnusedInBytes,
            vecTempOutBuffer, dwBytesToUncompress);

         //ATLTRACE(_T("Uncompress(): input %u bytes, output %u bytes, consumed %u input bytes\n"),
         //   m_vecInBuffer.size(),
         //   vecTempOutBuffer.size(),
         //   m_vecInBuffer.size() - uiUnusedInBytes);

         if (!bRet && vecTempOutBuffer.empty())
         {
            m_bEndOfOutputStream = true;
            return;
         }
      }

      // append to out buffer
      if (!vecTempOutBuffer.empty())
      {
         m_vecOutBuffer.insert(m_vecOutBuffer.end(), vecTempOutBuffer.begin(), vecTempOutBuffer.end());
         vecTempOutBuffer.clear();
      }

      // move unused in bytes to front of buffer
      if (uiUnusedInBytes > 0)
      {
         size_t uiDecompressed = m_vecInBuffer.size() - uiUnusedInBytes;

         if (uiDecompressed > 0)
            m_vecInBuffer.erase(m_vecInBuffer.begin(), m_vecInBuffer.begin() + uiDecompressed);
      }
      else
         m_vecInBuffer.clear();
   }
}
示例#2
0
 // Handles skiped bytes.
 void SkipInputData(j_decompress_ptr cinfo, long num_bytes)
 {
     if(num_bytes > 0)
     {
         while(num_bytes > (long)cinfo->src->bytes_in_buffer)
         {
             num_bytes -= (long)cinfo->src->bytes_in_buffer;
             FillInputBuffer(cinfo);
         }
         cinfo->src->next_input_byte += (size_t)num_bytes;
         cinfo->src->bytes_in_buffer -= (size_t)num_bytes;
     }
 }
示例#3
0
//-------------------------------------------------------------------------
void CFKFileJpg::SkipInputData( j_decompress_ptr p_pInfo, long p_lNumBytes )
{
	CFKFileJpg* pSource = ( CFKFileJpg* )p_pInfo->src;
	if( p_lNumBytes > 0 )
	{
		while( p_lNumBytes > ( long )pSource->bytes_in_buffer )
		{
			p_lNumBytes -= ( long )pSource->bytes_in_buffer;
			FillInputBuffer( p_pInfo );
		}
		pSource->next_input_byte	+= (size_t)p_lNumBytes;
		pSource->bytes_in_buffer	-= (size_t)p_lNumBytes;
	}
}
	void XMLReader::FillOutputBuffer()
	{
		if (mOutputStart > mOutputBuffer) {
			size_t len = mOutputEnd - mOutputStart;
			std::memmove(mOutputBuffer, mOutputStart, len * sizeof(*mOutputBuffer));
			mOutputEnd = mOutputBuffer + len;
			mOutputStart = mOutputBuffer;
		}
		size_t remainingCapacity = mOutputBuffer + kOutputBufferCount - mOutputEnd;
		if (remainingCapacity > 0) {
			FillInputBuffer();
			if (mInputEnd > mInputStart) {
				mConverter.Convert(const_cast<const char * &>(mInputStart), mInputEnd,
					mOutputEnd, mOutputBuffer + kOutputBufferCount);
			}
		}
	}
	// Returns true if a node was read successfully, false on EOF
	bool XMLReader::ReadInternal()
	{
		switch (mNodeType) {
			case kNone:
				FillInputBuffer();
				if ((mInputEnd - mInputStart) >= 2) {
					uint16_t x = (uint16_t(mInputBuffer[0]) << 8) | mInputBuffer[1];
					switch (x) {
						case 0xFEFF:
						case 0x003C:
							mConverter.Reset(TextEncoding::UTF16BE());
							break;
						case 0xFFFE:
						case 0x3C00:
							mConverter.Reset(TextEncoding::UTF16LE());
							break;
					}
				}
				mNodeType = kDocument;
				return true;
			
			case kDocument:
				// An XML document can start with:
				// document	::= prolog element Misc*
				// prolog	::= XMLDecl? Misc* (doctypedecl Misc*)?
				// XMLDecl	::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
				// Misc ::= Comment | PI | S
				// doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S? ('[' intSubset ']' S?)? '>'
				// Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
				// PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
				// S ::= (#x20 | #x9 | #xD | #xA)+

				// If the XML file starts with a byte order mark, throw it away.
				// The earlier code for the kNone case has already used it to
				// set the default encoding.
				ParseChar(UnicodeChar(0xFEFF));

				if (BufferStartsWith("<?xml")) {
					if (! ParseXmlDeclaration()) return false;
					UnicodeString encodingName = GetAttribute("encoding");
					if (encodingName.empty()) return true;
					TextEncoding newEncoding = TextEncoding::WebCharset(encodingName.c_str());
					if (newEncoding == mConverter.GetSourceEncoding()) return true;

					// The encoding in the XML declaration is different from the one
					// we assumed, so we have to reset all the input buffering and
					// re-parse the XmlDeclaration.
					mConverter.Reset(newEncoding);
					mInput.Restart();
					mInputStart = mInputEnd = mInputBuffer;
					mOutputStart = mOutputEnd = mOutputBuffer;
					ParseChar(UnicodeChar(0xFEFF));
					return ParseXmlDeclaration();
				}
				else if (StartsWithWhitespace()) return ParseRequiredWhitespace();
				//else if (BufferStartsWith("<!--")) return ParseComment();
				//else if (BufferStartsWith("<?")) return ParseProcessingInstruction();
				//else if (BufferStartsWith("<!DOCTYPE")) return ParseDocumentType();
				else if (BufferStartsWith("<")) return ParseElement();
				else return false;

			case kXmlDeclaration:
			case kElement:
			case kEndElement:
			case kText:
		    case kWhitespace:
				if (BufferStartsWith("</")) return ParseEndElement();
				else if (BufferStartsWith("<")) return ParseElement();
				else return ParseText();
		}
		return false;
	}
ULONGLONG ZipArchiveFile::Seek(LONGLONG llOffset, ESeekOrigin origin)
{
   if (AtEndOfStream())
   {
      // seek beyond end of file
      return m_uiUncompressedSize;
   }

   // calc new position
   ULONGLONG ullNewPos = m_ullCurrentPos;
   switch (origin)
   {
   case seekBegin:
      ullNewPos = llOffset;
      break;

   case seekCurrent:
      ullNewPos += llOffset;

   case seekEnd:
      ullNewPos = ULONGLONG(m_uiUncompressedSize) - llOffset;
      break;

   default:
      ATLASSERT(false);
      break;
   }

   if (ullNewPos >= m_uiUncompressedSize)
   {
      // just seeked to end of file
      Close();
      return m_uiUncompressedSize;
   }

   // could be converted into rewind + forward skip
   if (ullNewPos < m_ullCurrentPos)
      throw Exception(_T("zip file archive stream can't be seeked backwards"), __FILE__, __LINE__);

   ULONGLONG ullBytesToSkip = ullNewPos - m_ullCurrentPos;

   if (ullBytesToSkip == 0)
      return m_ullCurrentPos;

   // skip over bytes
   do
   {
      // consume out buffer
      if (ullBytesToSkip < m_vecOutBuffer.size())
      {
         m_vecOutBuffer.erase(m_vecOutBuffer.begin(), m_vecOutBuffer.begin() + static_cast<size_t>(ullBytesToSkip));

         ullBytesToSkip = 0;
      }
      else
      if (ullBytesToSkip == m_vecOutBuffer.size())
      {
         m_vecOutBuffer.clear();
         ullBytesToSkip = 0;
      }
      else
      {
         // more than enough in buffer
         ullBytesToSkip -= m_vecOutBuffer.size();
         m_vecOutBuffer.clear();
      }

      // when not enough, decode more input
      if (ullBytesToSkip > 0)
      {
         FillInputBuffer();

         // read in at most 16k at a time
         DWORD dwBytesToRead = static_cast<DWORD>(std::min<ULONGLONG>(ullBytesToSkip, c_dwSkipBufferSize));

         FillOutBuffer(dwBytesToRead);
      }

   } while (ullBytesToSkip > 0);

   m_ullCurrentPos = ullNewPos;

   return m_ullCurrentPos;
}