static void DumpNumber(lua_Number x, DumpState* D) { /* http://stackoverflow.com/questions/14954088/how-do-i-handle-byte-order-differences-when-reading-writing-floating-point-types/14955046#14955046 10-byte little-endian serialized format for double: - normalized mantissa stored as 64-bit (8-byte) signed integer: negative range: (-2^53, -2^52] zero: 0 positive range: [+2^52, +2^53) - 16-bit (2-byte) signed exponent: range: [-0x7FFE, +0x7FFE] Represented value = mantissa * 2^(exponent - 53) Special cases: - +infinity: mantissa = 0x7FFFFFFFFFFFFFFF, exp = 0x7FFF - -infinity: mantissa = 0x8000000000000000, exp = 0x7FFF - NaN: mantissa = 0x0000000000000000, exp = 0x7FFF - +/-0: only one zero supported */ double y=(double)x,m; unsigned char z[8]; long long im; int ie; if (luai_numisnan(NULL,x)) { DumpChar(0,D); /* NaN */ return; } else if (x == LUA_INFINITY) { DumpChar(1,D); /* +inf */ return; } else if (x == -LUA_INFINITY) { DumpChar(2,D); /* -inf */ return; } else if (x == 0) { DumpChar(3,D); /* 0 */ return; } /* Split double into normalized mantissa (range: (-1, -0.5], 0, [+0.5, +1)) and base-2 exponent */ m = frexp(y, &ie); /* y = m * 2^ie exactly for FLT_RADIX=2, frexp() can't fail */ /* Extract most significant 53 bits of mantissa as integer */ m = ldexp(m, 53); /* can't overflow because DBL_MAX_10_EXP >= 37 equivalent to DBL_MAX_2_EXP >= 122 */ im = (long long)trunc(m); /* exact unless DBL_MANT_DIG > 53 */ /* If the exponent is too small or too big, reduce the number to 0 or +/- infinity */ if (ie>0x7FFE) { if (im<0) DumpChar(2,D); /* -inf */ else DumpChar(1,D); /* +inf */ return; } else if (ie<-0x7FFE) { DumpChar(3,D); /* 0 */ return; } DumpChar(4,D); /* encoded */ /* Store im as signed 64-bit little-endian integer */ z[0]=(unsigned char)(im&0xFF); z[1]=(unsigned char)((im>>8)&0xFF); z[2]=(unsigned char)((im>>16)&0xFF); z[3]=(unsigned char)((im>>24)&0xFF); z[4]=(unsigned char)((im>>32)&0xFF); z[5]=(unsigned char)((im>>40)&0xFF); z[6]=(unsigned char)((im>>48)&0xFF); z[7]=(unsigned char)((im>>56)&0xFF); DumpMem(z,1,8,D); /* Store ie as signed 16-bit little-endian integer */ z[0]=(unsigned char)(ie&0xFF); z[1]=(unsigned char)((ie>>8)&0xFF); DumpMem(z,1,2,D); }
static int l_hashfloat (lua_Number n) { int i; lua_Integer ni; n = l_mathop(frexp)(n, &i) * -cast_num(INT_MIN); if (!lua_numbertointeger(n, &ni)) { /* is 'n' inf/-inf/NaN? */ lua_assert(luai_numisnan(n) || l_mathop(fabs)(n) == cast_num(HUGE_VAL)); return 0; } else { /* normal case */ unsigned int u = cast_uint(i) + cast_uint(ni); return cast_int(u <= cast_uint(INT_MAX) ? u : ~u); } }
int luaK_numberK (FuncState *fs, lua_Number r) { int n; lua_State *L = fs->ls->L; TValue o; setnvalue(&o, r); if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */ /* use raw representation as key to avoid numeric problems */ setsvalue(L, L->top++, luaS_newlstr(L, (char *)&r, sizeof(r))); n = addk(fs, L->top - 1, &o); L->top--; } else n = addk(fs, &o, &o); /* regular case */ return n; }
/* ** Return 'l <= r', for numbers. */ static int LEnum (const TValue *l, const TValue *r) { if (ttisinteger(l)) { lua_Integer li = ivalue(l); if (ttisinteger(r)) return li <= ivalue(r); /* both are integers */ else /* 'l' is int and 'r' is float */ return LEintfloat(li, fltvalue(r)); /* l <= r ? */ } else { lua_Number lf = fltvalue(l); /* 'l' must be float */ if (ttisfloat(r)) return luai_numle(lf, fltvalue(r)); /* both are float */ else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */ return 0; /* NaN <= i is always false */ else /* without NaN, (l <= r) <--> not(r < l) */ return !LTintfloat(ivalue(r), lf); /* not (r < l) ? */ } }
/* ** Try to "constant-fold" an operation; return 1 iff successful */ static int constfolding (FuncState *fs, int op, expdesc *e1, expdesc *e2) { TValue v1, v2, res; if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2)) return 0; /* non-numeric operands or not safe to fold */ luaO_arith(fs->ls->L, op, &v1, &v2, &res); if (ttisinteger(&res)) { e1->k = VKINT; e1->u.ival = ivalue(&res); } else { lua_Number n = fltvalue(&res); if (luai_numisnan(n) || isminuszero(n)) return 0; /* folds neither NaN nor -0 */ e1->k = VKFLT; e1->u.nval = n; } return 1; }
static int load_table(lua_State * L, lbs_LoadState * ls) { int array_size = 0; int hash_size = 0; unsigned int total_size = 0; int result = lbsLS_readbytes(ls, (unsigned char *)&array_size, LUABINS_LINT); if (result == LUABINS_ESUCCESS) { result = lbsLS_readbytes(ls, (unsigned char *)&hash_size, LUABINS_LINT); } if (result == LUABINS_ESUCCESS) { total_size = array_size + hash_size; /* SPAM(( "LT SIZE CHECK\n" "* array_size %d limit 0 .. %d\n" "* hash_size %d limit >0\n" "* hash_size bytes %d, limit %d\n" "* unread %u limit >min_size %u (total_size %u)\n", array_size, MAXASIZE, hash_size, ceillog2((unsigned int)hash_size), MAXBITS, (unsigned int)lbsLS_unread(ls), (unsigned int)luabins_min_table_data_size(total_size), (unsigned int)total_size )); */ if ( array_size < 0 || array_size > MAXASIZE || hash_size < 0 || (hash_size > 0 && ceillog2((unsigned int)hash_size) > MAXBITS) || lbsLS_unread(ls) < luabins_min_table_data_size(total_size) ) { result = LUABINS_EBADSIZE; } } if (result == LUABINS_ESUCCESS) { unsigned int i = 0; XSPAM(( "* load: creating table a:%d + h:%d = %d\n", array_size, hash_size, total_size )); lua_createtable(L, array_size, hash_size); for (i = 0; i < total_size; ++i) { int key_type = LUA_TNONE; result = load_value(L, ls); /* Load key. */ if (result != LUABINS_ESUCCESS) { break; } /* Table key can't be nil or NaN */ key_type = lua_type(L, -1); if (key_type == LUA_TNIL) { /* Corrupt data? */ SPAM(("load: nil as key detected\n")); result = LUABINS_EBADDATA; break; } if (key_type == LUA_TNUMBER) { lua_Number key = lua_tonumber(L, -1); if (luai_numisnan(key)) { /* Corrupt data? */ SPAM(("load: NaN as key detected\n")); result = LUABINS_EBADDATA; break; } } result = load_value(L, ls); /* Load value. */ if (result != LUABINS_ESUCCESS) { break; } lua_rawset(L, -3); } } return result; }
/* ** Both NaN and -0.0 should not go to the constant table, as they have ** problems with the hashing. (NaN is not a valid key, -0.0 collides ** with +0.0.) */ static int luaK_numberK (FuncState *fs, lua_Number r) { TValue o; lua_assert(!luai_numisnan(r) && !isminuszero(r)); setfltvalue(&o, r); return addk(fs, &o, &o); }