55#include < array>
66#include < stdexcept>
77#include < string>
8- #include < vector>
8+
9+ #include " string_types.h"
910
1011#ifdef __has_cpp_attribute
1112#if __has_cpp_attribute(fallthrough)
@@ -37,10 +38,7 @@ namespace jwt {
3738 ' w' , ' x' , ' y' , ' z' , ' 0' , ' 1' , ' 2' , ' 3' , ' 4' , ' 5' , ' 6' , ' 7' , ' 8' , ' 9' , ' +' , ' /' }};
3839 return data;
3940 }
40- static const std::string& fill () {
41- static std::string fill{" =" };
42- return fill;
43- }
41+ static std::array<string_constant, 1 > fill () { return std::array<string_constant, 1 >{" =" }; }
4442 };
4543 /* *
4644 * \brief valid list of character when working with [Base64URL](https://tools.ietf.org/html/rfc4648#section-5)
@@ -60,10 +58,7 @@ namespace jwt {
6058 ' w' , ' x' , ' y' , ' z' , ' 0' , ' 1' , ' 2' , ' 3' , ' 4' , ' 5' , ' 6' , ' 7' , ' 8' , ' 9' , ' -' , ' _' }};
6159 return data;
6260 }
63- static const std::string& fill () {
64- static std::string fill{" %3d" };
65- return fill;
66- }
61+ static std::array<string_constant, 1 > fill () { return std::array<string_constant, 1 >{" %3d" }; }
6762 };
6863 namespace helper {
6964 /* *
@@ -81,15 +76,15 @@ namespace jwt {
8176 ' w' , ' x' , ' y' , ' z' , ' 0' , ' 1' , ' 2' , ' 3' , ' 4' , ' 5' , ' 6' , ' 7' , ' 8' , ' 9' , ' -' , ' _' }};
8277 return data;
8378 }
84- static const std::initializer_list<std::string>& fill () {
85- static std::initializer_list<std::string> fill{" %3D" , " %3d" };
86- return fill;
87- }
79+ static std::array<string_constant, 2 > fill () { return std::array<string_constant, 2 >{" %3D" , " %3d" }; }
8880 };
8981 } // namespace helper
9082
9183 inline uint32_t index (const std::array<char , 64 >& alphabet, char symbol) {
92- auto itr = std::find_if (alphabet.cbegin (), alphabet.cend (), [symbol](char c) { return c == symbol; });
84+ if (symbol >= ' A' && symbol <= ' Z' ) { return static_cast <uint32_t >(symbol - ' A' ); }
85+ if (symbol >= ' a' && symbol <= ' z' ) { return static_cast <uint32_t >(26 + symbol - ' a' ); }
86+ if (symbol >= ' 0' && symbol <= ' 9' ) { return static_cast <uint32_t >(52 + symbol - ' 0' ); }
87+ auto itr = std::find (std::next (alphabet.cbegin (), 62U ), alphabet.cend (), symbol);
9388 if (itr == alphabet.cend ()) { throw std::runtime_error (" Invalid input: not within alphabet" ); }
9489
9590 return std::distance (alphabet.cbegin (), itr);
@@ -116,30 +111,31 @@ namespace jwt {
116111 }
117112 };
118113
119- inline padding count_padding (const std::string& base, const std::vector<std::string>& fills) {
120- for (const auto & fill : fills) {
121- if (base.size () < fill.size ()) continue ;
114+ template <class StrInputIt >
115+ padding count_padding (string_view base, StrInputIt fillStart, StrInputIt fillEnd) {
116+ for (StrInputIt fillIt = fillStart; fillIt != fillEnd; ++fillIt) {
117+ int fillLen = static_cast <int >(fillIt->size ());
118+ int deltaLen = static_cast <int >(base.size ()) - fillLen;
122119 // Does the end of the input exactly match the fill pattern?
123- if (base.substr (base. size () - fill. size ()) == fill ) {
124- return padding{1 , fill. length ( )} +
125- count_padding (base.substr (0 , base. size () - fill. size ()), fills );
120+ if (deltaLen >= 0 && base.substr (deltaLen) == *fillIt ) {
121+ return padding{1 , static_cast < size_t >(fillLen )} +
122+ count_padding (base.substr (0 , deltaLen), fillStart, fillEnd );
126123 }
127124 }
128125
129126 return {};
130127 }
131128
132- inline std::string encode (const std::string& bin, const std::array<char , 64 >& alphabet,
133- const std::string& fill) {
129+ inline std::string encode (string_view bin, const std::array<char , 64 >& alphabet, string_view fill) {
134130 size_t size = bin.size ();
135131 std::string res;
136132
137133 // clear incomplete bytes
138134 size_t fast_size = size - size % 3 ;
139- for (size_t i = 0 ; i < fast_size;) {
140- uint32_t octet_a = static_cast <unsigned char >(bin[i++ ]);
141- uint32_t octet_b = static_cast <unsigned char >(bin[i++ ]);
142- uint32_t octet_c = static_cast <unsigned char >(bin[i++ ]);
135+ for (size_t i = 0 ; i < fast_size; i += 3 ) {
136+ uint32_t octet_a = static_cast <unsigned char >(bin[i]);
137+ uint32_t octet_b = static_cast <unsigned char >(bin[i + 1 ]);
138+ uint32_t octet_c = static_cast <unsigned char >(bin[i + 2 ]);
143139
144140 uint32_t triple = (octet_a << 0x10 ) + (octet_b << 0x08 ) + octet_c;
145141
@@ -178,9 +174,10 @@ namespace jwt {
178174 return res;
179175 }
180176
181- inline std::string decode (const std::string& base, const std::array<char , 64 >& alphabet,
182- const std::vector<std::string>& fill) {
183- const auto pad = count_padding (base, fill);
177+ template <class StrInputIt >
178+ inline std::string decode (string_view base, const std::array<char , 64 >& alphabet, StrInputIt fillStart,
179+ StrInputIt fillEnd) {
180+ const auto pad = count_padding (base, fillStart, fillEnd);
184181 if (pad.count > 2 ) throw std::runtime_error (" Invalid input: too much fill" );
185182
186183 const size_t size = base.size () - pad.length ;
@@ -224,44 +221,42 @@ namespace jwt {
224221 return res;
225222 }
226223
227- inline std::string decode (const std::string& base, const std::array<char , 64 >& alphabet,
228- const std::string& fill) {
229- return decode (base, alphabet, std::vector<std::string>{fill});
230- }
231-
232- inline std::string pad (const std::string& base, const std::string& fill) {
233- std::string padding;
234- switch (base.size () % 4 ) {
235- case 1 : padding += fill; JWT_FALLTHROUGH;
236- case 2 : padding += fill; JWT_FALLTHROUGH;
237- case 3 : padding += fill; JWT_FALLTHROUGH;
224+ inline std::string pad (string_view base, string_view fill) {
225+ std::string res (base);
226+ switch (res.size () % 4 ) {
227+ case 1 : res += fill; JWT_FALLTHROUGH;
228+ case 2 : res += fill; JWT_FALLTHROUGH;
229+ case 3 : res += fill; JWT_FALLTHROUGH;
238230 default : break ;
239231 }
240-
241- return base + padding;
232+ return res;
242233 }
243234
244- inline std::string trim (const std::string& base, const std::string& fill) {
235+ inline std::string trim (string_view base, string_view fill) {
245236 auto pos = base.find (fill);
246- return base.substr (0 , pos);
237+ return static_cast <std::string>( base.substr (0 , pos) );
247238 }
248239 } // namespace details
249240
250241 template <typename T>
251- std::string encode (const std::string& bin) {
252- return details::encode (bin, T::data (), T::fill ());
242+ std::string encode (string_view bin) {
243+ static const auto fills = T::fill ();
244+ return details::encode (bin, T::data (), fills.front ());
253245 }
254246 template <typename T>
255- std::string decode (const std::string& base) {
256- return details::decode (base, T::data (), T::fill ());
247+ std::string decode (string_view base) {
248+ static const auto fills = T::fill ();
249+ return details::decode (base, T::data (), fills.begin (), fills.end ());
257250 }
258251 template <typename T>
259- std::string pad (const std::string& base) {
260- return details::pad (base, T::fill ());
252+ std::string pad (string_view base) {
253+ static const auto fills = T::fill ();
254+ return details::pad (base, fills.front ());
261255 }
262256 template <typename T>
263- std::string trim (const std::string& base) {
264- return details::trim (base, T::fill ());
257+ std::string trim (string_view base) {
258+ static const auto fills = T::fill ();
259+ return details::trim (base, fills.front ());
265260 }
266261 } // namespace base
267262} // namespace jwt
0 commit comments