• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 // Functions for encoding and decoding data in Base64 as specified by RFC 3548
16 // and RFC 4648. See https://tools.ietf.org/html/rfc4648
17 #pragma once
18 
19 #include <stdbool.h>
20 #include <stddef.h>
21 
22 // C-compatible versions of a subset of the pw_base64 module.
23 #ifdef __cplusplus
24 extern "C" {
25 #endif  // __cplusplus
26 
27 // Returns the size of the given number of bytes when encoded as Base64. Base64
28 //
29 // Equivalent to pw::base64::EncodedSize().
30 #define PW_BASE64_ENCODED_SIZE(binary_size_bytes) \
31   (((size_t)binary_size_bytes + 2) / 3 * 4)  // +2 to round up to a 3-byte group
32 
33 // Encodes the provided data in Base64 and writes the result to the buffer.
34 // Exactly PW_BASE64_ENCODED_SIZE(binary_size_bytes) bytes will be written. The
35 // output buffer *MUST* be large enough for the encoded output!
36 //
37 // Equivalent to pw::base64::Encode().
38 void pw_Base64Encode(const void* binary_data,
39                      const size_t binary_size_bytes,
40                      char* output);
41 
42 // Evaluates to the maximum size of decoded Base64 data in bytes.
43 //
44 // Equivalent to pw::base64::MaxDecodedSize().
45 #define PW_BASE64_MAX_DECODED_SIZE(base64_size_bytes) \
46   (((size_t)base64_size_bytes) / 4 * 3)
47 
48 // Decodes the provided Base64 data into raw binary. The output buffer *MUST* be
49 // at least PW_BASE64_MAX_DECODED_SIZE bytes large.
50 //
51 // Equivalent to pw::base64::Decode().
52 size_t pw_Base64Decode(const char* base64,
53                        size_t base64_size_bytes,
54                        void* output);
55 
56 // Returns true if the provided string is valid Base64 encoded data. Accepts
57 // either the standard (+/) or URL-safe (-_) alphabets.
58 //
59 // Equivalent to pw::base64::IsValid().
60 bool pw_Base64IsValid(const char* base64_data, size_t base64_size);
61 
62 // C++ API, which uses the C functions internally.
63 #ifdef __cplusplus
64 }  // extern "C"
65 
66 #include <span>
67 #include <string_view>
68 #include <type_traits>
69 
70 namespace pw::base64 {
71 
72 // Returns the size of the given number of bytes when encoded as Base64. Base64
73 // encodes 3-byte groups into 4-character strings. The final group is padded to
74 // be 3-bytes if it only has 1 or 2.
EncodedSize(size_t binary_size_bytes)75 constexpr size_t EncodedSize(size_t binary_size_bytes) {
76   return PW_BASE64_ENCODED_SIZE(binary_size_bytes);
77 }
78 
79 // Encodes the provided data in Base64 and writes the result to the buffer.
80 // Encodes to the standard alphabet with + and / for characters 62 and 63.
81 // Exactly EncodedSize(binary_size_bytes) bytes will be written. The
82 // output buffer *MUST* be large enough for the encoded output! The input and
83 // output buffers MUST NOT be the same; encoding cannot occur in place.
84 //
85 // The resulting string in the output is NOT null-terminated!
Encode(std::span<const std::byte> binary,char * output)86 inline void Encode(std::span<const std::byte> binary, char* output) {
87   pw_Base64Encode(binary.data(), binary.size_bytes(), output);
88 }
89 
90 // Encodes the provided data in Base64 if the result fits in the provided
91 // buffer. Returns the number of bytes written, which will be 0 if the output
92 // buffer is too small.
93 size_t Encode(std::span<const std::byte> binary, std::span<char> output_buffer);
94 
95 // Returns the maximum size of decoded Base64 data in bytes. base64_size_bytes
96 // must be a multiple of 4, since Base64 encodes 3-byte groups into 4-character
97 // strings. If the last 3-byte group has padding, the actual decoded size would
98 // be 1 or 2 bytes less than MaxDecodedSize.
MaxDecodedSize(size_t base64_size_bytes)99 constexpr size_t MaxDecodedSize(size_t base64_size_bytes) {
100   return PW_BASE64_MAX_DECODED_SIZE(base64_size_bytes);
101 }
102 
103 // Decodes the provided Base64 data into raw binary. The output buffer *MUST* be
104 // at least MaxDecodedSize bytes large. The output buffer may be the same as the
105 // input buffer; decoding can occur in place. Returns the number of bytes that
106 // were decoded.
107 //
108 // Decodes either standard (+/) or URL-safe (-_) alphabets. The data must be
109 // padded to 4-character blocks with =. This function does NOT check that the
110 // input is valid! Use IsValid or the four-argument overload to check the
111 // input formatting.
Decode(std::string_view base64,void * output)112 inline size_t Decode(std::string_view base64, void* output) {
113   return pw_Base64Decode(base64.data(), base64.size(), output);
114 }
115 
116 // Decodes the provided Base64 data, if the data is valid and fits in the output
117 // buffer. Returns the number of bytes written, which will be 0 if the data is
118 // invalid or doesn't fit.
119 size_t Decode(std::string_view base64, std::span<std::byte> output_buffer);
120 
121 // Returns true if the provided string is valid Base64 encoded data. Accepts
122 // either the standard (+/) or URL-safe (-_) alphabets.
IsValid(std::string_view base64)123 inline bool IsValid(std::string_view base64) {
124   return pw_Base64IsValid(base64.data(), base64.size());
125 }
126 
127 }  // namespace pw::base64
128 
129 #endif  // __cplusplus
130