Better support for serialization and sorting of the Token data type

This commit is contained in:
2026-02-18 23:23:59 -05:00
parent 0de2a50843
commit 1fd06f0628
6 changed files with 98 additions and 44 deletions

View File

@@ -48,19 +48,17 @@ LuaConstantReg *LuaConstantReg::All;
eng::string LuaToken::str() const {
uint64_t n = (uint64_t)value;
char buffer[20];
int pos = 19;
buffer[pos] = 0;
while (n > 0) {
uint64_t digit = (n % 36);
n /= 36;
if (digit < 10) {
buffer[--pos] = '0' + digit;
} else {
buffer[--pos] = 'a' + (digit - 10);
char buffer[13] = {};
for (int i = 11; i >= 0; i--) {
int d = n % 37;
n /= 37;
if (d >= 1 && d <= 10) {
buffer[i] = '0' + (d - 1);
} else if (d >= 11 && d <= 36) {
buffer[i] = 'a' + (d - 11);
}
}
return eng::string(buffer + pos, 19 - pos);
return eng::string(buffer);
}
static int panicf(lua_State *L) {
@@ -612,7 +610,7 @@ bool LuaCoreStack::tangetclass(LuaSlot classobj, LuaSlot tab) {
bool LuaCoreStack::issortablekey(LuaSlot s) const {
int type = lua_type(L_, s);
return (type == LUA_TBOOLEAN) || (type == LUA_TNUMBER) || (type == LUA_TSTRING);
return (type == LUA_TBOOLEAN) || (type == LUA_TNUMBER) || (type == LUA_TSTRING) || (type == LUA_TLIGHTUSERDATA);
}
void LuaCoreStack::movesortablekey(LuaSlot key, LuaCoreStack &otherstack, LuaSlot otherslot) {
@@ -633,6 +631,10 @@ void LuaCoreStack::movesortablekey(LuaSlot key, LuaCoreStack &otherstack, LuaSlo
lua_replace(otherstack.L_, otherslot);
break;
}
case LUA_TLIGHTUSERDATA:
lua_pushlightuserdata(otherstack.L_, lua_touserdata(L_, key));
lua_replace(otherstack.L_, otherslot);
break;
default:
assert(false && "movesortablekey: not a sortable key");
}
@@ -960,3 +962,35 @@ LuaDefine(keywords_finalcheckthrow, "table", kwdoc) {
return LS.result();
}
LuaDefine(unittests_token, "", "Unit tests for LuaToken encoding") {
// Test round-trip encoding for various strings.
LuaAssertStrEq(L, LuaToken("a").str(), "a");
LuaAssertStrEq(L, LuaToken("z").str(), "z");
LuaAssertStrEq(L, LuaToken("0").str(), "0");
LuaAssertStrEq(L, LuaToken("9").str(), "9");
LuaAssertStrEq(L, LuaToken("null").str(), "null");
LuaAssertStrEq(L, LuaToken("hello").str(), "hello");
LuaAssertStrEq(L, LuaToken("zzzzzzzzzzzz").str(), "zzzzzzzzzzzz");
LuaAssertStrEq(L, LuaToken("a0").str(), "a0");
LuaAssertStrEq(L, LuaToken("0a").str(), "0a");
LuaAssertStrEq(L, LuaToken("000000000000").str(), "000000000000");
// Test that empty/invalid strings produce the empty token.
LuaAssert(L, LuaToken(std::string_view("")).empty());
LuaAssert(L, LuaToken(std::string_view("hello world")).empty());
LuaAssert(L, LuaToken(std::string_view("aaaaaaaaaaaaa")).empty()); // 13 chars
// Test that numeric ordering matches lexicographic ordering.
LuaAssert(L, LuaToken("a").value > LuaToken("0").value);
LuaAssert(L, LuaToken("b").value > LuaToken("a").value);
LuaAssert(L, LuaToken("aa").value > LuaToken("a").value);
LuaAssert(L, LuaToken("ab").value > LuaToken("aa").value);
LuaAssert(L, LuaToken("b").value > LuaToken("az").value);
LuaAssert(L, LuaToken("ba").value > LuaToken("az").value);
LuaAssert(L, LuaToken("hello").value > LuaToken("hell").value);
LuaAssert(L, LuaToken("a0").value > LuaToken("a").value);
LuaAssert(L, LuaToken("a").value != LuaToken("a0").value);
return 0;
}