aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/yaml-cpp/src/binary.cpp
blob: d27762a2436d253d1aa65ff09a079c7c5d79b9ba (plain) (blame)
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
#include "yaml-cpp/binary.h"

#include <cctype>

namespace YAML {
static const char encoding[] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

std::string EncodeBase64(const unsigned char *data, std::size_t size) {
  const char PAD = '=';

  std::string ret;
  ret.resize(4 * size / 3 + 3);
  char *out = &ret[0];

  std::size_t chunks = size / 3;
  std::size_t remainder = size % 3;

  for (std::size_t i = 0; i < chunks; i++, data += 3) {
    *out++ = encoding[data[0] >> 2];
    *out++ = encoding[((data[0] & 0x3) << 4) | (data[1] >> 4)];
    *out++ = encoding[((data[1] & 0xf) << 2) | (data[2] >> 6)];
    *out++ = encoding[data[2] & 0x3f];
  }

  switch (remainder) {
    case 0:
      break;
    case 1:
      *out++ = encoding[data[0] >> 2];
      *out++ = encoding[((data[0] & 0x3) << 4)];
      *out++ = PAD;
      *out++ = PAD;
      break;
    case 2:
      *out++ = encoding[data[0] >> 2];
      *out++ = encoding[((data[0] & 0x3) << 4) | (data[1] >> 4)];
      *out++ = encoding[((data[1] & 0xf) << 2)];
      *out++ = PAD;
      break;
  }

  ret.resize(out - &ret[0]);
  return ret;
}

static const unsigned char decoding[] = {
    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, 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,  54,  55,  56,  57,  58,  59,  60,  61,  255, 255,
    255, 0,   255, 255, 255, 0,   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,  255, 255, 255, 255, 255, 255, 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,  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, 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, 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, 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, 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, 255, 255, 255, 255, 255, 255, 255,
    255,
};

std::vector<unsigned char> DecodeBase64(const std::string &input) {
  using ret_type = std::vector<unsigned char>;
  if (input.empty())
    return ret_type();

  ret_type ret(3 * input.size() / 4 + 1);
  unsigned char *out = &ret[0];

  unsigned value = 0;
  for (std::size_t i = 0, cnt = 0; i < input.size(); i++) {
    if (std::isspace(static_cast<unsigned char>(input[i]))) {
      // skip newlines
      continue;
    }
    unsigned char d = decoding[static_cast<unsigned char>(input[i])];
    if (d == 255)
      return ret_type();

    value = (value << 6) | d;
    if (cnt % 4 == 3) {
      *out++ = value >> 16;
      if (i > 0 && input[i - 1] != '=')
        *out++ = value >> 8;
      if (input[i] != '=')
        *out++ = value;
    }
    ++cnt;
  }

  ret.resize(out - &ret[0]);
  return ret;
}
}  // namespace YAML