• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

libbitcoin / libbitcoin-system / 14507858421

17 Apr 2025 04:11AM UTC coverage: 82.822% (+0.007%) from 82.815%
14507858421

push

github

web-flow
Merge pull request #1640 from evoskuil/master

Fix inverted NOEXCEPT define (regression), style, comments, whitespace.

7 of 8 new or added lines in 1 file covered. (87.5%)

15 existing lines in 6 files now uncovered.

10183 of 12295 relevant lines covered (82.82%)

3821900.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.08
/src/radix/base_64.cpp
1
/**
2
 * Copyright (c) 2011-2025 libbitcoin developers (see AUTHORS)
3
 *
4
 * This file is part of libbitcoin.
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Affero General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU Affero General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Affero General Public License
17
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
 */
19
#include <bitcoin/system/radix/base_64.hpp>
20

21
#include <string>
22
#include <bitcoin/system/data/data.hpp>
23

24
// base64
25
// Base 64 is an ascii data encoding with a domain of 64 symbols (characters).
26
// 64 is 2^6 so base64 is a 6<=>8 bit mapping.
27
// 4 characters (64^4) are encoded into one 8 byte (8^8) chunk before mapping.
28
// So after 8 byte encoding base64 is a 64<=>64 bit mapping.
29
// The 6 bit encoding is authoritative as byte encoding is padded.
30
// Invalid padding results in a decoding error.
31

32
// This implementation derived from public domain:
33
// en.wikibooks.org/wiki/Algorithm_Implementation/Miscellaneous/Base64
34

35
namespace libbitcoin {
36
namespace system {
37

38
const static char pad = '=';
39

40
const static char table[] =
41
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
42

43
std::string encode_base64(const data_slice& unencoded) NOEXCEPT
3✔
44
{
45
    std::string encoded;
3✔
46
    const auto size = unencoded.size();
3✔
47
    const auto padding = to_int((!is_zero(size % 3)));
3✔
48
    encoded.reserve((size / 3 + padding) * 4);
3✔
49

50
    uint32_t value;
3✔
51
    auto cursor = unencoded.begin();
3✔
52
    for (size_t position = 0; position < size / 3u; position++)
15✔
53
    {
54
        // Convert to big endian.
55
        value = (*cursor++) << 16;
12✔
56
        value += (*cursor++) << 8;
12✔
57
        value += (*cursor++);
12✔
58

59
        encoded.append(1, table[(value & 0x00fc0000) >> 18]);
12✔
60
        encoded.append(1, table[(value & 0x0003f000) >> 12]);
12✔
61
        encoded.append(1, table[(value & 0x00000fc0) >> 6]);
12✔
62
        encoded.append(1, table[(value & 0x0000003f) >> 0]);
12✔
63
    }
64

65
    switch (size % 3)
3✔
66
    {
67
        case 1:
1✔
68
            // Convert to big endian.
69
            value = (*cursor++) << 16;
1✔
70

71
            encoded.append(1, table[(value & 0x00fc0000) >> 18]);
1✔
72
            encoded.append(1, table[(value & 0x0003f000) >> 12]);
1✔
73
            encoded.append(2, pad);
1✔
74
            break;
1✔
75
        case 2:
×
76
            // Convert to big endian.
77
            value = (*cursor++) << 16;
×
78
            value += (*cursor++) << 8;
×
79

80
            encoded.append(1, table[(value & 0x00fc0000) >> 18]);
×
81
            encoded.append(1, table[(value & 0x0003f000) >> 12]);
×
82
            encoded.append(1, table[(value & 0x00000fc0) >> 6]);
×
83
            encoded.append(1, pad);
×
UNCOV
84
            break;
×
85
    }
86

87
    return encoded;
3✔
88
}
89

90
bool decode_base64(data_chunk& out, const std::string& in) NOEXCEPT
4✔
91
{
92
    const static uint32_t mask = 0x000000ff;
4✔
93

94
    const auto length = in.length();
4✔
95
    if (!is_zero(length % 4))
4✔
96
        return false;
97

98
    size_t padding = 0;
3✔
99
    if (!is_zero(length))
3✔
100
    {
101
        if (in[length - 1] == pad)
2✔
102
            padding++;
1✔
103
        if (in[length - 2] == pad)
2✔
104
            padding++;
1✔
105
    }
106

107
    data_chunk decoded;
3✔
108
    decoded.reserve(((length / 4) * 3) - padding);
3✔
109

110
    uint32_t value = 0;
3✔
111
    for (auto cursor = in.begin(); cursor < in.end();)
15✔
112
    {
113
        for (size_t position = 0; position < 4u; position++)
63✔
114
        {
115
            value <<= 6;
51✔
116
            if (*cursor >= 0x41 && *cursor <= 0x5a)
51✔
117
                value |= *cursor - 0x41;
30✔
118
            else if (*cursor >= 0x61 && *cursor <= 0x7a)
21✔
119
                value |= *cursor - 0x47;
13✔
120
            else if (*cursor >= 0x30 && *cursor <= 0x39)
8✔
121
                value |= *cursor + 0x04;
7✔
122
            else if (*cursor == 0x2b)
1✔
123
                value |= 0x3e;
×
124
            else if (*cursor == 0x2f)
1✔
125
                value |= 0x3f;
×
126
            else if (*cursor == pad)
1✔
127
            {
128
                // Handle 1 or 2 pad characters.
129
                switch (in.end() - cursor)
1✔
130
                {
131
                    case 1:
×
132
                        decoded.push_back((value >> 16) & mask);
×
133
                        decoded.push_back((value >> 8) & mask);
×
134
                        out = decoded;
×
135
                        return true;
1✔
136
                    case 2:
1✔
137
                        decoded.push_back((value >> 10) & mask);
1✔
138
                        out = decoded;
1✔
139
                        return true;
1✔
140
                    default:
141
                        return false;
142
                }
143
            }
144
            else
145
                return false;
146

147
            cursor++;
50✔
148
        }
149

150
        decoded.push_back((value >> 16) & mask);
12✔
151
        decoded.push_back((value >> 8) & mask);
12✔
152
        decoded.push_back((value >> 0) & mask);
12✔
153
    }
154

155
    out = decoded;
2✔
156
    return true;
2✔
157
}
158

159
} // namespace system
160
} // namespace libbitcoin
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc