/src/CMake/Source/cmBase32.cxx
Line | Count | Source |
1 | | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
2 | | file LICENSE.rst or https://cmake.org/licensing for details. */ |
3 | | #include "cmBase32.h" |
4 | | |
5 | | // -- Static functions |
6 | | |
7 | | static unsigned char const Base32EncodeTable[33] = |
8 | | "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; |
9 | | |
10 | | inline unsigned char Base32EncodeChar(int schar) |
11 | 0 | { |
12 | 0 | return Base32EncodeTable[schar]; |
13 | 0 | } |
14 | | |
15 | | static void Base32Encode5(unsigned char const src[5], char dst[8]) |
16 | 0 | { |
17 | | // [0]:5 bits |
18 | 0 | dst[0] = Base32EncodeChar((src[0] >> 3) & 0x1F); |
19 | | // [0]:3 bits + [1]:2 bits |
20 | 0 | dst[1] = Base32EncodeChar(((src[0] << 2) & 0x1C) + ((src[1] >> 6) & 0x03)); |
21 | | // [1]:5 bits |
22 | 0 | dst[2] = Base32EncodeChar((src[1] >> 1) & 0x1F); |
23 | | // [1]:1 bit + [2]:4 bits |
24 | 0 | dst[3] = Base32EncodeChar(((src[1] << 4) & 0x10) + ((src[2] >> 4) & 0x0F)); |
25 | | // [2]:4 bits + [3]:1 bit |
26 | 0 | dst[4] = Base32EncodeChar(((src[2] << 1) & 0x1E) + ((src[3] >> 7) & 0x01)); |
27 | | // [3]:5 bits |
28 | 0 | dst[5] = Base32EncodeChar((src[3] >> 2) & 0x1F); |
29 | | // [3]:2 bits + [4]:3 bit |
30 | 0 | dst[6] = Base32EncodeChar(((src[3] << 3) & 0x18) + ((src[4] >> 5) & 0x07)); |
31 | | // [4]:5 bits |
32 | 0 | dst[7] = Base32EncodeChar((src[4] << 0) & 0x1F); |
33 | 0 | } |
34 | | |
35 | | // -- Class methods |
36 | | |
37 | 0 | cmBase32Encoder::cmBase32Encoder() = default; |
38 | | |
39 | | std::string cmBase32Encoder::encodeString(unsigned char const* input, |
40 | | size_t len, bool padding) |
41 | 0 | { |
42 | 0 | std::string res; |
43 | |
|
44 | 0 | static size_t const blockSize = 5; |
45 | 0 | static size_t const bufferSize = 8; |
46 | 0 | char buffer[bufferSize]; |
47 | |
|
48 | 0 | unsigned char const* end = input + len; |
49 | 0 | while ((input + blockSize) <= end) { |
50 | 0 | Base32Encode5(input, buffer); |
51 | 0 | res.append(buffer, bufferSize); |
52 | 0 | input += blockSize; |
53 | 0 | } |
54 | |
|
55 | 0 | size_t remain = static_cast<size_t>(end - input); |
56 | 0 | if (remain != 0) { |
57 | | // Temporary source buffer filled up with 0s |
58 | 0 | unsigned char padded[blockSize]; |
59 | 0 | for (size_t ii = 0; ii != remain; ++ii) { |
60 | 0 | padded[ii] = input[ii]; |
61 | 0 | } |
62 | 0 | for (size_t ii = remain; ii != blockSize; ++ii) { |
63 | 0 | padded[ii] = 0; |
64 | 0 | } |
65 | |
|
66 | 0 | Base32Encode5(padded, buffer); |
67 | 0 | size_t numPad(0); |
68 | 0 | switch (remain) { |
69 | 0 | case 1: |
70 | 0 | numPad = 6; |
71 | 0 | break; |
72 | 0 | case 2: |
73 | 0 | numPad = 4; |
74 | 0 | break; |
75 | 0 | case 3: |
76 | 0 | numPad = 3; |
77 | 0 | break; |
78 | 0 | case 4: |
79 | 0 | numPad = 1; |
80 | 0 | break; |
81 | 0 | default: |
82 | 0 | break; |
83 | 0 | } |
84 | 0 | res.append(buffer, bufferSize - numPad); |
85 | 0 | if (padding) { |
86 | 0 | for (size_t ii = 0; ii != numPad; ++ii) { |
87 | 0 | res.push_back(paddingChar); |
88 | 0 | } |
89 | 0 | } |
90 | 0 | } |
91 | | |
92 | 0 | return res; |
93 | 0 | } |