Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/VM/src/lobject.cpp
2725 views
1
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2
// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details
3
#include "lobject.h"
4
5
#include "lstate.h"
6
#include "lstring.h"
7
#include "lgc.h"
8
#include "ldo.h"
9
#include "lnumutils.h"
10
11
#include <ctype.h>
12
#include <string.h>
13
#include <stdio.h>
14
#include <stdlib.h>
15
16
const TValue luaO_nilobject_ = {{NULL}, {0}, LUA_TNIL};
17
18
int luaO_log2(unsigned int x)
19
{
20
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,
21
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,
22
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,
23
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,
24
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,
25
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,
26
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};
27
int l = -1;
28
while (x >= 256)
29
{
30
l += 8;
31
x >>= 8;
32
}
33
return l + log_2[x];
34
}
35
36
int luaO_rawequalObj(const TValue* t1, const TValue* t2)
37
{
38
if (ttype(t1) != ttype(t2))
39
return 0;
40
else
41
switch (ttype(t1))
42
{
43
case LUA_TNIL:
44
return 1;
45
case LUA_TNUMBER:
46
return luai_numeq(nvalue(t1), nvalue(t2));
47
case LUA_TINTEGER:
48
return luai_inteq(lvalue(t1), lvalue(t2));
49
case LUA_TVECTOR:
50
return luai_veceq(vvalue(t1), vvalue(t2));
51
case LUA_TBOOLEAN:
52
return bvalue(t1) == bvalue(t2); // boolean true must be 1 !!
53
case LUA_TLIGHTUSERDATA:
54
return pvalue(t1) == pvalue(t2) && lightuserdatatag(t1) == lightuserdatatag(t2);
55
default:
56
LUAU_ASSERT(iscollectable(t1));
57
return gcvalue(t1) == gcvalue(t2);
58
}
59
}
60
61
int luaO_rawequalKey(const TKey* t1, const TValue* t2)
62
{
63
if (ttype(t1) != ttype(t2))
64
return 0;
65
else
66
switch (ttype(t1))
67
{
68
case LUA_TNIL:
69
return 1;
70
case LUA_TNUMBER:
71
return luai_numeq(nvalue(t1), nvalue(t2));
72
case LUA_TINTEGER:
73
return luai_inteq(lvalue(t1), lvalue(t2));
74
case LUA_TVECTOR:
75
return luai_veceq(vvalue(t1), vvalue(t2));
76
case LUA_TBOOLEAN:
77
return bvalue(t1) == bvalue(t2); // boolean true must be 1 !!
78
case LUA_TLIGHTUSERDATA:
79
return pvalue(t1) == pvalue(t2) && lightuserdatatag(t1) == lightuserdatatag(t2);
80
default:
81
LUAU_ASSERT(iscollectable(t1));
82
return gcvalue(t1) == gcvalue(t2);
83
}
84
}
85
86
int luaO_str2d(const char* s, double* result)
87
{
88
char* endptr;
89
*result = luai_str2num(s, &endptr);
90
if (endptr == s)
91
return 0; // conversion failed
92
if (*endptr == 'x' || *endptr == 'X') // maybe an hexadecimal constant?
93
*result = cast_num(strtoul(s, &endptr, 16));
94
if (*endptr == '\0')
95
return 1; // most common case
96
while (isspace(cast_to(unsigned char, *endptr)))
97
endptr++;
98
if (*endptr != '\0')
99
return 0; // invalid trailing characters?
100
return 1;
101
}
102
103
int luaO_str2l(const char* s, int64_t* result, int base)
104
{
105
char* endptr = nullptr;
106
if (base == 10)
107
{
108
*result = luai_str2long(s, &endptr, base);
109
if (endptr == s)
110
return 0; // conversion failed
111
if (*endptr == 'x' || *endptr == 'X') // maybe an hexadecimal constant?
112
*result = (int64_t)strtoull(s, &endptr, 16);
113
}
114
else
115
{
116
// unsigned parse in other bases
117
*result = (int64_t)strtoull(s, &endptr, base);
118
if (endptr == s)
119
return 0;
120
}
121
if (*endptr == '\0')
122
return 1; // most common case
123
while (isspace(cast_to(unsigned char, *endptr)))
124
endptr++;
125
if (*endptr != '\0')
126
return 0; // invalid trailing characters?
127
return 1;
128
}
129
130
const char* luaO_pushvfstring(lua_State* L, const char* fmt, va_list argp)
131
{
132
char result[LUA_BUFFERSIZE];
133
vsnprintf(result, sizeof(result), fmt, argp);
134
135
setsvalue(L, L->top, luaS_new(L, result));
136
incr_top(L);
137
return svalue(L->top - 1);
138
}
139
140
const char* luaO_pushfstring(lua_State* L, const char* fmt, ...)
141
{
142
const char* msg;
143
va_list argp;
144
va_start(argp, fmt);
145
msg = luaO_pushvfstring(L, fmt, argp);
146
va_end(argp);
147
return msg;
148
}
149
150
// Possible chunkname prefixes:
151
//
152
// '=' prefix: meant to represent custom chunknames. When truncation is needed,
153
// the beginning of the chunkname is kept.
154
//
155
// '@' prefix: meant to represent filepaths. When truncation is needed, the end
156
// of the filepath is kept, as this is more useful for identifying the file.
157
const char* luaO_chunkid(char* buf, size_t buflen, const char* source, size_t srclen)
158
{
159
if (*source == '=')
160
{
161
if (srclen <= buflen)
162
return source + 1;
163
// truncate the part after =
164
memcpy(buf, source + 1, buflen - 1);
165
buf[buflen - 1] = '\0';
166
}
167
else if (*source == '@')
168
{
169
if (srclen <= buflen)
170
return source + 1;
171
// truncate the part after @
172
memcpy(buf, "...", 3);
173
memcpy(buf + 3, source + srclen - (buflen - 4), buflen - 4);
174
buf[buflen - 1] = '\0';
175
}
176
else
177
{ // buf = [string "string"]
178
size_t len = strcspn(source, "\n\r"); // stop at first newline
179
buflen -= sizeof("[string \"...\"]");
180
if (len > buflen)
181
len = buflen;
182
strcpy(buf, "[string \"");
183
if (source[len] != '\0')
184
{ // must truncate?
185
strncat(buf, source, len);
186
strcat(buf, "...");
187
}
188
else
189
strcat(buf, source);
190
strcat(buf, "\"]");
191
}
192
return buf;
193
}
194
195