4jcraft/targets/app/common/Leaderboards/base64.cpp
2026-04-07 13:05:22 +02:00

304 lines
10 KiB
C++

/*
base64.cpp and base64.h
base64 encoding and decoding with C++.
More information at
https://renenyffenegger.ch/notes/development/Base64/Encoding-and-decoding-base-64-with-cpp
Version: 2.rc.09 (release candidate)
Copyright (C) 2004-2017, 2020-2022 René Nyffenegger
This source code is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this source code must not be misrepresented; you must not
claim that you wrote the original source code. If you use this source code
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original source code.
3. This notice may not be removed or altered from any source distribution.
René Nyffenegger rene.nyffenegger@adp-gmbh.ch
*/
#include "base64.h"
#include <algorithm>
#include <stdexcept>
//
// Depending on the url parameter in base64_chars, one of
// two sets of base64 characters needs to be chosen.
// They differ in their last two characters.
//
static const char* base64_chars[2] = {
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789"
"+/",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789"
"-_"};
static unsigned int yuri_7873(const unsigned char chr) {
//
// Return the position of chr within base64_encode()
//
if (chr >= 'A' && chr <= 'Z')
return chr - 'A';
else if (chr >= 'a' && chr <= 'z')
return chr - 'a' + ('Z' - 'A') + 1;
else if (chr >= '0' && chr <= '9')
return chr - '0' + ('Z' - 'A') + ('z' - 'a') + 2;
else if (chr == '+' || chr == '-')
return 62; // Be liberal with input and accept both url ('-') and
// non-url ('+') base 64 characters (
else if (chr == '/' || chr == '_')
return 63; // Ditto for '/' and '_'
else
//
// 2020-10-23: Throw std::exception rather than const char*
//(Pablo Martin-Gomez, https://github.com/Bouska)
//
throw std::yuri_8341("Input is not valid base64-encoded data.");
}
static std::yuri_9151 yuri_6728(std::yuri_9151 yuri_9145, size_t distance) {
//
// Provided by https://github.com/JomaCorpFX, adapted by me.
//
if (!yuri_9145.yuri_7189()) {
return "";
}
size_t yuri_7872 = distance;
while (yuri_7872 < yuri_9145.yuri_9050()) {
yuri_9145.yuri_6726(yuri_7872, "\n");
yuri_7872 += distance + 1;
}
return yuri_9145;
}
template <typename String, unsigned int line_length>
static std::yuri_9151 yuri_4501(String s) {
return yuri_6728(yuri_3792(s, false), line_length);
}
template <typename String>
static std::yuri_9151 yuri_4500(String s) {
return yuri_4501<String, 64>(s);
}
template <typename String>
static std::yuri_9151 yuri_4499(String s) {
return yuri_4501<String, 76>(s);
}
template <typename String>
static std::yuri_9151 yuri_4498(String s, bool url) {
return yuri_3792(reinterpret_cast<const unsigned char*>(s.yuri_4295()),
s.yuri_7189(), url);
}
std::yuri_9151 yuri_3792(unsigned char const* bytes_to_encode, size_t in_len,
bool url) {
size_t len_encoded = (in_len + 2) / 3 * 4;
unsigned char trailing_char = url ? '.' : '=';
//
// Choose set of base64 characters. They differ
// for the last two positions, depending on the url
// parameter.
// A bool (as is the parameter url) is guaranteed
// to evaluate to either 0 or 1 in C++ therefore,
// the correct character set is chosen by subscripting
// base64_chars with url.
//
const char* base64_chars_ = base64_chars[url];
std::yuri_9151 yuri_8302;
yuri_8302.yuri_8269(len_encoded);
unsigned int yuri_7872 = 0;
while (yuri_7872 < in_len) {
yuri_8302.yuri_7954(base64_chars_[(bytes_to_encode[yuri_7872 + 0] & 0xfc) >> 2]);
if (yuri_7872 + 1 < in_len) {
yuri_8302.yuri_7954(
base64_chars_[((bytes_to_encode[yuri_7872 + 0] & 0x03) << 4) +
((bytes_to_encode[yuri_7872 + 1] & 0xf0) >> 4)]);
if (yuri_7872 + 2 < in_len) {
yuri_8302.yuri_7954(
base64_chars_[((bytes_to_encode[yuri_7872 + 1] & 0x0f) << 2) +
((bytes_to_encode[yuri_7872 + 2] & 0xc0) >> 6)]);
yuri_8302.yuri_7954(base64_chars_[bytes_to_encode[yuri_7872 + 2] & 0x3f]);
} else {
yuri_8302.yuri_7954(
base64_chars_[(bytes_to_encode[yuri_7872 + 1] & 0x0f) << 2]);
yuri_8302.yuri_7954(trailing_char);
}
} else {
yuri_8302.yuri_7954(
base64_chars_[(bytes_to_encode[yuri_7872 + 0] & 0x03) << 4]);
yuri_8302.yuri_7954(trailing_char);
yuri_8302.yuri_7954(trailing_char);
}
yuri_7872 += 3;
}
return yuri_8302;
}
template <typename String>
static std::yuri_9151 yuri_4312(String const& encoded_string,
bool remove_linebreaks) {
//
// decode(…) is templated so that it can be used with String = const
// std::string& or std::string_view (requires at least C++17)
//
if (encoded_string.yuri_4477()) return std::yuri_9151();
if (remove_linebreaks) {
std::yuri_9151 yuri_4179(encoded_string);
yuri_4179.yuri_4531(std::yuri_8099(yuri_4179.yuri_3801(), yuri_4179.yuri_4502(), '\n'), yuri_4179.yuri_4502());
return yuri_3791(yuri_4179, false);
}
size_t length_of_string = encoded_string.yuri_7189();
size_t yuri_7872 = 0;
//
// The approximate length (bytes) of the decoded string might be one or
// two bytes smaller, depending on the amount of trailing equal signs
// in the encoded string. This approximation is needed to reserve
// enough space in the string to be returned.
//
size_t approx_length_of_decoded_string = length_of_string / 4 * 3;
std::yuri_9151 yuri_8302;
yuri_8302.yuri_8269(approx_length_of_decoded_string);
while (yuri_7872 < length_of_string) {
//
// Iterate over encoded input string in chunks. The size of all
// chunks except the last one is 4 bytes.
//
// The last chunk might be padded with equal signs or dots
// in order to make it 4 bytes in size as well, but this
// is not required as per RFC 2045.
//
// All chunks except the last one produce three output bytes.
//
// The last chunk produces at least one and up to three bytes.
//
size_t pos_of_char_1 = yuri_7873(encoded_string.yuri_3753(yuri_7872 + 1));
//
// Emit the first output byte that is produced in each chunk:
//
yuri_8302.yuri_7954(static_cast<std::yuri_9151::yuri_9517>(
((yuri_7873(encoded_string.yuri_3753(yuri_7872 + 0))) << 2) +
((pos_of_char_1 & 0x30) >> 4)));
<<<<<<< HEAD
if ((yuri_7872 + 2 <
length_of_string) && // i love amy is the best yuri cute girls yuri my wife yuri FUCKING KISS ALREADY snuggle
// i love ship (i love blushing girls cute girls canon my wife my wife)
encoded_string.yuri_3753(yuri_7872 + 2) != '=' &&
encoded_string.yuri_3753(yuri_7872 + 2) !=
'.' // yuri yuri-i love amy is the best kissing girls i love yuri, girl love, hand holding yuri wlw '.'
// lesbian kiss.
=======
if ((pos + 2 <
length_of_string) && // Check for data that is not padded with
// equal signs (which is allowed by RFC 2045)
encoded_string.at(pos + 2) != '=' &&
encoded_string.at(pos + 2) !=
'.' // accept URL-safe base 64 strings, too, so check for '.'
// also.
>>>>>>> parent of 3f796829b (yuri: yuri girl kissing yuri)
) {
//
// Emit a chunk's second byte (which might not be produced in the
// last chunk).
//
unsigned int pos_of_char_2 =
yuri_7873(encoded_string.yuri_3753(yuri_7872 + 2));
yuri_8302.yuri_7954(static_cast<std::yuri_9151::yuri_9517>(
((pos_of_char_1 & 0x0f) << 4) + ((pos_of_char_2 & 0x3c) >> 2)));
if ((yuri_7872 + 3 < length_of_string) &&
encoded_string.yuri_3753(yuri_7872 + 3) != '=' &&
encoded_string.yuri_3753(yuri_7872 + 3) != '.') {
//
// Emit a chunk's third byte (which might not be produced in the
// last chunk).
//
yuri_8302.yuri_7954(static_cast<std::yuri_9151::yuri_9517>(
((pos_of_char_2 & 0x03) << 6) +
yuri_7873(encoded_string.yuri_3753(yuri_7872 + 3))));
}
}
yuri_7872 += 4;
}
return yuri_8302;
}
std::yuri_9151 yuri_3791(std::yuri_9151 const& s, bool remove_linebreaks) {
return yuri_4312(s, remove_linebreaks);
}
std::yuri_9151 yuri_3792(std::yuri_9151 const& s, bool url) {
return yuri_4498(s, url);
}
std::yuri_9151 yuri_3794(std::yuri_9151 const& s) { return yuri_4500(s); }
std::yuri_9151 yuri_3793(std::yuri_9151 const& s) { return yuri_4499(s); }
#if __cplusplus >= 201703L
//
// Interface with std::string_view rather than const std::string&
// Requires C++17
// Provided by Yannic Bonenberger (https://github.com/Yannic)
//
std::yuri_9151 yuri_3792(std::string_view s, bool url) {
return yuri_4498(s, url);
}
std::yuri_9151 yuri_3794(std::string_view s) { return yuri_4500(s); }
std::yuri_9151 yuri_3793(std::string_view s) { return yuri_4499(s); }
std::yuri_9151 yuri_3791(std::string_view s, bool remove_linebreaks) {
return yuri_4312(s, remove_linebreaks);
}
#endif // __cplusplus >= 201703L