/decoders/binary/base64.d

http://github.com/wilkie/djehuty · D · 122 lines · 70 code · 32 blank · 20 comment · 17 complexity · 6fe2802c8114d98896dbf84c650be8bf MD5 · raw file

  1. /*
  2. * base64.d
  3. *
  4. * This file implements the Base64 algorithm.
  5. *
  6. * Author: Dave Wilkinson
  7. *
  8. */
  9. module decoders.binary.base64;
  10. import core.endian;
  11. import core.stream;
  12. import core.definitions;
  13. import decoders.binary.decoder;
  14. private {
  15. static const ubyte _base64_encoding_table[] = [
  16. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
  17. 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
  18. 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
  19. 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
  20. 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
  21. '8', '9', '+', '/', '='
  22. ];
  23. static const ubyte _base64_decoding_table[] = [
  24. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  25. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, 52, 53,
  26. 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
  27. 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, 255, 26, 27, 28,
  28. 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255,
  29. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  30. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  31. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  32. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  33. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  34. 255, 255, 255, 255, 255, 0
  35. ];
  36. }
  37. // Section: Codecs/Binary
  38. // Description: This represents the Base64 Codec.
  39. class Base64Decoder : BinaryDecoder {
  40. StreamData decode(Stream stream, Stream toStream) {
  41. ubyte chunk;
  42. for (;stream.read(chunk);) {
  43. // decode character
  44. // add to stream, where last character left off
  45. chunk = _base64_decoding_table[chunk];
  46. // should we quit or ignore?
  47. if (chunk == 255) {
  48. return StreamData.Complete;
  49. }
  50. else if (chunk == 254) {
  51. continue;
  52. }
  53. if (decoderFrameState == 0) {
  54. // just set the byte, do not increment
  55. chunk <<= 2;
  56. decoderSubState = chunk;
  57. decoderFrameState = 6;
  58. }
  59. else if (decoderFrameState == 2) {
  60. // just finish the current byte of out stream
  61. // just append it out
  62. chunk |= decoderSubState;
  63. toStream.write(&chunk, 1);
  64. decoderFrameState = 0;
  65. }
  66. else if (decoderFrameState == 4) {
  67. // spans two bytes
  68. decoderNextState = chunk;
  69. chunk >>= 2;
  70. chunk |= decoderSubState;
  71. toStream.write(&chunk, 1);
  72. decoderSubState = (decoderNextState & 0x3) << 6;
  73. decoderFrameState = 2;
  74. }
  75. else if (decoderFrameState == 6) {
  76. // needs to span two bytes in out stream
  77. // finish current byte
  78. decoderNextState = chunk;
  79. chunk >>= 4;
  80. chunk |= decoderSubState;
  81. toStream.write(&chunk, 1);
  82. // go to next byte, just set
  83. decoderSubState = (decoderNextState & 0xF) << 4;
  84. decoderFrameState = 4;
  85. }
  86. decoderFrameState = decoderFrameState;
  87. }
  88. return StreamData.Required;
  89. }
  90. }