/decoders/binary/zlib.d

http://github.com/wilkie/djehuty · 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. module decoders.binary.zlib;
  11. import decoders.binary.decoder;
  12. import decoders.binary.deflate;
  13. import core.stream;
  14. import core.definitions;
  15. // Section: Codecs/Binary
  16. // Description: This represents the ZLIB Codec.
  17. class ZLIBDecoder : BinaryDecoder {
  18. StreamData decode(Stream stream, Stream toStream) {
  19. for (;;) {
  20. switch (decoderState) {
  21. // INIT DECODER //
  22. case ZLIB_STATE_INIT:
  23. // SET VARIABLES WITHIN IDP
  24. // GOTO NEXT STEP
  25. decoderState = ZLIB_STATE_READ_HEADER;
  26. // READ STREAM HEADER //
  27. case ZLIB_STATE_READ_HEADER:
  28. if (!(stream.read(&zlibStreamHeader,2))) {
  29. return StreamData.Required;
  30. }
  31. // GET COMPRESSION METHOD, INFO
  32. // CM:
  33. zlibCompressionMethod = cast(ubyte)(zlibStreamHeader.zlibCMF & 0xF);
  34. // CINFO:
  35. zlibCompressionInfo = cast(ubyte)(zlibStreamHeader.zlibCMF >> 4);
  36. // GET FLAGS
  37. // FDICT
  38. zlibIsDictionary = cast(ubyte)(zlibStreamHeader.zlibFLG & 32);
  39. // FCHECK
  40. zlibFCHECK = cast(ubyte)(zlibStreamHeader.zlibFLG & 0xF);
  41. // FLEVEL
  42. zlibCompressionLevel = cast(ubyte)(zlibStreamHeader.zlibFLG >> 6);
  43. if (zlibCompressionMethod == 8) {
  44. ///write("zlib - using DEFLATE\n");
  45. if (zlibCompressionInfo > 7) {
  46. //write("zlib - window size is invalid\n");
  47. return StreamData.Invalid;
  48. }
  49. else if (zlibCompressionInfo == 7) {
  50. // write("zlib - window size of 32K\n");
  51. }
  52. }
  53. else {
  54. //ite("zlib - unsupported compression method\n");
  55. return StreamData.Invalid;
  56. }
  57. if (zlibIsDictionary) {
  58. //write("zlib - has preset dictionary\n");
  59. }
  60. switch (zlibCompressionLevel) {
  61. case 0:
  62. //write("zlib - compression level: fastest\n");
  63. break;
  64. case 1:
  65. //write("zlib - compression level: fast\n");
  66. break;
  67. case 2:
  68. //write("zlib - compression level: default\n");
  69. break;
  70. case 3:
  71. //write("zlib - compression level: maximum\n");
  72. break;
  73. default:
  74. //write("zlib - compression level odd, continuing anyway\n");
  75. break;
  76. }
  77. decoderState = ZLIB_STATE_STREAM_DEFLATE;
  78. case ZLIB_STATE_STREAM_DEFLATE:
  79. StreamData ret;
  80. //stream.read(decoding, stream.getRemaining() - 4);
  81. //decoding.rewind();
  82. // writeln("zlib deflate");
  83. if (deflateDecompressor is null) {
  84. deflateDecompressor = new DEFLATEDecoder();
  85. }
  86. if ((ret = deflateDecompressor.decode(stream, toStream)) != StreamData.Required) {
  87. decoderState = ZLIB_STATE_READ_ADLER32;
  88. }
  89. else {
  90. ////OutputDebugStringA("zlib - returning early\n");
  91. return ret;
  92. }
  93. case ZLIB_STATE_READ_ADLER32:
  94. // writeln("zlib read adler32");
  95. //OutputDebugStringA("zlib - decompression done, reading ALDER32\n");
  96. if (!(stream.skip(4))) {
  97. //return StreamData.Required;
  98. }
  99. //OutputDebugStringA("zlib - returning\n");
  100. return StreamData.Complete;
  101. default:
  102. break;
  103. }
  104. break;
  105. }
  106. return StreamData.Invalid;
  107. }
  108. private:
  109. const auto ZLIB_STATE_INIT = 0;
  110. const auto ZLIB_STATE_READ_HEADER = 1;
  111. const auto ZLIB_STATE_STREAM_DEFLATE = 2;
  112. const auto ZLIB_STATE_READ_ADLER32 = 3;
  113. align(1) struct _zlib_cmf_flg_header {
  114. ubyte zlibCMF;
  115. ubyte zlibFLG;
  116. }
  117. protected:
  118. // CMF, FLG
  119. _zlib_cmf_flg_header zlibStreamHeader;
  120. // CM
  121. ubyte zlibCompressionMethod;
  122. // CINFO
  123. ubyte zlibCompressionInfo;
  124. // FDICT
  125. ubyte zlibIsDictionary;
  126. //FLEVEL
  127. ubyte zlibCompressionLevel;
  128. //FCHECK
  129. ubyte zlibFCHECK;
  130. // USED WHEN STREAMING THE DECODER
  131. DEFLATEDecoder deflateDecompressor;
  132. }