Change struct & sjson to use integers. This is slightly more complex (#3222)

* Change struct to use integers. This is slightly more complex as we have to deal with Unsigned 32-bit integers (that aren't lua integers)
* Use int64 in struct rather than double.
* Fix sjson to do the right things in LUA5.3 with integers and floats
This commit is contained in:
Philip Gladstone 2020-08-23 18:11:18 -04:00 committed by GitHub
parent 64ece47ff6
commit 0e02c0e5f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 20 deletions

View File

@ -97,7 +97,7 @@ create_new_element(jsonsl_t jsn,
lua_rawgeti(data->L, LUA_REGISTRYINDEX, get_parent_object_ref());
if (data->hkey_ref == LUA_NOREF) {
// list, so append
lua_pushnumber(data->L, get_parent_object_used_count_pre_inc());
lua_pushinteger(data->L, get_parent_object_used_count_pre_inc());
DBG_PRINTF("Adding array element\n");
} else {
// object, so
@ -108,7 +108,7 @@ create_new_element(jsonsl_t jsn,
}
if (data->pos_ref != LUA_NOREF && state->level > 1) {
lua_rawgeti(data->L, LUA_REGISTRYINDEX, data->pos_ref);
lua_pushnumber(data->L, state->level - 1);
lua_pushinteger(data->L, state->level - 1);
lua_pushvalue(data->L, -3); // get the key
lua_settable(data->L, -3);
lua_pop(data->L, 1);
@ -152,10 +152,21 @@ create_new_element(jsonsl_t jsn,
}
static void push_number(JSN_DATA *data, struct jsonsl_state_st *state) {
lua_pushlstring(data->L, get_state_buffer(data, state), state->pos_cur - state->pos_begin);
LUA_NUMBER r = lua_tonumber(data->L, -1);
const char *start = get_state_buffer(data, state);
const char *end = start + state->pos_cur - state->pos_begin;
lua_pushlstring(data->L, start, end - start);
#if LUA_VERSION_NUM >= 503
int sz = lua_stringtonumber(data->L, lua_tostring(data->L, -1));
if (sz) {
lua_pop(data->L, 1);
} else {
luaL_error(data->L, "Invalid number");
}
#else
lua_Number result = lua_tonumber(data->L, -1);
lua_pop(data->L, 1);
lua_pushnumber(data->L, r);
lua_pushnumber(data->L, result);
#endif
}
static int fromhex(char c) {
@ -241,7 +252,7 @@ cleanup_closing_element(jsonsl_t jsn,
lua_rawgeti(data->L, LUA_REGISTRYINDEX, get_parent_object_ref());
if (data->hkey_ref == LUA_NOREF) {
// list, so append
lua_pushnumber(data->L, get_parent_object_used_count_pre_inc());
lua_pushinteger(data->L, get_parent_object_used_count_pre_inc());
} else {
// object, so
lua_rawgeti(data->L, LUA_REGISTRYINDEX, data->hkey_ref);
@ -272,7 +283,7 @@ cleanup_closing_element(jsonsl_t jsn,
lua_rawgeti(data->L, LUA_REGISTRYINDEX, get_parent_object_ref());
if (data->hkey_ref == LUA_NOREF) {
// list, so append
lua_pushnumber(data->L, get_parent_object_used_count_pre_inc());
lua_pushinteger(data->L, get_parent_object_used_count_pre_inc());
} else {
// object, so
lua_rawgeti(data->L, LUA_REGISTRYINDEX, data->hkey_ref);
@ -291,7 +302,7 @@ cleanup_closing_element(jsonsl_t jsn,
state->lua_object_ref = LUA_NOREF;
if (data->pos_ref != LUA_NOREF) {
lua_rawgeti(data->L, LUA_REGISTRYINDEX, data->pos_ref);
lua_pushnumber(data->L, state->level);
lua_pushinteger(data->L, state->level);
lua_pushnil(data->L);
lua_settable(data->L, -3);
lua_pop(data->L, 1);
@ -719,7 +730,11 @@ static void encode_lua_object(lua_State *L, ENC_DATA *data, int argno, const cha
char value[len + 1];
strcpy(value, str);
lua_pop(L, 1);
luaL_addstring(&b, value);
if (strcmp(value, "-Infinity") == 0 || strcmp(value, "NaN") == 0 || strcmp(value, "Infinity") == 0) {
luaL_addstring(&b, "null"); // According to ECMA-262 section 24.5.2 Note 4
} else {
luaL_addstring(&b, value);
}
break;
}

View File

@ -60,6 +60,14 @@ typedef unsigned STRUCT_INT Uinttype;
#define MAXINTSIZE 32
#endif
#ifndef LUA_MININTEGER
#define LUA_MININTEGER INT_MIN
#endif
#ifndef LUA_MAXINTEGER
#define LUA_MAXINTEGER INT_MAX
#endif
/* is 'x' a power of 2? */
#define isp2(x) ((x) > 0 && ((x) & ((x) - 1)) == 0)
@ -170,7 +178,7 @@ static void controloptions (lua_State *L, int opt, const char **fmt,
static void putinteger (lua_State *L, luaL_Buffer *b, int arg, int endian,
int size) {
lua_Number n = luaL_checknumber(L, arg);
int32_t n = luaL_checkinteger(L, arg);
Uinttype value;
char buff[MAXINTSIZE];
if (n < 0)
@ -267,29 +275,29 @@ static int b_pack (lua_State *L) {
}
static lua_Number getinteger (const char *buff, int endian,
static int64_t getinteger (const char *buff, int endian,
int issigned, int size) {
Uinttype l = 0;
uint64_t l = 0;
int i;
if (endian == BIG) {
for (i = 0; i < size; i++) {
l <<= 8;
l |= (Uinttype)(unsigned char)buff[i];
l |= (unsigned char)buff[i];
}
}
else {
for (i = size - 1; i >= 0; i--) {
l <<= 8;
l |= (Uinttype)(unsigned char)buff[i];
l |= (unsigned char)buff[i];
}
}
if (!issigned)
return (lua_Number)l;
return (int64_t)l;
else { /* signed format */
Uinttype mask = (Uinttype)(~((Uinttype)0)) << (size*8 - 1);
uint64_t mask = (uint64_t)(~((uint64_t)0)) << (size*8 - 1);
if (l & mask) /* negative value? */
l |= mask; /* signal extension */
return (lua_Number)(Inttype)l;
return (int64_t)l;
}
}
@ -312,8 +320,12 @@ static int b_unpack (lua_State *L) {
case 'b': case 'B': case 'h': case 'H':
case 'l': case 'L': case 'T': case 'i': case 'I': { /* integer types */
int issigned = islower(opt);
lua_Number res = getinteger(data+pos, h.endian, issigned, size);
lua_pushnumber(L, res);
int64_t res = getinteger(data+pos, h.endian, issigned, size);
if (res >= LUA_MININTEGER && res <= LUA_MAXINTEGER) {
lua_pushinteger(L, res);
} else {
lua_pushnumber(L, res);
}
break;
}
case 'x': {
@ -339,7 +351,7 @@ static int b_unpack (lua_State *L) {
if (size == 0) {
if (!lua_isnumber(L, -1))
luaL_error(L, "format `c0' needs a previous size");
size = lua_tonumber(L, -1);
size = lua_tointeger(L, -1);
lua_pop(L, 1);
luaL_argcheck(L, pos+size <= ld, 2, "data string too short");
}