/decoders/binary/zlib.d
D | 183 lines | 85 code | 51 blank | 47 comment | 17 complexity | f5c1047763c002d8ee621d99fed71ed5 MD5 | raw file
1/* 2 * zlib.d 3 * 4 * This file implements the ZLIB standard. ZLIB is basically a wrapper around 5 * the DEFLATE algorithm. 6 * 7 * Author: Dave Wilkinson 8 * 9 */ 10 11module decoders.binary.zlib; 12 13import decoders.binary.decoder; 14import decoders.binary.deflate; 15 16import core.stream; 17import core.definitions; 18 19// Section: Codecs/Binary 20 21// Description: This represents the ZLIB Codec. 22class ZLIBDecoder : BinaryDecoder { 23 StreamData decode(Stream stream, Stream toStream) { 24 for (;;) { 25 switch (decoderState) { 26 // INIT DECODER // 27 case ZLIB_STATE_INIT: 28 // SET VARIABLES WITHIN IDP 29 30 // GOTO NEXT STEP 31 32 decoderState = ZLIB_STATE_READ_HEADER; 33 34 // READ STREAM HEADER // 35 case ZLIB_STATE_READ_HEADER: 36 37 if (!(stream.read(&zlibStreamHeader,2))) { 38 return StreamData.Required; 39 } 40 41 // GET COMPRESSION METHOD, INFO 42 43 // CM: 44 zlibCompressionMethod = cast(ubyte)(zlibStreamHeader.zlibCMF & 0xF); 45 46 // CINFO: 47 zlibCompressionInfo = cast(ubyte)(zlibStreamHeader.zlibCMF >> 4); 48 49 // GET FLAGS 50 51 // FDICT 52 zlibIsDictionary = cast(ubyte)(zlibStreamHeader.zlibFLG & 32); 53 54 // FCHECK 55 zlibFCHECK = cast(ubyte)(zlibStreamHeader.zlibFLG & 0xF); 56 57 // FLEVEL 58 zlibCompressionLevel = cast(ubyte)(zlibStreamHeader.zlibFLG >> 6); 59 60 if (zlibCompressionMethod == 8) { 61 ///write("zlib - using DEFLATE\n"); 62 63 if (zlibCompressionInfo > 7) { 64 //write("zlib - window size is invalid\n"); 65 66 return StreamData.Invalid; 67 } 68 else if (zlibCompressionInfo == 7) { 69 // write("zlib - window size of 32K\n"); 70 } 71 72 } 73 else { 74 //ite("zlib - unsupported compression method\n"); 75 return StreamData.Invalid; 76 } 77 78 if (zlibIsDictionary) { 79 //write("zlib - has preset dictionary\n"); 80 } 81 82 switch (zlibCompressionLevel) { 83 case 0: 84 //write("zlib - compression level: fastest\n"); 85 break; 86 case 1: 87 //write("zlib - compression level: fast\n"); 88 break; 89 case 2: 90 //write("zlib - compression level: default\n"); 91 break; 92 case 3: 93 //write("zlib - compression level: maximum\n"); 94 break; 95 96 default: 97 //write("zlib - compression level odd, continuing anyway\n"); 98 break; 99 } 100 101 decoderState = ZLIB_STATE_STREAM_DEFLATE; 102 103 case ZLIB_STATE_STREAM_DEFLATE: 104 105 StreamData ret; 106 107 //stream.read(decoding, stream.getRemaining() - 4); 108 109 //decoding.rewind(); 110 // writeln("zlib deflate"); 111 112 if (deflateDecompressor is null) { 113 deflateDecompressor = new DEFLATEDecoder(); 114 } 115 116 if ((ret = deflateDecompressor.decode(stream, toStream)) != StreamData.Required) { 117 decoderState = ZLIB_STATE_READ_ADLER32; 118 } 119 else { 120 ////OutputDebugStringA("zlib - returning early\n"); 121 return ret; 122 } 123 124 case ZLIB_STATE_READ_ADLER32: 125 // writeln("zlib read adler32"); 126 127 //OutputDebugStringA("zlib - decompression done, reading ALDER32\n"); 128 129 if (!(stream.skip(4))) { 130 //return StreamData.Required; 131 } 132 //OutputDebugStringA("zlib - returning\n"); 133 134 return StreamData.Complete; 135 136 137 default: 138 break; 139 } 140 141 break; 142 } 143 144 return StreamData.Invalid; 145 } 146 147private: 148 149 const auto ZLIB_STATE_INIT = 0; 150 151 const auto ZLIB_STATE_READ_HEADER = 1; 152 const auto ZLIB_STATE_STREAM_DEFLATE = 2; 153 const auto ZLIB_STATE_READ_ADLER32 = 3; 154 155 align(1) struct _zlib_cmf_flg_header { 156 ubyte zlibCMF; 157 ubyte zlibFLG; 158 } 159protected: 160 161 // CMF, FLG 162 _zlib_cmf_flg_header zlibStreamHeader; 163 164 // CM 165 ubyte zlibCompressionMethod; 166 167 // CINFO 168 ubyte zlibCompressionInfo; 169 170 // FDICT 171 ubyte zlibIsDictionary; 172 173 //FLEVEL 174 ubyte zlibCompressionLevel; 175 176 //FCHECK 177 ubyte zlibFCHECK; 178 179 180 // USED WHEN STREAMING THE DECODER 181 DEFLATEDecoder deflateDecompressor; 182 183}