Files
2026-06-30 17:46:34 +08:00

140 lines
3.7 KiB
C++

#pragma once
// base36_codec.hpp
#ifndef BASE36_CODEC_HPP
#define BASE36_CODEC_HPP
#include <string>
#include <cctype>
#include <limits>
#include <charconv>
//By ChatGPT: 1:1 converted from base36 library source code
namespace basecodec
{
// Base36 alphabet
inline constexpr const char* base36_alphabet = "0123456789abcdefghijklmnopqrstuvwxyz";
// Python: line 17
// def dumps(number):
inline bool encodeBase36(int64_t number, std::string& result) noexcept
{
result.clear();
// Python: line 23
if (number < 0)
{
std::string positive;
if (!encodeBase36(-number, positive))
return false;
result = '-' + positive;
return true;
}
// Python: line 26
if (number == 0)
{
result = "0";
return true;
}
std::string value;
while (number != 0)
{
int remainder = number % 36;
number /= 36;
value.insert(value.begin(), base36_alphabet[remainder]);
}
result = std::move(value);
return true;
}
inline bool encodeBase36FromDecimalString(const std::string& decimalStr, std::string& base36Out) noexcept
{
uint64_t number = 0;
auto [ptr, ec] = std::from_chars(decimalStr.data(), decimalStr.data() + decimalStr.size(), number, 10);
if (ec != std::errc())
return false;
static const char alphabet[] = "0123456789abcdefghijklmnopqrstuvwxyz";
std::string result;
do
{
result.insert(result.begin(), alphabet[number % 36]);
number /= 36;
}
while (number != 0);
base36Out = result;
return true;
}
// Python: line 35
// def loads(value):
inline bool decodeBase36(const std::string& input, int64_t& number) noexcept
{
// Validate input: allow optional leading '-', rest must be base36 chars
size_t start = 0;
bool negative = false;
if (!input.empty() && input[0] == '-')
{
negative = true;
start = 1;
}
if (start == input.size())
return false; // "-" alone is invalid
number = 0;
for (size_t i = start; i < input.size(); ++i)
{
char c = std::tolower(input[i]);
int digit;
if (c >= '0' && c <= '9')
digit = c - '0';
else if (c >= 'a' && c <= 'z')
digit = c - 'a' + 10;
else
return false; // invalid character
#pragma push_macro("max")
#undef max
if (number > (std::numeric_limits<int64_t>::max() - digit) / 36)
return false; // overflow
#pragma pop_macro("max")
number = number * 36 + digit;
}
if (negative)
number = -number;
return true;
}
inline bool decodeBase36ToDecimalString(const std::string& base36Str, std::string& decimalOut) noexcept
{
uint64_t number = 0;
for (char c : base36Str)
{
int digit = 0;
if (c >= '0' && c <= '9')
digit = c - '0';
else if (c >= 'a' && c <= 'z')
digit = c - 'a' + 10;
else if (c >= 'A' && c <= 'Z')
digit = c - 'A' + 10; // case-insensitive
else
return false; // invalid character
if (digit >= 36)
return false;
number = number * 36 + digit;
}
// Convert number to string using std::to_string
decimalOut = std::to_string(number);
return true;
}
} // namespace basecodec
#endif // BASE36_CODEC_HPP