luau/VM/src/lobject.cpp

161 lines
4.9 KiB
C++
Raw Normal View History

// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
#include "lgc.h"
#include "ldo.h"
#include "lnumutils.h"
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
2021-12-02 23:20:08 +00:00
const TValue luaO_nilobject_ = {{NULL}, {0}, LUA_TNIL};
int luaO_log2(unsigned int x)
{
static const uint8_t log_2[256] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8};
int l = -1;
while (x >= 256)
{
l += 8;
x >>= 8;
}
return l + log_2[x];
}
int luaO_rawequalObj(const TValue* t1, const TValue* t2)
{
if (ttype(t1) != ttype(t2))
return 0;
else
switch (ttype(t1))
{
case LUA_TNIL:
return 1;
case LUA_TNUMBER:
return luai_numeq(nvalue(t1), nvalue(t2));
case LUA_TVECTOR:
return luai_veceq(vvalue(t1), vvalue(t2));
case LUA_TBOOLEAN:
2022-08-04 22:27:28 +01:00
return bvalue(t1) == bvalue(t2); // boolean true must be 1 !!
case LUA_TLIGHTUSERDATA:
return pvalue(t1) == pvalue(t2);
default:
LUAU_ASSERT(iscollectable(t1));
return gcvalue(t1) == gcvalue(t2);
}
}
int luaO_rawequalKey(const TKey* t1, const TValue* t2)
{
if (ttype(t1) != ttype(t2))
return 0;
else
switch (ttype(t1))
{
case LUA_TNIL:
return 1;
case LUA_TNUMBER:
return luai_numeq(nvalue(t1), nvalue(t2));
case LUA_TVECTOR:
return luai_veceq(vvalue(t1), vvalue(t2));
case LUA_TBOOLEAN:
2022-08-04 22:27:28 +01:00
return bvalue(t1) == bvalue(t2); // boolean true must be 1 !!
case LUA_TLIGHTUSERDATA:
return pvalue(t1) == pvalue(t2);
default:
LUAU_ASSERT(iscollectable(t1));
return gcvalue(t1) == gcvalue(t2);
}
}
int luaO_str2d(const char* s, double* result)
{
char* endptr;
*result = luai_str2num(s, &endptr);
if (endptr == s)
2022-08-04 22:27:28 +01:00
return 0; // conversion failed
if (*endptr == 'x' || *endptr == 'X') // maybe an hexadecimal constant?
*result = cast_num(strtoul(s, &endptr, 16));
if (*endptr == '\0')
2022-08-04 22:27:28 +01:00
return 1; // most common case
while (isspace(cast_to(unsigned char, *endptr)))
endptr++;
if (*endptr != '\0')
2022-08-04 22:27:28 +01:00
return 0; // invalid trailing characters?
return 1;
}
const char* luaO_pushvfstring(lua_State* L, const char* fmt, va_list argp)
{
char result[LUA_BUFFERSIZE];
vsnprintf(result, sizeof(result), fmt, argp);
setsvalue2s(L, L->top, luaS_new(L, result));
incr_top(L);
return svalue(L->top - 1);
}
const char* luaO_pushfstring(lua_State* L, const char* fmt, ...)
{
const char* msg;
va_list argp;
va_start(argp, fmt);
msg = luaO_pushvfstring(L, fmt, argp);
va_end(argp);
return msg;
}
void luaO_chunkid(char* out, const char* source, size_t bufflen)
{
if (*source == '=')
{
2022-08-04 22:27:28 +01:00
source++; // skip the `='
size_t srclen = strlen(source);
size_t dstlen = srclen < bufflen ? srclen : bufflen - 1;
memcpy(out, source, dstlen);
out[dstlen] = '\0';
}
else if (*source == '@')
{
size_t l;
2022-08-04 22:27:28 +01:00
source++; // skip the `@'
2022-02-11 18:43:14 +00:00
bufflen -= sizeof("...");
l = strlen(source);
strcpy(out, "");
if (l > bufflen)
{
2022-08-04 22:27:28 +01:00
source += (l - bufflen); // get last part of file name
strcat(out, "...");
}
strcat(out, source);
}
else
2022-08-04 22:27:28 +01:00
{ // out = [string "string"]
size_t len = strcspn(source, "\n\r"); // stop at first newline
2022-02-11 18:43:14 +00:00
bufflen -= sizeof("[string \"...\"]");
if (len > bufflen)
len = bufflen;
strcpy(out, "[string \"");
if (source[len] != '\0')
2022-08-04 22:27:28 +01:00
{ // must truncate?
strncat(out, source, len);
strcat(out, "...");
}
else
strcat(out, source);
strcat(out, "\"]");
}
}