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

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

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

408938
  if (src[size - 1] == '=')
41
408860
    size--;
42


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





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





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





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





45
  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
408933
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

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


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

12180656
    if (v & 0x80808080) {
105

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


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

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