Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights reserved. 2 // See the file tools.license for terms. 3 4 #ifndef toolx_zlib 5 #define toolx_zlib 6 7 // what is needed for root file compression with zlib. 8 9 //NOTE : zlib contains deflate/inflate and also the gz functions to write/read a .gz file. 10 // The gz functions use also deflate/inflate. 11 12 #include <zlib.h> 13 14 #include <ostream> 15 16 namespace toolx { 17 18 inline bool compress_buffer(std::ostream& a_out, 19 unsigned int a_level, 20 unsigned int a_srcsize,const char* a_src, 21 unsigned int a_tgtsize,char* a_tgt, 22 unsigned int& a_irep) { 23 24 z_stream stream; // decompression stream 25 26 stream.next_in = (Bytef*)(a_src); 27 stream.avail_in = (uInt)(a_srcsize); 28 stream.next_out = (Bytef*)a_tgt; 29 stream.avail_out = (uInt)(a_tgtsize); 30 stream.zalloc = (alloc_func)0; 31 stream.zfree = (free_func)0; 32 stream.opaque = (voidpf)0; 33 stream.total_in = 0; /*to quiet Coverity.*/ 34 stream.total_out = 0; /*to quiet Coverity.*/ 35 36 int err = deflateInit(&stream,a_level); 37 if(err!=Z_OK) { 38 a_out << "toolx::compress_buffer :" 39 << " error in zlib/deflateInit." << std::endl; 40 a_irep = 0; 41 return false; 42 } 43 44 err = deflate(&stream, Z_FINISH); 45 if(err!=Z_STREAM_END) { 46 deflateEnd(&stream); 47 a_out << "toolx::compress_buffer :" 48 << " error in zlib/deflate." << std::endl; 49 a_irep = 0; 50 return false; 51 } 52 53 deflateEnd(&stream); 54 55 //a_out << "toolx::compress_buffer : ok " 56 // << stream.total_out << std::endl; 57 58 a_irep = (unsigned)stream.total_out; 59 60 return true; 61 } 62 63 inline bool decompress_buffer(std::ostream& a_out, 64 unsigned int a_srcsize,const char* a_src, 65 unsigned int a_tgtsize,char* a_tgt, 66 unsigned int& a_irep) { 67 68 z_stream stream; // decompression stream 69 70 stream.next_in = (Bytef*)(a_src); 71 stream.avail_in = (uInt)(a_srcsize); 72 stream.next_out = (Bytef*)a_tgt; 73 stream.avail_out = (uInt)(a_tgtsize); 74 stream.zalloc = (alloc_func)0; 75 stream.zfree = (free_func)0; 76 stream.opaque = (voidpf)0; 77 stream.total_in = 0; /*to quiet Coverity.*/ 78 stream.total_out = 0; /*to quiet Coverity.*/ 79 80 int err = inflateInit(&stream); 81 if (err != Z_OK) { 82 a_out << "toolx::decompress_buffer :" 83 << " error " << err << " in zlib/inflateInit." << std::endl; 84 return false; 85 } 86 87 err = inflate(&stream, Z_FINISH); 88 if (err != Z_STREAM_END) { 89 inflateEnd(&stream); 90 a_out << "toolx::decompress_buffer :" 91 << " error " << err << " in zlib/inflate." << std::endl; 92 return false; 93 } 94 95 inflateEnd(&stream); 96 97 //a_out << "toolx::decompress_buffer : zlib : ok " 98 // << stream.total_out << std::endl; 99 100 a_irep = (unsigned)stream.total_out; 101 102 return true; 103 } 104 105 } 106 107 #if ZLIB_VERNUM <= 0x1140 108 #include <cstdio> 109 #endif 110 111 namespace toolx { 112 113 #if ZLIB_VERNUM <= 0x1140 114 inline int gunzip_get_byte(char*& a_buffer) { 115 int c = *a_buffer;a_buffer++; 116 return c; 117 } 118 119 inline int gunzip_check_header(char*& a_buffer) { 120 #define TOOLX_ZLIB_HEAD_CRC 0x02 /* bit 1 set: header CRC present */ 121 #define TOOLX_ZLIB_EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ 122 #define TOOLX_ZLIB_ORIG_NAME 0x08 /* bit 3 set: original file name present */ 123 #define TOOLX_ZLIB_COMMENT 0x10 /* bit 4 set: file comment present */ 124 #define TOOLX_ZLIB_RESERVED 0xE0 /* bits 5..7: reserved */ 125 126 uInt len; 127 int c; 128 129 /* Check the gzip magic header */ 130 for (len = 0; len < 2; len++) { 131 c = gunzip_get_byte(a_buffer); 132 /* 133 if (c != gz_magic[len]) { 134 if (len != 0) s->stream.avail_in++, s->stream.next_in--; 135 if (c != EOF) { 136 s->stream.avail_in++, s->stream.next_in--; 137 s->transparent = 1; 138 } 139 s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END; 140 return; 141 } 142 */ 143 } 144 int method = gunzip_get_byte(a_buffer); 145 int flags = gunzip_get_byte(a_buffer); 146 if (method != Z_DEFLATED || (flags & TOOLX_ZLIB_RESERVED) != 0) { 147 return Z_DATA_ERROR; 148 } 149 150 /* Discard time, xflags and OS code: */ 151 for (len = 0; len < 6; len++) (void)gunzip_get_byte(a_buffer); 152 153 if ((flags & TOOLX_ZLIB_EXTRA_FIELD) != 0) { /* skip the extra field */ 154 len = (uInt)gunzip_get_byte(a_buffer); 155 len += ((uInt)gunzip_get_byte(a_buffer))<<8; 156 /* len is garbage if EOF but the loop below will quit anyway */ 157 while (len-- != 0 && gunzip_get_byte(a_buffer) != EOF) ; 158 } 159 if ((flags & TOOLX_ZLIB_ORIG_NAME) != 0) { /* skip the original file name */ 160 while ((c = gunzip_get_byte(a_buffer)) != 0 && c != EOF) ; 161 } 162 if ((flags & TOOLX_ZLIB_COMMENT) != 0) { /* skip the .gz file comment */ 163 while ((c = gunzip_get_byte(a_buffer)) != 0 && c != EOF) ; 164 } 165 if ((flags & TOOLX_ZLIB_HEAD_CRC) != 0) { /* skip the header crc */ 166 for (len = 0; len < 2; len++) (void)gunzip_get_byte(a_buffer); 167 } 168 //s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; 169 return Z_OK; 170 171 #undef TOOLX_ZLIB_HEAD_CRC 172 #undef TOOLX_ZLIB_EXTRA_FIELD 173 #undef TOOLX_ZLIB_ORIG_NAME 174 #undef TOOLX_ZLIB_COMMENT 175 #undef TOOLX_ZLIB_RESERVED 176 } 177 #endif //ZLIB_VERNUM <= 0x1140 178 179 inline bool gunzip_buffer(std::ostream& a_out, 180 unsigned int a_srcsize,const char* a_src, 181 unsigned int a_tgtsize,char* a_tgt, 182 unsigned int& a_irep) { 183 184 z_stream stream; // decompression stream 185 186 #if ZLIB_VERNUM <= 0x1140 187 char* pos = (char*)a_src; 188 if(gunzip_check_header(pos)!=Z_OK) return false; 189 stream.next_in = (Bytef*)pos; 190 stream.avail_in = (uInt)(a_srcsize-(pos-a_src)); 191 #else 192 stream.next_in = (Bytef*)a_src; 193 stream.avail_in = (uInt)a_srcsize; 194 #endif //ZLIB_VERNUM 195 196 stream.next_out = (Bytef*)a_tgt; 197 stream.avail_out = (uInt)a_tgtsize; 198 stream.zalloc = (alloc_func)0; 199 stream.zfree = (free_func)0; 200 stream.opaque = (voidpf)0; 201 202 #if ZLIB_VERNUM <= 0x1140 203 int err = inflateInit2(&stream,-MAX_WBITS); 204 #else 205 int err = inflateInit2(&stream,MAX_WBITS+16); 206 #endif 207 if (err != Z_OK) { 208 a_out << "toolx::gunzip_buffer :" 209 << " error " << err << " in zlib/inflateInit2." << std::endl; 210 return false; 211 } 212 213 err = inflate(&stream, Z_FINISH); 214 if (err != Z_STREAM_END) { 215 inflateEnd(&stream); 216 a_out << "toolx::gunzip_buffer :" 217 << " error " << err << " in zlib/inflate." << std::endl; 218 return false; 219 } 220 221 inflateEnd(&stream); 222 223 a_irep = (unsigned)stream.total_out; 224 225 return true; 226 } 227 228 } 229 230 #endif