@@ -149,14 +149,22 @@ std::string Base64::toBase64(const std::vector<std::uint8_t>& bytes)
149149 return result;
150150}
151151
152- bool Base64::compareBase64 (
152+ Base64::Comparison Base64::compareBase64 (
153153 const std::vector<std::uint8_t >& bytes, std::string_view maybeEncoded) noexcept
154154{
155- if (bytes.empty () || maybeEncoded. empty () )
155+ if (bytes.empty ())
156156 {
157- return bytes.empty () && maybeEncoded.empty ();
157+ if (maybeEncoded.empty ())
158+ {
159+ return Comparison::EqualTo;
160+ }
161+ }
162+ else if (maybeEncoded.empty ())
163+ {
164+ return Comparison::GreaterThan;
158165 }
159166
167+ auto result = Comparison::EqualTo;
160168 auto itr = bytes.cbegin ();
161169 const auto itrEnd = bytes.cend ();
162170
@@ -171,18 +179,34 @@ bool Base64::compareBase64(
171179 if (((a | b | c | d) & 0xC0 ) != 0 )
172180 {
173181 // Invalid Base64 characters
174- return false ;
182+ return Comparison::InvalidBase64 ;
175183 }
176184
177- const uint32_t segment = (static_cast <uint32_t >(a) << 18 ) | (static_cast <uint32_t >(b) << 12 )
178- | (static_cast <uint32_t >(c) << 6 ) | static_cast <uint32_t >(d);
179-
180- if (itr == itrEnd || *itr++ != static_cast <std::uint8_t >((segment & 0xFF0000 ) >> 16 )
181- || itr == itrEnd || *itr++ != static_cast <std::uint8_t >((segment & 0xFF00 ) >> 8 )
182- || itr == itrEnd || *itr++ != static_cast <std::uint8_t >(segment & 0xFF ))
185+ if (Comparison::EqualTo == result)
183186 {
184- // Decoded bytes did not match
185- return false ;
187+ const uint32_t segment = (static_cast <uint32_t >(a) << 18 )
188+ | (static_cast <uint32_t >(b) << 12 ) | (static_cast <uint32_t >(c) << 6 )
189+ | static_cast <uint32_t >(d);
190+ const std::array decoded { static_cast <std::uint8_t >((segment & 0xFF0000 ) >> 16 ),
191+ static_cast <std::uint8_t >((segment & 0xFF00 ) >> 8 ),
192+ static_cast <std::uint8_t >(segment & 0xFF ) };
193+
194+ for (auto value : decoded)
195+ {
196+ if (itr == itrEnd)
197+ {
198+ result = Comparison::LessThan;
199+ break ;
200+ }
201+
202+ if (*itr != value)
203+ {
204+ result = *itr < value ? Comparison::LessThan : Comparison::GreaterThan;
205+ break ;
206+ }
207+
208+ ++itr;
209+ }
186210 }
187211
188212 maybeEncoded = maybeEncoded.substr (4 );
@@ -199,55 +223,81 @@ bool Base64::compareBase64(
199223 if (((a | b | c) & 0xC0 ) != 0 || (c & 0x3 ) != 0 )
200224 {
201225 // Invalid Base64 characters or padding
202- return false ;
226+ return Comparison::InvalidBase64 ;
203227 }
204228
205229 const uint16_t segment = (static_cast <uint16_t >(a) << 10 ) | (static_cast <uint16_t >(b) << 4 )
206230 | (static_cast <uint16_t >(c) >> 2 );
231+ const std::array decoded { static_cast <std::uint8_t >((segment & 0xFF00 ) >> 8 ),
232+ static_cast <std::uint8_t >(segment & 0xFF ) };
207233
208234 if (triplet)
209235 {
210- if (itr == itrEnd || *itr++ != static_cast <std::uint8_t >((segment & 0xFF00 ) >> 8 )
211- || itr == itrEnd || *itr++ != static_cast <std::uint8_t >(segment & 0xFF ))
236+ if (Comparison::EqualTo == result)
212237 {
213- // Decoded bytes did not match
214- return false ;
238+ for (auto value : decoded)
239+ {
240+ if (itr == itrEnd)
241+ {
242+ result = Comparison::LessThan;
243+ break ;
244+ }
245+
246+ if (*itr != value)
247+ {
248+ result = *itr < value ? Comparison::LessThan : Comparison::GreaterThan;
249+ break ;
250+ }
251+
252+ ++itr;
253+ }
215254 }
216255
217256 maybeEncoded = maybeEncoded.substr (3 );
218257 }
219258 else
220259 {
221- if ((segment & 0xFF ) != 0 )
260+ if (decoded[ 1 ] != 0 )
222261 {
223262 // Invalid padding
224- return false ;
263+ return Comparison::InvalidBase64 ;
225264 }
226265
227- if (itr == itrEnd || *itr++ != static_cast <std:: uint8_t >((segment & 0xFF00 ) >> 8 ) )
266+ if (Comparison::EqualTo == result )
228267 {
229- // Decoded byte did not match
230- return false ;
268+ if (itr == itrEnd)
269+ {
270+ result = Comparison::LessThan;
271+ }
272+ else if (*itr != decoded[0 ])
273+ {
274+ result = *itr < decoded[0 ] ? Comparison::LessThan : Comparison::GreaterThan;
275+ }
276+
277+ ++itr;
231278 }
232279
233280 maybeEncoded = maybeEncoded.substr (2 );
234281 }
235282 }
236283
237- // We should reach the end of the byte vector
238- if (itr != itrEnd)
239- {
240- return false ;
241- }
242-
243284 // Make sure anything that's left is 0 - 2 characters of padding
244285 if ((maybeEncoded.size () > 0 && padding != maybeEncoded[0 ])
245286 || (maybeEncoded.size () > 1 && padding != maybeEncoded[1 ]) || maybeEncoded.size () > 2 )
246287 {
247- return false ;
288+ return Comparison::InvalidBase64 ;
248289 }
249290
250- return true ;
291+ if (Comparison::EqualTo == result)
292+ {
293+ // We should reach the end of the byte vector
294+ if (itr != itrEnd)
295+ {
296+ result = Comparison::GreaterThan;
297+ }
298+ }
299+
300+ return result;
251301}
252302
253303bool Base64::validateBase64 (std::string_view maybeEncoded) noexcept
0 commit comments