Files
SpineParticlesWeb/connector/native/encoding.cpp
T
2026-09-05 23:35:45 +08:00

107 lines
3.1 KiB
C++

#include "encoding.hpp"
#include <array>
#include <cctype>
#include <iomanip>
#include <sstream>
#include <stdexcept>
namespace connector {
std::vector<std::uint8_t> decode_base64(const std::string& value) {
static const std::string alphabet =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
std::array<int, 256> table{};
table.fill(-1);
for (std::size_t index = 0; index < alphabet.size(); ++index) {
table[static_cast<unsigned char>(alphabet[index])] = static_cast<int>(index);
}
if (value.size() % 4 != 0) throw std::runtime_error("图片数据格式无效");
std::vector<std::uint8_t> output;
output.reserve(value.size() / 4 * 3);
int accumulator = 0;
int bits = -8;
bool padding = false;
for (const unsigned char c : value) {
if (c == '=') {
padding = true;
continue;
}
if (padding || table[c] < 0) throw std::runtime_error("图片数据格式无效");
accumulator = (accumulator << 6) | table[c];
bits += 6;
if (bits >= 0) {
output.push_back(static_cast<std::uint8_t>((accumulator >> bits) & 0xff));
bits -= 8;
}
}
return output;
}
namespace {
int hex_value(char c) {
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
return -1;
}
} // namespace
std::string url_decode(const std::string& value) {
std::string output;
output.reserve(value.size());
for (std::size_t index = 0; index < value.size(); ++index) {
if (value[index] == '+') {
output.push_back(' ');
} else if (value[index] == '%' && index + 2 < value.size()) {
const int high = hex_value(value[index + 1]);
const int low = hex_value(value[index + 2]);
if (high < 0 || low < 0) throw std::runtime_error("URL 编码无效");
output.push_back(static_cast<char>((high << 4) | low));
index += 2;
} else {
output.push_back(value[index]);
}
}
return output;
}
std::string url_encode(const std::string& value) {
std::ostringstream output;
output << std::uppercase << std::hex;
for (const unsigned char c : value) {
if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
output << static_cast<char>(c);
} else {
output << '%' << std::setw(2) << std::setfill('0') << static_cast<int>(c);
}
}
return output.str();
}
std::string html_escape(const std::string& value) {
std::string output;
output.reserve(value.size());
for (const char c : value) {
switch (c) {
case '&': output += "&amp;"; break;
case '<': output += "&lt;"; break;
case '>': output += "&gt;"; break;
case '"': output += "&quot;"; break;
case '\'': output += "&#39;"; break;
default: output.push_back(c);
}
}
return output;
}
std::string trim(const std::string& value) {
std::size_t start = 0;
while (start < value.size() && std::isspace(static_cast<unsigned char>(value[start]))) ++start;
std::size_t end = value.size();
while (end > start && std::isspace(static_cast<unsigned char>(value[end - 1]))) --end;
return value.substr(start, end - start);
}
} // namespace connector