foobar2000 SDK  2015-01-14
base64.cpp
Go to the documentation of this file.
1 #include "pfc.h"
2 
3 namespace bitWriter {
4  static void set_bit(t_uint8 * p_stream,size_t p_offset, bool state) {
5  t_uint8 mask = 1 << (7-(p_offset&7));
6  t_uint8 & byte = p_stream[p_offset>>3];
7  byte = (byte & ~mask) | (state ? mask : 0);
8  }
9  static void set_bits(t_uint8 * stream, t_size offset, t_size word, t_size bits) {
10  for(t_size walk = 0; walk < bits; ++walk) {
11  t_uint8 bit = (t_uint8)((word >> (bits - walk - 1))&1);
12  set_bit(stream, offset+walk, bit != 0);
13  }
14  }
15 };
16 
17 namespace pfc {
18  t_size base64_decode_estimate(const char * text) {
19  t_size textLen = strlen(text);
20  if (textLen % 4 != 0) throw pfc::exception_invalid_params();
21  t_size outLen = (textLen / 4) * 3;
22 
23  if (textLen >= 4) {
24  if (text[textLen-1] == '=') {
25  textLen--; outLen--;
26  if (text[textLen-1] == '=') {
27  textLen--; outLen--;
28  }
29  }
30  }
31  return outLen;
32  }
33 
34 
35 
36  void base64_decode(const char * text, void * out) {
37  static const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
38  t_uint8 alphabetRev[256];
39  for(t_size walk = 0; walk < PFC_TABSIZE(alphabetRev); ++walk) alphabetRev[walk] = 0xFF;
40  for(t_size walk = 0; walk < PFC_TABSIZE(alphabet); ++walk) alphabetRev[alphabet[walk]] = (t_uint8)walk;
41  const t_size textLen = strlen(text);
42 
43  if (textLen % 4 != 0) throw pfc::exception_invalid_params();
44  if (textLen == 0) return;
45 
46  t_size outWritePtr = 0;
47 
48  {
49  const t_size max = textLen - 4;
50  t_size textWalk = 0;
51  for(; textWalk < max; textWalk ++) {
52  const t_uint8 v = alphabetRev[(t_uint8)text[textWalk]];
53  if (v == 0xFF) throw pfc::exception_invalid_params();
54  bitWriter::set_bits(reinterpret_cast<t_uint8*>(out),outWritePtr,v,6);
55  outWritePtr += 6;
56  }
57 
58  t_uint8 temp[3];
59  t_size tempWritePtr = 0;
60  for(; textWalk < textLen; textWalk ++) {
61  const char c = text[textWalk];
62  if (c == '=') break;
63  const t_uint8 v = alphabetRev[(t_uint8)c];
64  if (v == 0xFF) throw pfc::exception_invalid_params();
65  bitWriter::set_bits(temp,tempWritePtr,v,6);
66  tempWritePtr += 6;
67  }
68  for(; textWalk < textLen; textWalk ++) {
69  if (text[textWalk] != '=') throw pfc::exception_invalid_params();
70  }
71  memcpy(reinterpret_cast<t_uint8*>(out) + (outWritePtr/8), temp, tempWritePtr/8);
72  }
73  }
74  void base64_encode(pfc::string_base & out, const void * in, t_size inSize) {
75  out.reset(); base64_encode_append(out, in, inSize);
76  }
77  void base64_encode_append(pfc::string_base & out, const void * in, t_size inSize) {
78  static const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
79  int shift = 0;
80  int accum = 0;
81  const t_uint8 * inPtr = reinterpret_cast<const t_uint8*>(in);
82 
83  for(t_size walk = 0; walk < inSize; ++walk) {
84  accum <<= 8;
85  shift += 8;
86  accum |= inPtr[walk];
87  while ( shift >= 6 ) {
88  shift -= 6;
89  out << format_char( alphabet[(accum >> shift) & 0x3F] );
90  }
91  }
92  if (shift == 4) {
93  out << format_char( alphabet[(accum & 0xF)<<2] ) << "=";
94  } else if (shift == 2) {
95  out << format_char( alphabet[(accum & 0x3)<<4] ) << "==";
96  }
97  }
98 
99 }
uint8_t t_uint8
Definition: int_types.h:9
void base64_decode(const char *text, void *out)
Definition: base64.cpp:36
void base64_encode(pfc::string_base &out, const void *in, t_size inSize)
Definition: base64.cpp:74
static void set_bit(t_uint8 *p_stream, size_t p_offset, bool state)
Definition: base64.cpp:4
t_uint8 byte
Definition: mp3_utils.h:11
size_t t_size
Definition: int_types.h:48
t_size base64_decode_estimate(const char *text)
Definition: base64.cpp:18
void base64_encode_append(pfc::string_base &out, const void *in, t_size inSize)
Definition: base64.cpp:77
static void set_bits(t_uint8 *stream, t_size offset, t_size word, t_size bits)
Definition: base64.cpp:9