PageRenderTime 39ms CodeModel.GetById 17ms app.highlight 17ms RepoModel.GetById 2ms app.codeStats 0ms

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