CCompressionProcessor::EStatus CZipCompressor::Finish( char* out_buf, size_t out_size, /* out */ size_t* out_avail) { *out_avail = 0; if ( !out_size ) { return eStatus_Overflow; } LIMIT_SIZE_PARAM_U(out_size); // Default behavior on empty data -- don't write header/footer if ( !GetProcessedSize() && !F_ISSET(fAllowEmptyData) ) { return eStatus_EndOfData; } // Write gzip file header if not done yet size_t header_len = 0; if ( F_ISSET(fWriteGZipFormat) && m_NeedWriteHeader ) { header_len = s_WriteGZipHeader(out_buf, out_size, &m_FileInfo); if (!header_len) { SetError(-1, "Cannot write gzip header"); return eStatus_Overflow; } // IncreaseOutputSize() // -- will be called below, and it will count 'header_len' m_NeedWriteHeader = false; } // Finish compression STREAM->next_in = 0; STREAM->avail_in = 0; STREAM->next_out = (unsigned char*)out_buf + header_len; STREAM->avail_out = (unsigned int)(out_size - header_len); int errcode = deflate(STREAM, Z_FINISH); SetError(errcode, zError(errcode)); *out_avail = out_size - STREAM->avail_out; IncreaseOutputSize((unsigned long)(*out_avail)); switch (errcode) { case Z_OK: return eStatus_Overflow; case Z_STREAM_END: // Write .gz file footer if ( F_ISSET(fWriteGZipFormat) ) { size_t footer_len = s_WriteGZipFooter(out_buf + *out_avail, STREAM->avail_out, GetProcessedSize(), m_CRC32); if ( !footer_len ) { SetError(-1, "Cannot write gzip footer"); return eStatus_Overflow; } IncreaseOutputSize((unsigned long)footer_len); *out_avail += footer_len; } return eStatus_EndOfData; } ERR_COMPRESS(66, FormatErrorMessage("CZipCompressor::Finish", GetProcessedSize())); return eStatus_Error; }
CCompressionProcessor::EStatus CZipCompressor::Process( const char* in_buf, size_t in_len, char* out_buf, size_t out_size, /* out */ size_t* in_avail, /* out */ size_t* out_avail) { *out_avail = 0; if (in_len > kMax_UInt) { SetError(Z_STREAM_ERROR, "size of the source buffer is too big"); ERR_COMPRESS(61, FormatErrorMessage("CZipCompressor::Process", GetProcessedSize())); return eStatus_Error; } if ( !out_size ) { return eStatus_Overflow; } LIMIT_SIZE_PARAM_U(out_size); size_t header_len = 0; // Write gzip file header if ( F_ISSET(fWriteGZipFormat) && m_NeedWriteHeader ) { header_len = s_WriteGZipHeader(out_buf, out_size, &m_FileInfo); if (!header_len) { SetError(-1, "Cannot write gzip header"); ERR_COMPRESS(62, FormatErrorMessage("CZipCompressor::Process", GetProcessedSize())); return eStatus_Error; } m_NeedWriteHeader = false; } STREAM->next_in = (unsigned char*)const_cast<char*>(in_buf); STREAM->avail_in = (unsigned int)in_len; STREAM->next_out = (unsigned char*)out_buf + header_len; STREAM->avail_out = (unsigned int)(out_size - header_len); int errcode = deflate(STREAM, Z_NO_FLUSH); SetError(errcode, zError(errcode)); *in_avail = STREAM->avail_in; *out_avail = out_size - STREAM->avail_out; IncreaseProcessedSize((unsigned long)(in_len - *in_avail)); IncreaseOutputSize((unsigned long)(*out_avail)); // If we writing in gzip file format if ( F_ISSET(fWriteGZipFormat) ) { // Update the CRC32 for processed data m_CRC32 = crc32(m_CRC32, (unsigned char*)in_buf, (unsigned int)(in_len - *in_avail)); } if ( errcode == Z_OK ) { return eStatus_Success; } ERR_COMPRESS(63, FormatErrorMessage("CZipCompressor::Process", GetProcessedSize())); return eStatus_Error; }
float SpectrumAnalyst::GetProcessedValue(float freq0, float freq1) const { float bin0, bin1, binwidth; if (mAlg == Spectrum) { bin0 = freq0 * mWindowSize / mRate; bin1 = freq1 * mWindowSize / mRate; } else { bin0 = freq0 * mRate; bin1 = freq1 * mRate; } binwidth = bin1 - bin0; float value = float(0.0); if (binwidth < 1.0) { float binmid = (bin0 + bin1) / 2.0; int ibin = (int)(binmid) - 1; if (ibin < 1) ibin = 1; if (ibin >= GetProcessedSize() - 3) ibin = std::max(0, GetProcessedSize() - 4); value = CubicInterpolate(mProcessed[ibin], mProcessed[ibin + 1], mProcessed[ibin + 2], mProcessed[ibin + 3], binmid - ibin); } else { if (bin0 < 0) bin0 = 0; if (bin1 >= GetProcessedSize()) bin1 = GetProcessedSize() - 1; if ((int)(bin1) > (int)(bin0)) value += mProcessed[(int)(bin0)] * ((int)(bin0) + 1 - bin0); bin0 = 1 + (int)(bin0); while (bin0 < (int)(bin1)) { value += mProcessed[(int)(bin0)]; bin0 += 1.0; } value += mProcessed[(int)(bin1)] * (bin1 - (int)(bin1)); value /= binwidth; } return value; }
CCompressionProcessor::EStatus CZipCompressor::Flush( char* out_buf, size_t out_size, /* out */ size_t* out_avail) { *out_avail = 0; if ( !out_size ) { return eStatus_Overflow; } LIMIT_SIZE_PARAM_U(out_size); STREAM->next_in = 0; STREAM->avail_in = 0; STREAM->next_out = (unsigned char*)out_buf; STREAM->avail_out = (unsigned int)out_size; int errcode = deflate(STREAM, Z_SYNC_FLUSH); SetError(errcode, zError(errcode)); *out_avail = out_size - STREAM->avail_out; IncreaseOutputSize((unsigned long)(*out_avail)); if ( errcode == Z_OK || errcode == Z_BUF_ERROR ) { if ( STREAM->avail_out == 0) { return eStatus_Overflow; } return eStatus_Success; } ERR_COMPRESS(64, FormatErrorMessage("CZipCompressor::Flush", GetProcessedSize())); return eStatus_Error; }
CCompressionProcessor::EStatus CZipCompressor::Init(void) { if ( IsBusy() ) { // Abnormal previous session termination End(); } // Initialize members Reset(); SetBusy(); m_CRC32 = 0; m_NeedWriteHeader = true; m_Cache.erase(); // Initialize the compressor stream structure memset(STREAM, 0, sizeof(z_stream)); // Create a compressor stream int errcode = deflateInit2_(STREAM, GetLevel(), Z_DEFLATED, F_ISSET(fWriteGZipFormat) ? -m_WindowBits : m_WindowBits, m_MemLevel, m_Strategy, ZLIB_VERSION, (int)sizeof(z_stream)); SetError(errcode, zError(errcode)); if ( errcode == Z_OK ) { return eStatus_Success; } ERR_COMPRESS(60, FormatErrorMessage("CZipCompressor::Init", GetProcessedSize())); return eStatus_Error; }
CCompressionProcessor::EStatus CZipDecompressor::Init(void) { // Initialize members Reset(); SetBusy(); m_NeedCheckHeader = true; m_IsGZ = false; m_SkipInput = 0; m_Cache.erase(); m_Cache.reserve(kMaxHeaderSize); // Initialize the compressor stream structure memset(STREAM, 0, sizeof(z_stream)); // Create a compressor stream int errcode = inflateInit2_(STREAM, m_WindowBits, ZLIB_VERSION, (int)sizeof(z_stream)); SetError(errcode, zError(errcode)); if ( errcode == Z_OK ) { return eStatus_Success; } ERR_COMPRESS(68, FormatErrorMessage("CZipDecompressor::Init", GetProcessedSize())); return eStatus_Error; }
float SpectrumAnalyst::FindPeak(float xPos, float *pY) const { float bestpeak = 0.0f; float bestValue = 0.0; if (GetProcessedSize() > 1) { bool up = (mProcessed[1] > mProcessed[0]); float bestdist = 1000000; for (int bin = 3; bin < GetProcessedSize() - 1; bin++) { bool nowUp = mProcessed[bin] > mProcessed[bin - 1]; if (!nowUp && up) { // Local maximum. Find actual value by cubic interpolation int leftbin = bin - 2; /* if (leftbin < 1) leftbin = 1; */ float valueAtMax = 0.0; float max = leftbin + CubicMaximize(mProcessed[leftbin], mProcessed[leftbin + 1], mProcessed[leftbin + 2], mProcessed[leftbin + 3], &valueAtMax); float thispeak; if (mAlg == Spectrum) thispeak = max * mRate / mWindowSize; else thispeak = max / mRate; if (fabs(thispeak - xPos) < bestdist) { bestpeak = thispeak; bestdist = fabs(thispeak - xPos); bestValue = valueAtMax; // Should this test come after the enclosing if? if (thispeak > xPos) break; } } up = nowUp; } } if (pY) *pY = bestValue; return bestpeak; }
CCompressionProcessor::EStatus CZipDecompressor::End(int abandon) { int errcode = inflateEnd(STREAM); SetBusy(false); if ( abandon || m_DecompressMode == eMode_TransparentRead || errcode == Z_OK ) { return eStatus_Success; } ERR_COMPRESS(71, FormatErrorMessage("CZipDecompressor::End", GetProcessedSize())); return eStatus_Error; }
CCompressionProcessor::EStatus CZipCompressor::End(int abandon) { int errcode = deflateEnd(STREAM); SetBusy(false); if (abandon) { // Ignore result of deflateEnd(), because it can return an error code for empty data return eStatus_Success; } SetError(errcode, zError(errcode)); if ( errcode == Z_OK ) { return eStatus_Success; } ERR_COMPRESS(67, FormatErrorMessage("CZipCompressor::End", GetProcessedSize())); return eStatus_Error; }
CCompressionProcessor::EStatus CZipDecompressor::Finish( char* out_buf, size_t out_size, size_t* out_avail) { if (m_DecompressMode == eMode_TransparentRead) { return eStatus_EndOfData; } // Do not check here on eMode_Unknown. It will be processed below. size_t in_avail; // Process only if we have some data -- otherwise zlib return error CCompressionProcessor::EStatus status = eStatus_Success; if ( GetProcessedSize() || m_Cache.size() ) { status = Process(0, 0, out_buf, out_size, &in_avail, out_avail); } if (status == eStatus_Success && *out_avail == 0) { // Possible case with .gz files only (check on concatenated files) return eStatus_EndOfData; } return status; }
CCompressionProcessor::EStatus CZipDecompressor::Process( const char* in_buf, size_t in_len, char* out_buf, size_t out_size, /* out */ size_t* in_avail, /* out */ size_t* out_avail) { *out_avail = 0; if (in_len > kMax_UInt) { SetError(Z_STREAM_ERROR, "size of the source buffer is too big"); ERR_COMPRESS(69, FormatErrorMessage("CZipDecompressor::Process", GetProcessedSize())); return eStatus_Error; } if ( !out_size ) { return eStatus_Overflow; } LIMIT_SIZE_PARAM_U(out_size); // By default we consider that data is compressed if ( m_DecompressMode == eMode_Unknown && !F_ISSET(fAllowTransparentRead) ) { m_DecompressMode = eMode_Decompress; } char* x_in_buf = const_cast<char*>(in_buf); size_t x_in_len = in_len; // If data is compressed, or the read mode is undefined yet if ( m_DecompressMode != eMode_TransparentRead ) { // Need to skip some bytes from input stream? // (in case of concatenated .gz files only) if ( m_SkipInput ) { // Skip from cache if present if ( m_Cache.size() ) { size_t n = min(m_Cache.size(), m_SkipInput); m_Cache.erase(0, n); m_SkipInput -= n; IncreaseProcessedSize((unsigned long)n); } // And/or from input stream also if ( m_SkipInput ) { size_t n = min(x_in_len, m_SkipInput); x_in_buf += n; x_in_len -= n; m_SkipInput -= n; IncreaseProcessedSize((unsigned long)n); if ( m_SkipInput ) { // Data block is very small... and was skipped. *in_avail = x_in_len; *out_avail = 0; return eStatus_Success; } } } bool from_cache = false; size_t old_avail_in = 0; // Check file header if ( F_ISSET(fCheckFileHeader) ) { size_t header_len = 0; if ( m_NeedCheckHeader ) { if (!x_in_buf && !m_Cache.size()) { // Possible Flush(), but we should refill the cache // to perform header check -- so, just ignore. *in_avail = 0; *out_avail = 0; return eStatus_Success; } if (x_in_buf && m_Cache.size() < kMaxHeaderSize) { size_t n = min(kMaxHeaderSize - m_Cache.size(), x_in_len); m_Cache.append(x_in_buf, n); x_in_buf += n; x_in_len -= n; if (m_Cache.size() < kMaxHeaderSize) { // Data block is very small and was fully cached. *in_avail = 0; *out_avail = 0; return eStatus_Success; } } // Check gzip header in the buffer header_len = s_CheckGZipHeader(m_Cache.data(), m_Cache.size()); _ASSERT(header_len < kMaxHeaderSize); // If gzip header found, skip it if ( header_len ) { m_Cache.erase(0, header_len); IncreaseProcessedSize((unsigned long)header_len); m_DecompressMode = eMode_Decompress; m_IsGZ = true; } // Reinit decompression stream inflateEnd(STREAM); int errcode = inflateInit2_(STREAM, m_IsGZ ? -m_WindowBits : m_WindowBits, ZLIB_VERSION, (int)sizeof(z_stream)); SetError(errcode, zError(errcode)); if ( errcode != Z_OK ) { return eStatus_Error; } // Already skipped, or we don't have header here m_NeedCheckHeader = false; } } // Prepare STREAM for decompressing if ( m_Cache.size() ) { // Possible, we have some unprocessed data in the cache STREAM->next_in = (unsigned char*)(m_Cache.data()); STREAM->avail_in = (unsigned int)m_Cache.size(); STREAM->next_out = (unsigned char*)out_buf; STREAM->avail_out = (unsigned int)out_size; from_cache = true; old_avail_in = STREAM->avail_in; // = m_Cache.size() } else { STREAM->next_in = (unsigned char*)x_in_buf; STREAM->avail_in = (unsigned int)x_in_len; STREAM->next_out = (unsigned char*)out_buf; STREAM->avail_out = (unsigned int)out_size; } // Try to decompress data int errcode = inflate(STREAM, Z_SYNC_FLUSH); if ( m_DecompressMode == eMode_Unknown ) { // The flag fAllowTransparentRead is set _ASSERT(F_ISSET(fAllowTransparentRead)); // Determine decompression mode for following operations if (errcode == Z_OK || errcode == Z_STREAM_END) { m_DecompressMode = eMode_Decompress; } else { m_DecompressMode = eMode_TransparentRead; } } if ( m_DecompressMode == eMode_Decompress ) { SetError(errcode, zError(errcode)); // Concatenated file? Try to process next .gz chunk, if present if ((errcode == Z_STREAM_END) && m_IsGZ) { // Skip .gz file footer (8 bytes) if (STREAM->avail_in < 8) { m_SkipInput = 8 - STREAM->avail_in; STREAM->avail_in = 0; } else { STREAM->avail_in -= 8; } if ( F_ISSET(fAllowConcatenatedGZip) ) { m_NeedCheckHeader = true; errcode = Z_OK; } } // Update count of processed data if ( from_cache ) { m_Cache.erase(0, old_avail_in - STREAM->avail_in); *in_avail = x_in_len; IncreaseProcessedSize((unsigned long)(old_avail_in - STREAM->avail_in)); } else { *in_avail = STREAM->avail_in; IncreaseProcessedSize((unsigned long)(x_in_len - *in_avail)); x_in_len = *in_avail; } // In case of concatenated .gz files: // Possible, we already skipped some bytes from cache, // and it should be empty now. If needed, try to skip some // bytes from the input stream also. if ( m_SkipInput ) { _ASSERT(m_Cache.size() == 0); size_t n = min(x_in_len, m_SkipInput); if ( n ) { x_in_len -= n; m_SkipInput -= n; *in_avail = x_in_len; IncreaseProcessedSize((unsigned long)n); } } *out_avail = out_size - STREAM->avail_out; IncreaseOutputSize((unsigned long)(*out_avail)); // Analyze decompressor status switch (errcode) { case Z_OK: if ( from_cache && STREAM->avail_in > 0 && *out_avail == 0) { return m_NeedCheckHeader ? eStatus_Repeat : eStatus_Overflow; } return eStatus_Success; case Z_STREAM_END: return eStatus_EndOfData; } ERR_COMPRESS(70, FormatErrorMessage("CZipDecompressor::Process", GetProcessedSize())); return eStatus_Error; } /* else: eMode_ThansparentRead (see below) */ } // Transparent read _ASSERT(m_DecompressMode == eMode_TransparentRead); size_t total = 0; if ( m_Cache.size() ) { total = min(m_Cache.size(), out_size); memcpy(out_buf, m_Cache.data(), total); m_Cache.erase(0, total); out_size -= total; } if (x_in_len && out_size) { size_t n = min(x_in_len, out_size); memcpy(out_buf + total, x_in_buf, n); total += n; x_in_len -= n; } *in_avail = x_in_len; *out_avail = total; IncreaseProcessedSize((unsigned long)total); IncreaseOutputSize((unsigned long)total); return eStatus_Success; }