158 lines
6.3 KiB
C++
158 lines
6.3 KiB
C++
#include "prx/libc/include/general/VabiMacros.hpp"
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <iterator>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
|
|
namespace GuestRune {
|
|
|
|
struct Range {
|
|
std::int32_t count;
|
|
void* entries;
|
|
};
|
|
|
|
struct Locale {
|
|
char magic[8];
|
|
char encoding[32];
|
|
void* getRune;
|
|
void* putRune;
|
|
std::int32_t invalidRune;
|
|
std::uint64_t types[256];
|
|
std::int32_t lower[256];
|
|
std::int32_t upper[256];
|
|
Range typeRanges;
|
|
Range lowerRanges;
|
|
Range upperRanges;
|
|
void* variable;
|
|
std::int32_t variableLength;
|
|
};
|
|
static_assert(offsetof(Locale, invalidRune) == 56);
|
|
static_assert(offsetof(Locale, types) == 64);
|
|
static_assert(offsetof(Locale, lower) == 2112);
|
|
static_assert(offsetof(Locale, upper) == 3136);
|
|
static_assert(offsetof(Locale, typeRanges) == 4160);
|
|
static_assert(offsetof(Locale, variable) == 4208);
|
|
static_assert(sizeof(Locale) == 4224);
|
|
|
|
constexpr std::uint64_t Alpha = 0x100;
|
|
constexpr std::uint64_t Control = 0x200;
|
|
constexpr std::uint64_t Digit = 0x400;
|
|
constexpr std::uint64_t Graph = 0x800;
|
|
constexpr std::uint64_t Lower = 0x1000;
|
|
constexpr std::uint64_t Punct = 0x2000;
|
|
constexpr std::uint64_t Space = 0x4000;
|
|
constexpr std::uint64_t Upper = 0x8000;
|
|
constexpr std::uint64_t Hex = 0x10000;
|
|
constexpr std::uint64_t Blank = 0x20000;
|
|
constexpr std::uint64_t Print = 0x40000;
|
|
constexpr std::uint64_t Number = 0x400000;
|
|
|
|
constexpr std::uint64_t Type(int c) {
|
|
if (c == '\t') return Control | Space | Blank;
|
|
if (c >= '\n' && c <= '\r') return Control | Space;
|
|
if (c < ' ' || c == 0x7f) return Control;
|
|
if (c == ' ') return Space | Blank | Print;
|
|
if (c >= '0' && c <= '9') return Digit | Print | Graph | Hex | Number | static_cast<std::uint64_t>(c - '0');
|
|
if (c >= 'A' && c <= 'F') return Upper | Hex | Print | Graph | Alpha | static_cast<std::uint64_t>(c - 'A' + 10);
|
|
if (c >= 'a' && c <= 'f') return Lower | Hex | Print | Graph | Alpha | static_cast<std::uint64_t>(c - 'a' + 10);
|
|
if (c >= 'A' && c <= 'Z') return Upper | Print | Graph | Alpha;
|
|
if (c >= 'a' && c <= 'z') return Lower | Print | Graph | Alpha;
|
|
if (c < 0x7f) return Punct | Print | Graph;
|
|
return 0;
|
|
}
|
|
|
|
constexpr Locale MakeDefault() {
|
|
Locale locale{{'R', 'u', 'n', 'e', 'M', 'a', 'g', 'i'}, "NONE", nullptr, nullptr, 0xfffd, {}, {}, {}, {}, {}, {}, nullptr, 0};
|
|
for (int c = 0; c < 256; ++c) {
|
|
locale.types[c] = Type(c);
|
|
locale.lower[c] = c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c;
|
|
locale.upper[c] = c >= 'a' && c <= 'z' ? c - ('a' - 'A') : c;
|
|
}
|
|
return locale;
|
|
}
|
|
|
|
}
|
|
|
|
extern "C" {
|
|
|
|
extern const GuestRune::Locale _DefaultRuneLocale_nid_postfix;
|
|
const GuestRune::Locale _DefaultRuneLocale_nid_postfix = GuestRune::MakeDefault();
|
|
const GuestRune::Locale* _CurrentRuneLocale_nid_postfix = &_DefaultRuneLocale_nid_postfix;
|
|
int __mb_sb_limit_nid_postfix = 256;
|
|
|
|
}
|
|
|
|
namespace GuestRune {
|
|
|
|
constexpr std::uint32_t Weof = 0xffffffff;
|
|
|
|
int Is(std::uint32_t c, std::uint64_t mask) {
|
|
return c < 256 && (_CurrentRuneLocale_nid_postfix->types[c] & mask) != 0;
|
|
}
|
|
|
|
}
|
|
|
|
extern "C" {
|
|
|
|
int APS5_VABI iswalnum_nid_postfix(std::uint32_t c) { return GuestRune::Is(c, GuestRune::Alpha | GuestRune::Number); }
|
|
int APS5_VABI iswalpha_nid_postfix(std::uint32_t c) { return GuestRune::Is(c, GuestRune::Alpha); }
|
|
int APS5_VABI iswblank_nid_postfix(std::uint32_t c) { return GuestRune::Is(c, GuestRune::Blank); }
|
|
int APS5_VABI iswcntrl_nid_postfix(std::uint32_t c) { return GuestRune::Is(c, GuestRune::Control); }
|
|
int APS5_VABI iswdigit_nid_postfix(std::uint32_t c) { return GuestRune::Is(c, GuestRune::Digit); }
|
|
int APS5_VABI iswgraph_nid_postfix(std::uint32_t c) { return GuestRune::Is(c, GuestRune::Graph); }
|
|
int APS5_VABI iswlower_nid_postfix(std::uint32_t c) { return GuestRune::Is(c, GuestRune::Lower); }
|
|
int APS5_VABI iswprint_nid_postfix(std::uint32_t c) { return GuestRune::Is(c, GuestRune::Print); }
|
|
int APS5_VABI iswpunct_nid_postfix(std::uint32_t c) { return GuestRune::Is(c, GuestRune::Punct); }
|
|
int APS5_VABI iswspace_nid_postfix(std::uint32_t c) { return GuestRune::Is(c, GuestRune::Space); }
|
|
int APS5_VABI iswupper_nid_postfix(std::uint32_t c) { return GuestRune::Is(c, GuestRune::Upper); }
|
|
int APS5_VABI iswxdigit_nid_postfix(std::uint32_t c) { return GuestRune::Is(c, GuestRune::Hex); }
|
|
int APS5_VABI iswctype_nid_postfix(std::uint32_t c, std::uint64_t mask) { return GuestRune::Is(c, mask); }
|
|
|
|
int APS5_VABI _Iswctype_nid_postfix(std::uint32_t c, std::uint64_t type) {
|
|
static constexpr std::uint64_t masks[] = {
|
|
GuestRune::Alpha | GuestRune::Number, GuestRune::Alpha, GuestRune::Control, GuestRune::Digit,
|
|
GuestRune::Graph, GuestRune::Lower, GuestRune::Print, GuestRune::Punct,
|
|
GuestRune::Space, GuestRune::Upper, GuestRune::Hex, GuestRune::Blank,
|
|
};
|
|
if (type == 0 || type > std::size(masks)) throw std::invalid_argument("_Iswctype: unknown class " + std::to_string(type));
|
|
return GuestRune::Is(c, masks[type - 1]);
|
|
}
|
|
|
|
std::uint64_t APS5_VABI wctype_nid_postfix(const char* property) {
|
|
static constexpr struct {
|
|
const char* name;
|
|
std::uint64_t mask;
|
|
} properties[] = {
|
|
{"alnum", GuestRune::Alpha | GuestRune::Number}, {"alpha", GuestRune::Alpha}, {"blank", GuestRune::Blank},
|
|
{"cntrl", GuestRune::Control}, {"digit", GuestRune::Digit}, {"graph", GuestRune::Graph},
|
|
{"lower", GuestRune::Lower}, {"print", GuestRune::Print}, {"punct", GuestRune::Punct},
|
|
{"space", GuestRune::Space}, {"upper", GuestRune::Upper}, {"xdigit", GuestRune::Hex},
|
|
{"ideogram", 0x80000}, {"special", 0x100000}, {"phonogram", 0x200000},
|
|
{"number", GuestRune::Number}, {"rune", 0xffffff00},
|
|
};
|
|
for (const auto& entry : properties) {
|
|
if (std::strcmp(property, entry.name) == 0) return entry.mask;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
std::uint32_t APS5_VABI towlower_nid_postfix(std::uint32_t c) {
|
|
return c < 256 ? static_cast<std::uint32_t>(_CurrentRuneLocale_nid_postfix->lower[c]) : c;
|
|
}
|
|
|
|
std::uint32_t APS5_VABI towupper_nid_postfix(std::uint32_t c) {
|
|
return c < 256 ? static_cast<std::uint32_t>(_CurrentRuneLocale_nid_postfix->upper[c]) : c;
|
|
}
|
|
|
|
std::uint32_t APS5_VABI btowc_nid_postfix(int c) {
|
|
return c == -1 ? GuestRune::Weof : static_cast<unsigned char>(c);
|
|
}
|
|
|
|
int APS5_VABI wctob_nid_postfix(std::uint32_t c) {
|
|
return c < 256 ? static_cast<int>(c) : -1;
|
|
}
|
|
|
|
}
|