File: base64.cc

package info (click to toggle)
libosl 0.6.0-3.1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 148,792 kB
  • ctags: 151,985
  • sloc: cpp: 131,133; ansic: 7,228; ruby: 1,290; makefile: 569; perl: 309; sh: 35
file content (108 lines) | stat: -rw-r--r-- 2,627 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include "osl/misc/base64.h"
#include "osl/stl/vector.h"
#include <boost/foreach.hpp>

std::string osl::misc::
base64Encode(boost::dynamic_bitset<> src)
{
  if (src.empty())
    return "";

  const size_t bits_to_add = 6 - src.size()%6;
  if (bits_to_add < 6)
  {
    for (size_t i=0; i<bits_to_add; ++i)
    {
      src.push_back(0ul); // this appends to the most significant bit
      src <<= 1; // Instead, append to the least significant bit
    }
  }
  assert(src.size()%6 == 0);
  assert(src.size()/6 > 0);

  vector<char> dst(src.size()/6, 0);
  const boost::dynamic_bitset<> mask(src.size(), 63ul);
  for (size_t i=0; i<dst.size(); ++i)
  {
    const unsigned long c = ((src >> i*6) & mask).to_ulong();
    assert (c <= 63);
    if (/*0 <= c &&*/ c <= 25)   // A..Z
      dst[dst.size()-1-i] = static_cast<char>(c+65);
    else if (26 <= c && c <= 51) // a..z 
      dst[dst.size()-1-i] = static_cast<char>(c+97-26);
    else if (52 <= c && c <= 61) // 0..9
      dst[dst.size()-1-i] = static_cast<char>(c+48-52);
    else if (c == 62)
      dst[dst.size()-1-i] = '-'; // for URL instread of '+'
    else if (c == 63)
      dst[dst.size()-1-i] = '_'; // for URL instread of '/'
    else
    {
      assert(false);
      return "";
    }
  }

  const size_t char_to_add = 4 - dst.size()%4;
  if (char_to_add < 4)
  {
    for (size_t i=0; i<char_to_add; ++i)
      dst.push_back('=');
  }

  return std::string(dst.begin(), dst.end());
}

boost::dynamic_bitset<> osl::misc::
base64Decode(std::string src)
{
  if (src.empty() || src.size()%4 != 0)
    return boost::dynamic_bitset<>(0);

  {
    int count = 0;
    while (src[src.size()-1] == '=')
    {
      src.erase(src.end()-1);
      ++count;
    }
    if (count >= 4)
      return boost::dynamic_bitset<>(0);
  }

  const size_t dst_size = src.size()*6;
  const size_t redundant = dst_size%8;
  boost::dynamic_bitset<> dst(dst_size, 0ul);
  BOOST_FOREACH(char c, src)
  {
    unsigned long tmp = 0;
    if (48 <= c && c <= 48+9)       // 0..9
      tmp = c -48+52;
    else if (65 <= c && c <= 65+25) // A..Z
      tmp = c - 65;
    else if (97 <= c && c <= 97+25) // a..z
      tmp = c -97+26;
    else if (c == '-')
      tmp = 62;
    else if (c == '_')
      tmp = 63;
    else
    {
      assert(false);
      return boost::dynamic_bitset<>(0);
    }
    assert(/*0 <= tmp &&*/ tmp <= 63);
    const boost::dynamic_bitset<> mask(dst_size, tmp);
    dst = (dst << 6) | mask;
  }
  if (redundant > 0)
  {
    dst >>= redundant;
    dst.resize(dst.size()-redundant);
  }
  return dst;
}
// ;;; Local Variables:
// ;;; mode:c++
// ;;; c-basic-offset:2
// ;;; End: