009
20.08.2003, 17:47 Uhr
virtual
Sexiest Bit alive (Operator)
|
Leider ist der komplette Source etwas zu lang, um ihnim Forum zu posten. Ich poste mal die Auszüge, die meines Erachtens die für Dich wichtigen sind:
C++: |
/** Wrapper class for the zlib uncompression functions. * This is a small wrapper class for the low level function of the zlib to * uncompress data. The usage of this class is fairly simple: the constructor * expects two parameters that specify where to read the compressed data * (a STL istream object) and which format to be used. After that \ref begin() * must be called to start the uncompression. Then the uncompressed data can be * get using \ref uncompress(). The uncompression is finalized calling \ref * end(). * * \note If the input stream is noz capable of seeking, obey the following * restrictions: * The input must not consist of more than one data unit, and the * input must not comply to the format specified by RFC 1952. * In futires versions these restrictions might be dropped. * \note All methods sign errors by throwing \ref ZLibException. * * \sa ZLibCompressor, ZLibException */ class ZLibUncompressor { // === CONSTANTS ============================================================= public: /** Status information. * These constants define the different states of \ref ZLibUncompressor. * -# The instance is in \c IDLE state right after construction or after * \ref end() was called. The only valid action is to call \ref begin(). * -# If in \c UNCOMPRESSING state the next valid actions are \ref * uncompress() to extract more data from the compressed input or * \ref end() to end uncompression. * -# if in \c ENDOFSTREAM state the next valid action is \ref end(), * Since this state indicates the end of the current data unit. * -# If in \c ERROR state then something bad happened and the only valid * action is \ref end() to end the uncompression and cleanup. * One may get the current status using \ref getState() */ enum STATE { IDLE, UNCOMPRESSING, ENDOFSTREAM, ERROR };
// === ATTRIBUTES ============================================================ private: /** Internal buffer size. * This specifies the size of the buffer that temporarily keeps the data * when reading from input. A buffer of this size is assigned to * the \ref m_strmZ. The buffer is \ref m_pcBuffer. */ static const size_t c_nBufferSize = 4096;
/** Internal state. * This member contains the current status of the instance. It is one of * the \ref STATE constants. */ STATE m_nState; /** * Control structure for communication with the zlib. most of the zlib * function require a pointer to this structure, which contains information * where to read and where to write data. */ z_stream m_strmZ;
/** Control structuer for zlib. * This is a pointer to the input stream that contains the compressed * source data. It is set by the constructor. */ std::istream* m_pstrmIn;
/** Internal buffer. * This is the buffer that is temporarily used to store compressed input * data before reading it into the final destination buffer. The buffer * size is defined in \ref c_nBufferSize. A pointer to this buffer is * used in \ref m_strmZ. */ Bytef m_pcBuffer[c_nBufferSize];
/** RFC 1952 compliancy. * This flag indicates, whether the compressed input conforms to the RFC * 1952 and is compatible with the format written by gzip.If \c false, it * does not conform to that RFC and the zlib header is searched when * reading the input instead of the gzip header. The value of this flag * is set by the constructor. */ bool m_bGZIPFormat;
/** CRC checksum. * This contains the CRC of the data uncompressed so far. It is only * updated, if \ref m_bGZIPFormat is \c true */ uint32_t m_nCRC32;
... } ...
void ZLibUncompressor::readFromStream() { if (!m_pstrmIn->eof()) { m_pstrmIn->read(reinterpret_cast<char*>(m_pcBuffer), c_nBufferSize); m_strmZ.next_in = m_pcBuffer; m_strmZ.avail_in = m_pstrmIn->gcount();
if (!m_pstrmIn->eof() && !m_pstrmIn->good()) { m_nState = ERROR; throw ZLibException("stream problem: cannot read"); } } }
// ----------------------------------------------------------------------------
void ZLibUncompressor::readTrailer() { uint32_t nCRC32; uint32_t nSize;
m_pstrmIn->read(reinterpret_cast<char*>(&nCRC32), sizeof(nCRC32)); m_pstrmIn->read(reinterpret_cast<char*>(&nSize), sizeof(nSize));
try { if (!m_pstrmIn->good()) { m_nState = ERROR; throw ZLibException("stream problem: cannot read"); } if (nCRC32 != m_nCRC32) { m_nState = ERROR; throw ZLibException("CRC checksum incorrect"); } if (nSize != m_strmZ.total_out) { m_nState = ERROR; throw ZLibException("size differs from expected size"); } } catch (std::exception& ex) { std::cerr<<ex.what()<<std::endl; throw; } }
// ----------------------------------------------------------------------------
void ZLibUncompressor::begin() { int nReturn = Z_OK;
// // Check state // if (IDLE != m_nState) throw ZLibException("Bad sequence: not in IDLE state."); // // Init zlib // std::memset(&m_strmZ, 0, sizeof(m_strmZ)); nReturn = inflateInit2(&m_strmZ, m_bGZIPFormat? -15:15); if (Z_OK != nReturn) { if (m_strmZ.msg) throw ZLibException(m_strmZ.msg); else throw ZLibException(nReturn); } m_nCRC32 = 0; m_strUnitName = ""; m_nState = UNCOMPRESSING;
// // fetch header information, if requested // if (m_bGZIPFormat) { readHeader(); }
}
// ----------------------------------------------------------------------------
size_t ZLibUncompressor::uncompress( char* p_pcOutput, size_t p_nLen) { int nReturn = Z_OK;
// // Check state // if (UNCOMPRESSING!=m_nState && ENDOFSTREAM!=m_nState) throw ZLibException("Bad sequence: neither UNCOMPRESSING " "nor ENDOFSTREAM state.");
// // Set up output buffer // m_strmZ.next_out = reinterpret_cast<Bytef*>(const_cast<char*>(p_pcOutput)); m_strmZ.avail_out = p_nLen;
// // Loop until everything is uncompressed or out buffer full // while (m_strmZ.avail_out>0 && ENDOFSTREAM!=m_nState) { // // If no input is available, get new // if (0==m_strmZ.avail_in) { if (m_pstrmIn->eof()) { m_nState = ERROR; throw ZLibException("unexpected end of file"); } readFromStream(); }
// // Decompress next portion, if not end of stream // if (ENDOFSTREAM != m_nState) { nReturn = inflate(&m_strmZ, Z_NO_FLUSH); if (Z_OK != nReturn) { m_nState = nReturn==Z_STREAM_END? ENDOFSTREAM:ERROR; if (ERROR == m_nState) { if (m_strmZ.msg) throw ZLibException(m_strmZ.msg); else throw ZLibException(nReturn); }else { m_pstrmIn->clear(); } } } }
// // Update CRC, if requested // if (m_bGZIPFormat) { m_nCRC32 = crc32(m_nCRC32, reinterpret_cast<Bytef*>(p_pcOutput), p_nLen-m_strmZ.avail_out); }
return p_nLen-m_strmZ.avail_out; }
// ----------------------------------------------------------------------------
void ZLibUncompressor::end() { if (IDLE == m_nState) throw ZLibException("Bad sequence: in IDLE state.");
// // seek to the real end of uncompressed data (we might fetched some // bytes too much) // m_pstrmIn->seekg(-m_strmZ.avail_in, std::ios::cur); m_strmZ.next_in = NULL; m_strmZ.avail_in = 0; // // Check trailer (makes sense only in case that state is ENDOFSTREAM // try { if (ENDOFSTREAM==m_nState && m_bGZIPFormat) { readTrailer(); } } catch (...) { inflateEnd(&m_strmZ); m_nState = IDLE; throw; }
// // Finish decompression // int nReturn = inflateEnd(&m_strmZ); m_nState = IDLE; if (Z_OK != nReturn) { if (m_strmZ.msg) throw ZLibException(m_strmZ.msg); else throw ZLibException(nReturn); }
}
|
-- Gruß, virtual Quote of the Month Ich eß' nur was ein Gesicht hat (Creme 21) |