00001 00032 #include "stdafx.h" 00033 #include "CPipeInflate.h" 00034 00035 // Can't use this for convenient notation below: 00036 // using AxPipe::Stock::CPipeInflate; 00037 // because the Doxygen get's confused. 00038 00039 namespace AxPipe { 00040 namespace Stock { 00042 CPipeInflate::CPipeInflate() { 00043 m_pOutSeg = NULL; 00044 m_cb = 0; 00045 ZeroMemory(&m_Zstream, sizeof m_Zstream); 00046 } 00047 00050 CPipeInflate::~CPipeInflate() { 00051 if (m_pOutSeg) { 00052 m_pOutSeg->Release(); 00053 } 00054 } 00055 00058 bool 00059 CPipeInflate::OutOpen() { 00060 bool fReturn = CPipe::OutOpen(); // Open base first, like constructor 00061 m_cb = 0; // Total output bytes counter 00062 ZeroMemory(&m_Zstream, sizeof m_Zstream); 00063 m_Zstream.next_in = Z_NULL; // Defer check to first call to inflate 00064 m_Zstream.zalloc = Z_NULL; // Use default alloc() 00065 m_Zstream.zfree = Z_NULL; // Use default free() 00066 00067 if (inflateInit(&m_Zstream) != Z_OK) { 00068 SetError(ERROR_CODE_STOCK, _T("ZLIB initialization error")); 00069 } 00070 ASSCHK(m_pOutSeg == NULL, _T("CPipeInflate::OutOpen() [m_pOutSeg non-NULL]")); 00071 00072 return fReturn; // Return the saved return code. 00073 } 00074 00077 bool 00078 CPipeInflate::OutClose() { 00079 // This is a safety first measure, should not really be needed. 00080 if (m_pOutSeg) { 00081 m_pOutSeg->Release(); 00082 m_pOutSeg = NULL; 00083 } 00084 return CPipe::OutClose(); // End by closing base, like destructor 00085 } 00086 00093 void 00094 CPipeInflate::Out(AxPipe::CSeg *pSeg) { 00095 m_Zstream.next_in = (unsigned char *)pSeg->PtrRd(); 00096 m_Zstream.avail_in = (UINT)pSeg->Len(); 00097 while (true) { 00098 if (!m_pOutSeg) { 00099 // Allocate the output segment, and point the Zstream structure to it 00100 m_pOutSeg = GetSeg(m_Zstream.avail_in + m_Zstream.avail_in); 00101 ASSPTR(m_pOutSeg); 00102 m_Zstream.avail_out = (UINT)m_pOutSeg->Size(); 00103 m_Zstream.next_out = m_pOutSeg->PtrWr(); 00104 } 00105 int iZerror = inflate(&m_Zstream, 0); 00106 m_cb += m_Zstream.total_out; // Update total output bytes ctr 00107 m_Zstream.total_out = 0; // can't use total_out since it's 32-bit 00108 switch (iZerror) { 00109 case Z_OK: 00110 // ZLib guarantees to either use all input or all output buffer. 00111 if (m_Zstream.avail_in && m_Zstream.avail_out) { 00112 SetError(ERROR_CODE_DERIVED, _T("ZLIB sequence error")); 00113 } 00114 if (!m_Zstream.avail_out) { 00115 Pump(m_pOutSeg); 00116 m_pOutSeg = NULL; 00117 } 00118 if (m_Zstream.avail_in) { 00119 continue; // More data to inflate! 00120 } 00121 // If we have no more input, we need to return and wait for more 00122 break; 00123 case Z_STREAM_END: 00124 m_pOutSeg->Len(m_pOutSeg->Size() - m_Zstream.avail_out); 00125 Pump(m_pOutSeg); 00126 m_pOutSeg = NULL; 00127 if (m_Zstream.avail_in) { 00128 SetError(ERROR_CODE_STOCK, _T("Trailing data")); 00129 } 00130 break; 00131 default: 00132 SetError(ERROR_CODE_STOCK, _T("ZLIB inflate error")); 00133 break; 00134 } 00135 break; 00136 } 00137 pSeg->Release(); 00138 } 00139 } 00140 }