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-02-19 22:14:06 Branches: 94 143 65.7 %

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

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

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

314810
  if (src[size - 1] == '=')
41
314718
    size--;
42


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





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





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





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





73
  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
314805
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

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


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

10206018
    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
10205950
      dst[k + 0] = ((v >> 22) & 0xFC) | ((v >> 20) & 0x03);
110
10205950
      dst[k + 1] = ((v >> 12) & 0xF0) | ((v >> 10) & 0x0F);
111
10205950
      dst[k + 2] = ((v >>  2) & 0xC0) | ((v >>  0) & 0x3F);
112
10205950
      i += 4;
113
10205950
      k += 3;
114
    }
115
  }
116


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

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