添加项目文件。
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
#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
|
||||
Reference in New Issue
Block a user