Coverage Report

Created: 2021-08-28 18:14

D:\git\skunkworks\herald-for-cpp\herald\src\datatype\base64_string.cpp
Line
Count
Source (jump to first uncovered line)
1
//  Copyright 2020-2021 Herald Project Contributors
2
//  SPDX-License-Identifier: Apache-2.0
3
//
4
5
#include "herald/datatype/base64_string.h"
6
#include "herald/datatype/data.h"
7
8
#include <string>
9
#include <iosfwd>
10
11
namespace herald {
12
namespace datatype {
13
14
// IMPL DEFINITION
15
// class Base64String::Impl {
16
// public:
17
//   Impl();
18
//   ~Impl() = default;
19
20
//   std::string value; // Base64 encoded, and guarded
21
// };
22
23
// Base64String::Impl::Impl() { }
24
25
26
const std::string base64_chars = 
27
             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
28
             "abcdefghijklmnopqrstuvwxyz"
29
             "0123456789+/";
30
31
32
40
bool is_base64(char c) {
33
40
  return (isalnum(c) || 
(c == '+')0
||
(c == '/')0
||
(c == '=')0
);
34
40
}
35
36
37
38
39
bool
40
3
Base64String::from(const std::string& original, Base64String& toInitialise) noexcept {
41
3
  bool ok = true;
42
24
  for (auto& c : original) {
43
24
    ok = ok & is_base64(c);
44
24
  }
45
3
  if (!ok) {
46
0
    return false;
47
0
  }
48
3
  toInitialise.value = original;
49
3
  return true;
50
3
}
51
52
140
Base64String::Base64String() : value() { }
53
54
Base64String::Base64String(Base64String&& other)
55
 : value(std::move(other.value))
56
0
{
57
0
  ;
58
0
}
59
60
140
Base64String::~Base64String() = default;
61
62
Base64String 
63
1
Base64String::encode(const Data& from) noexcept {
64
1
  std::size_t bufLen = from.size();
65
1
  std::string ret;
66
1
  ret.reserve(from.size());
67
1
  int i = 0;
68
1
  int j = 0;
69
1
  char char_array_3[3];
70
1
  char char_array_4[4];
71
1
72
1
  std::size_t idx = 0;
73
33
  while (bufLen--) {
74
32
    char_array_3[i++] = (char)from.at(idx);
75
32
    idx++;
76
32
    if (i == 3) {
77
10
      char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
78
10
      char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
79
10
      char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
80
10
      char_array_4[3] = char_array_3[2] & 0x3f;
81
10
82
50
      for(i = 0; (i <4) ; 
i++40
) {
83
40
        ret += base64_chars[char_array_4[i]];
84
40
      }
85
10
      i = 0;
86
10
    }
87
32
  }
88
1
89
1
  if (i)
90
1
  {
91
2
    for(j = i; j < 3; 
j++1
) {
92
1
      char_array_3[j] = '\0';
93
1
    }
94
1
95
1
    char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
96
1
    char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
97
1
    char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
98
1
    char_array_4[3] = char_array_3[2] & 0x3f;
99
1
100
4
    for (j = 0; (j < i + 1); 
j++3
) {
101
3
      ret += base64_chars[char_array_4[j]];
102
3
    }
103
1
104
2
    while((i++ < 3)) {
105
1
      ret += '=';
106
1
    }
107
1
  }
108
1
109
1
  // return ret;
110
1
111
1
  // std::string buffer; // should be smaller, but this will do
112
1
  // buffer.reserve(length);
113
1
  // std::size_t pad = 0;
114
1
  // for (std::size_t i = 0; i < length; i += 3) {
115
1
116
1
  //   int b = ((((int)data[i]) & 0xFF) << 16) & 0xFFFFFF;
117
1
  //   if (i + 1 < length) {
118
1
  //     b |= (((int)data[i + 1]) & 0xFF) << 8;
119
1
  //   } else {
120
1
  //     pad++;
121
1
  //   }
122
1
  //   if (i + 2 < length) {
123
1
  //     b |= (((int)data[i + 2]) & 0xFF);
124
1
  //   } else {
125
1
  //     pad++;
126
1
  //   }
127
1
128
1
  //   for (int j = 0; j < 4 - pad; j++) {
129
1
  //     std::size_t c = (b & 0xFC0000) >> 18;
130
1
  //     buffer.append(tbl[c]);
131
1
  //     b <<= 6;
132
1
  //   }
133
1
  // }
134
1
  // for (std::size_t j = 0; j < pad; j++) {
135
1
  //   buffer.append("=");
136
1
  // }
137
1
138
1
  Base64String nvalue;
139
1
  nvalue.value = std::move(ret);
140
1
  return nvalue;
141
1
}
142
143
Data
144
2
Base64String::decode() const noexcept {
145
2
  std::size_t in_len = value.size();
146
2
  int i = 0;
147
2
  int j = 0;
148
2
  int in_ = 0;
149
2
  char char_array_4[4], char_array_3[3];
150
2
  Data result;
151
2
152
18
  while (in_len-- && 
( value[in_] != '=')16
&&
is_base64(value[in_])16
) {
153
16
    char_array_4[i++] = value[in_]; in_++;
154
16
    if (i ==4) {
155
20
      for (i = 0; i <4; 
i++16
)
156
16
        char_array_4[i] = (char)base64_chars.find(char_array_4[i]);
157
4
158
4
      char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
159
4
      char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
160
4
      char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
161
4
162
16
      for (i = 0; (i < 3); 
i++12
) {
163
12
        result.append(std::byte(char_array_3[i]));
164
12
      }
165
4
      i = 0;
166
4
    }
167
16
  }
168
2
169
2
  if (i) {
170
0
    for (j = i; j <4; j++)
171
0
      char_array_4[j] = 0;
172
0
173
0
    for (j = 0; j <4; j++)
174
0
      char_array_4[j] = (char)base64_chars.find(char_array_4[j]);
175
0
176
0
    char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
177
0
    char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
178
0
    char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
179
0
180
0
    for (j = 0; (j < i - 1); j++) result.append(std::byte(char_array_3[j]));
181
0
  }
182
2
183
2
  return result; // std::move via compiler
184
2
}
185
186
187
std::string
188
2
Base64String::encoded() const noexcept {
189
2
  return value; // copy ctor
190
2
}
191
192
193
} // end namespace
194
} // end namespace