jigdo API
Last update by Admin on 2010-05-23
util/gunzip.hh
Go to the documentation of this file.00001 /* $Id: gunzip.hh,v 1.4 2003/06/24 13:55:07 richard Exp $ -*- C++ -*- 00002 __ _ 00003 |_) /| Copyright (C) 2003 | richard@ 00004 | \/¯| Richard Atterer | atterer.net 00005 ¯ '` ¯ 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License, version 2. See 00008 the file COPYING for details. 00009 00010 */ 00016 #ifndef GUNZIP_HH 00017 #define GUNZIP_HH 00018 00019 #include <config.h> 00020 00021 #include <string> 00022 #include <zlib.h> 00023 00024 #include <debug.hh> 00025 00026 #ifdef TRANSPARENT 00027 # undef TRANSPARENT 00028 #endif 00029 #ifdef ERROR 00030 # undef ERROR 00031 #endif 00032 //______________________________________________________________________ 00033 00048 class Gunzip { 00049 public: 00050 //________________________________________ 00051 00055 class IO { 00056 public: 00057 00058 virtual ~IO() { } 00059 00063 virtual void gunzip_deleted() = 0; 00064 00069 virtual void gunzip_data(Gunzip* self, byte* decompressed, 00070 unsigned size) = 0; 00071 00075 virtual void gunzip_needOut(Gunzip* self) = 0; 00076 00078 //virtual void gunzip_succeeded() = 0; 00079 00083 virtual void gunzip_failed(string* message) = 0; 00084 }; 00085 //________________________________________ 00086 00089 class IOPtr { // cf. job.hh 00090 public: 00091 IOPtr(IO* io) : ptr(io) { } 00092 ~IOPtr() { ptr->gunzip_deleted(); } 00093 00094 IO& operator*() const throw() { return *ptr; } 00095 IO* operator->() const throw() { return ptr; } 00096 operator bool() const throw() { return ptr != 0; } 00097 IO* get() const throw() { return ptr; } 00100 void set(IO* io) { 00101 if (ptr == io) return; 00102 if (ptr != 0) ptr->gunzip_deleted(); 00103 ptr = io; 00104 } 00105 private: 00106 IO* ptr; 00107 }; 00108 IOPtr io; 00109 //________________________________________ 00110 00111 Gunzip(IO* ioPtr); 00112 00113 virtual ~Gunzip(); 00114 00117 void inject(const byte* compressed, unsigned size); 00118 00121 inline byte* nextOut() const; 00122 00124 inline unsigned availOut() const; 00125 00129 inline void setOut(byte* newNextOut, unsigned newAvailOut); 00130 00131 private: 00132 // Pass zlib error to IO object 00133 void error(const char* msg); 00134 // Ensure that at least one output byte is writable in z.next_out/avail_out 00135 inline void needOutByte(); 00136 // Advance z.next_in/z.avail_in by one byte & return it 00137 inline byte nextInByte(); 00138 // Output a single byte. Calls needOutByte() and io->data(this,...,1) 00139 inline void outputByte(byte b); 00140 00141 /* zlib doesn't support in-memory decompression of .gz files, only of zlib 00142 streams, so we need to extract the zlib stream from the .gz file. Keep 00143 track of our progress in a state var. */ 00144 enum { 00145 INIT0, // Guessing whether or not .gz format: First two bytes \x1f \x8b 00146 INIT1, 00147 HEADER_CM, // .gz header: compression method byte 00148 HEADER_FLG, // .gz header: flag byte 00149 HEADER_FEXTRA0, // .gz header: optional extra fields 00150 HEADER_FEXTRA1, 00151 HEADER_FNAME, // .gz header: Original file name 00152 HEADER_FCOMMENT, // .gz header: Comment field 00153 ZLIB, // Found zlib stream, pass to zlib 00154 TRAILER_CRC0, // Checksum of uncompressed data, after zlib data 00155 TRAILER_CRC1, 00156 TRAILER_CRC2, 00157 TRAILER_CRC3, 00158 TRANSPARENT, // Final state: Not .gz format, pass to IO unmodified 00159 ERROR // Final state: zlib error or error in .gz header 00160 }; 00161 int state; 00162 byte headerFlags; 00163 z_stream z; 00164 unsigned skip; // Nr of bytes to ignore in input stream 00165 unsigned data; // to accumulate parameters from the stream 00166 uLong crc; // CRC32 checksum of uncompressed data 00167 }; 00168 //______________________________________________________________________ 00169 00170 byte* Gunzip::nextOut() const { 00171 return z.next_out; 00172 } 00173 00174 unsigned Gunzip::availOut() const { 00175 return z.avail_out; 00176 } 00177 00178 void Gunzip::setOut(byte* newNextOut, unsigned newAvailOut) { 00179 z.next_out = newNextOut; 00180 z.avail_out = newAvailOut; 00181 } 00182 00183 void Gunzip::needOutByte() { 00184 if (availOut() == 0) { 00185 io->gunzip_needOut(this); 00186 Paranoid(availOut() > 0); 00187 } 00188 } 00189 00190 void Gunzip::outputByte(byte b) { 00191 needOutByte(); 00192 *z.next_out = b; 00193 --z.avail_out; 00194 ++z.next_out; 00195 io->gunzip_data(this, z.next_out - 1, 1); 00196 } 00197 00198 byte Gunzip::nextInByte() { 00199 byte result = *z.next_in; 00200 ++z.next_in; 00201 --z.avail_in; 00202 return result; 00203 } 00204 00205 #endif
Generated on Tue Sep 23 14:27:41 2008 for jigdo by
