GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/base64.h Lines: 82 84 97.6 %
Date: 2019-03-02 22:23:06 Branches: 89 143 62.2 %

Line Branch Exec Source
1
#ifndef SRC_BASE64_H_
2
#define SRC_BASE64_H_
3
4
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5
6
#include "util.h"
7
8
#include <cstddef>
9
#include <cstdint>
10
11
namespace node {
12
//// Base 64 ////
13
15161
static inline constexpr size_t base64_encoded_size(size_t size) {
14
15161
  return ((size + 2 - ((size + 2) % 3)) / 3 * 4);
15
}
16
17
// Doesn't check for padding at the end.  Can be 1-2 bytes over.
18
277
static inline size_t base64_decoded_size_fast(size_t size) {
19
277
  size_t remainder = size % 4;
20
21
277
  size = (size / 4) * 3;
22
277
  if (remainder) {
23

219
    if (size == 0 && remainder == 1) {
24
      // special case: 1-byte input cannot be decoded
25
      size = 0;
26
    } else {
27
      // non-padded input, add 1 or 2 extra bytes
28
219
      size += 1 + (remainder == 3);
29
    }
30
  }
31
32
277
  return size;
33
}
34
35
template <typename TypeName>
36
267
size_t base64_decoded_size(const TypeName* src, size_t size) {
37

267
  if (size == 0)
38
    return 0;
39
40

267
  if (src[size - 1] == '=')
41
190
    size--;
42


267
  if (size > 0 && src[size - 1] == '=')
43
84
    size--;
44
45
267
  return base64_decoded_size_fast(size);
46
}
47
48
49
extern const int8_t unbase64_table[256];
50
51
52
14396912
inline static int8_t unbase64(uint8_t x) {
53
14396912
  return unbase64_table[x];
54
}
55
56
57
template <typename TypeName>
58
291
bool base64_decode_group_slow(char* const dst, const size_t dstlen,
59
                              const TypeName* const src, const size_t srclen,
60
                              size_t* const i, size_t* const k) {
61
  uint8_t hi;
62
  uint8_t lo;
63
#define V(expr)                                                               \
64
  for (;;) {                                                                  \
65
    const uint8_t c = src[*i];                                                \
66
    lo = unbase64(c);                                                         \
67
    *i += 1;                                                                  \
68
    if (lo < 64)                                                              \
69
      break;  /* Legal character. */                                          \
70
    if (c == '=' || *i >= srclen)                                             \
71
      return false;  /* Stop decoding. */                                     \
72
  }                                                                           \
73
  expr;                                                                       \
74
  if (*i >= srclen)                                                           \
75
    return false;                                                             \
76
  if (*k >= dstlen)                                                           \
77
    return false;                                                             \
78
  hi = lo;
79





291
  V(/* Nothing. */);
80





243
  V(dst[(*k)++] = ((hi & 0x3F) << 2) | ((lo & 0x30) >> 4));
81





149
  V(dst[(*k)++] = ((hi & 0x0F) << 4) | ((lo & 0x3C) >> 2));
82





41
  V(dst[(*k)++] = ((hi & 0x03) << 6) | ((lo & 0x3F) >> 0));
83
#undef V
84
32
  return true;  // Continue decoding.
85
}
86
87
88
template <typename TypeName>
89
262
size_t base64_decode_fast(char* const dst, const size_t dstlen,
90
                          const TypeName* const src, const size_t srclen,
91
                          const size_t decoded_size) {
92

262
  const size_t available = dstlen < decoded_size ? dstlen : decoded_size;
93
262
  const size_t max_k = available / 3 * 3;
94
262
  size_t max_i = srclen / 4 * 4;
95
262
  size_t i = 0;
96
262
  size_t k = 0;
97


3599564
  while (i < max_i && k < max_k) {
98
    const uint32_t v =
99
3599047
        unbase64(src[i + 0]) << 24 |
100
3599047
        unbase64(src[i + 1]) << 16 |
101
3599047
        unbase64(src[i + 2]) << 8 |
102
10797141
        unbase64(src[i + 3]);
103
    // If MSB is set, input contains whitespace or is not valid base64.
104

3599047
    if (v & 0x80808080) {
105

39
      if (!base64_decode_group_slow(dst, dstlen, src, srclen, &i, &k))
106
7
        return k;
107
32
      max_i = i + (srclen - i) / 4 * 4;  // Align max_i again.
108
    } else {
109
3599008
      dst[k + 0] = ((v >> 22) & 0xFC) | ((v >> 20) & 0x03);
110
3599008
      dst[k + 1] = ((v >> 12) & 0xF0) | ((v >> 10) & 0x0F);
111
3599008
      dst[k + 2] = ((v >>  2) & 0xC0) | ((v >>  0) & 0x3F);
112
3599008
      i += 4;
113
3599008
      k += 3;
114
    }
115
  }
116


255
  if (i < srclen && k < dstlen) {
117
208
    base64_decode_group_slow(dst, dstlen, src, srclen, &i, &k);
118
  }
119
255
  return k;
120
}
121
122
123
template <typename TypeName>
124
262
size_t base64_decode(char* const dst, const size_t dstlen,
125
                     const TypeName* const src, const size_t srclen) {
126
262
  const size_t decoded_size = base64_decoded_size(src, srclen);
127
262
  return base64_decode_fast(dst, dstlen, src, srclen, decoded_size);
128
}
129
130
5058
static size_t base64_encode(const char* src,
131
                            size_t slen,
132
                            char* dst,
133
                            size_t dlen) {
134
  // We know how much we'll write, just make sure that there's space.
135

5058
  CHECK(dlen >= base64_encoded_size(slen) &&
136
        "not enough space provided for base64 encode");
137
138
5058
  dlen = base64_encoded_size(slen);
139
140
  unsigned a;
141
  unsigned b;
142
  unsigned c;
143
  unsigned i;
144
  unsigned k;
145
  unsigned n;
146
147
  static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
148
                              "abcdefghijklmnopqrstuvwxyz"
149
                              "0123456789+/";
150
151
5058
  i = 0;
152
5058
  k = 0;
153
5058
  n = slen / 3 * 3;
154
155
362729898
  while (i < n) {
156
362719782
    a = src[i + 0] & 0xff;
157
362719782
    b = src[i + 1] & 0xff;
158
362719782
    c = src[i + 2] & 0xff;
159
160
362719782
    dst[k + 0] = table[a >> 2];
161
362719782
    dst[k + 1] = table[((a & 3) << 4) | (b >> 4)];
162
362719782
    dst[k + 2] = table[((b & 0x0f) << 2) | (c >> 6)];
163
362719782
    dst[k + 3] = table[c & 0x3f];
164
165
362719782
    i += 3;
166
362719782
    k += 4;
167
  }
168
169
5058
  if (n != slen) {
170
4385
    switch (slen - n) {
171
      case 1:
172
196
        a = src[i + 0] & 0xff;
173
196
        dst[k + 0] = table[a >> 2];
174
196
        dst[k + 1] = table[(a & 3) << 4];
175
196
        dst[k + 2] = '=';
176
196
        dst[k + 3] = '=';
177
196
        break;
178
179
      case 2:
180
4189
        a = src[i + 0] & 0xff;
181
4189
        b = src[i + 1] & 0xff;
182
4189
        dst[k + 0] = table[a >> 2];
183
4189
        dst[k + 1] = table[((a & 3) << 4) | (b >> 4)];
184
4189
        dst[k + 2] = table[(b & 0x0f) << 2];
185
4189
        dst[k + 3] = '=';
186
4189
        break;
187
    }
188
  }
189
190
5058
  return dlen;
191
}
192
}  // namespace node
193
194
195
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
196
197
#endif  // SRC_BASE64_H_