zstreambuf::~zstreambuf() { switch( m_state ) { case STATE_DEFLATING: DeflateEnd(); break; case STATE_INFLATING: InflateEnd(); break; default: break; } }
void Inflate(FILE *input_file, FILE *output_file) { z_stream stream; InflateInit(&stream); int ret = Z_OK; do { stream.avail_in = fread(input_buf, 1, sizeof(input_buf), input_file); if (ferror(input_file) != 0) { ERROR("failed to read from file"); } if (stream.avail_in == 0) { // 入力が既に尽きている状態であれば,意図していないファイルの終端に // 到達したことになります. ERROR("unexpected end of file"); } stream.next_in = input_buf; do { // 出力バッファを再設定して伸長の続きをおこないます. stream.next_out = output_buf; stream.avail_out = sizeof(output_buf); ret = inflate(&stream, Z_NO_FLUSH); switch (ret) { case Z_NEED_DICT: { // 辞書がなければ伸長できないのでエラーにします. ERROR("%s", zError(Z_DATA_ERROR)); } case Z_STREAM_ERROR: case Z_DATA_ERROR: case Z_MEM_ERROR: { ERROR("%s", stream.msg); } } fwrite(output_buf, sizeof(output_buf) - stream.avail_out, 1, output_file); if (ferror(output_file) != 0) { ERROR("failed to write into file"); } // 一つのファイルに複数のデータが格納されているかもしれないので, // 返り値が Z_STREAM_END であっても,入力が残っている状態であれば, // 内部状態をリセットして伸長を継続します. if ((ret == Z_STREAM_END) && ((stream.avail_in != 0) || (feof(input_file) == 0))) { ret = inflateReset(&stream); if (ret != Z_OK) { ERROR("%s", zError(ret)); } stream.avail_out = 0; } } while ((stream.avail_out == 0) && (ret != Z_STREAM_END)); } while (ret != Z_STREAM_END); InflateEnd(&stream); }