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: 2020-06-24 22:13:30 Branches: 95 143 66.4 %

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
3942
static inline constexpr size_t base64_encoded_size(size_t size) {
14
3942
  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
337371
static inline size_t base64_decoded_size_fast(size_t size) {
19
337371
  size_t remainder = size % 4;
20
21
337371
  size = (size / 4) * 3;
22
337371
  if (remainder) {
23

337308
    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
337308
      size += 1 + (remainder == 3);
29
    }
30
  }
31
32
337371
  return size;
33
}
34
35
template <typename TypeName>
36
337361
size_t base64_decoded_size(const TypeName* src, size_t size) {
37

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

337361
  if (src[size - 1] == '=')
41
337269
    size--;
42


337361
  if (size > 0 && src[size - 1] == '=')
43
337127
    size--;
44
45
337361
  return base64_decoded_size_fast(size);
46
}
47
48
49
extern const int8_t unbase64_table[256];
50
51
52
43395709
inline static int8_t unbase64(uint8_t x) {
53
43395709
  return unbase64_table[x];
54
}
55
56
57
template <typename TypeName>
58
337426
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





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





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





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





69
  V(dst[(*k)++] = ((hi & 0x03) << 6) | ((lo & 0x3F) >> 0));
83
#undef V
84
54
  return true;  // Continue decoding.
85
}
86
87
88
template <typename TypeName>
89
337356
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

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


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

10680155
    if (v & 0x80808080) {
105

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


337342
  if (i < srclen && k < dstlen) {
117
337294
    base64_decode_group_slow(dst, dstlen, src, srclen, &i, &k);
118
  }
119
337342
  return k;
120
}
121
122
123
template <typename TypeName>
124
337356
size_t base64_decode(char* const dst, const size_t dstlen,
125
                     const TypeName* const src, const size_t srclen) {
126
337356
  const size_t decoded_size = base64_decoded_size(src, srclen);
127
337356
  return base64_decode_fast(dst, dstlen, src, srclen, decoded_size);
128
}
129
130
1328
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

1328
  CHECK(dlen >= base64_encoded_size(slen) &&
136
        "not enough space provided for base64 encode");
137
138
1328
  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
1328
  i = 0;
152
1328
  k = 0;
153
1328
  n = slen / 3 * 3;
154
155
367202336
  while (i < n) {
156
183600504
    a = src[i + 0] & 0xff;
157
183600504
    b = src[i + 1] & 0xff;
158
183600504
    c = src[i + 2] & 0xff;
159
160
183600504
    dst[k + 0] = table[a >> 2];
161
183600504
    dst[k + 1] = table[((a & 3) << 4) | (b >> 4)];
162
183600504
    dst[k + 2] = table[((b & 0x0f) << 2) | (c >> 6)];
163
183600504
    dst[k + 3] = table[c & 0x3f];
164
165
183600504
    i += 3;
166
183600504
    k += 4;
167
  }
168
169
1328
  if (n != slen) {
170
703
    switch (slen - n) {
171
      case 1:
172
476
        a = src[i + 0] & 0xff;
173
476
        dst[k + 0] = table[a >> 2];
174
476
        dst[k + 1] = table[(a & 3) << 4];
175
476
        dst[k + 2] = '=';
176
476
        dst[k + 3] = '=';
177
476
        break;
178
179
      case 2:
180
227
        a = src[i + 0] & 0xff;
181
227
        b = src[i + 1] & 0xff;
182
227
        dst[k + 0] = table[a >> 2];
183
227
        dst[k + 1] = table[((a & 3) << 4) | (b >> 4)];
184
227
        dst[k + 2] = table[(b & 0x0f) << 2];
185
227
        dst[k + 3] = '=';
186
227
        break;
187
    }
188
  }
189
190
1328
  return dlen;
191
}
192
}  // namespace node
193
194
195
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
196
197
#endif  // SRC_BASE64_H_