]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | // |
2 | // Licensed to the Apache Software Foundation (ASF) under one | |
3 | // or more contributor license agreements. See the NOTICE file | |
4 | // distributed with this work for additional information | |
5 | // regarding copyright ownership. The ASF licenses this file | |
6 | // to you under the Apache License, Version 2.0 (the | |
7 | // "License"); you may not use this file except in compliance | |
8 | // with the License. You may obtain a copy of the License at | |
9 | // | |
10 | // http://www.apache.org/licenses/LICENSE-2.0 | |
11 | // | |
12 | // Unless required by applicable law or agreed to in writing, | |
13 | // software distributed under the License is distributed on an | |
14 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
15 | // KIND, either express or implied. See the License for the | |
16 | // specific language governing permissions and limitations | |
17 | // under the License. | |
18 | // | |
19 | ||
20 | #include <lua.h> | |
21 | #include <lauxlib.h> | |
22 | #include <stdlib.h> | |
23 | #include <math.h> | |
24 | #include <inttypes.h> | |
25 | #include <string.h> | |
26 | ||
27 | extern const char * LONG_NUM_TYPE; | |
28 | extern int64_t lualongnumber_checklong(lua_State *L, int index); | |
29 | extern int64_t lualongnumber_pushlong(lua_State *L, int64_t *val); | |
30 | ||
31 | //////////////////////////////////////////////////////////////////////////////// | |
32 | ||
33 | static void l_serialize(char *buf, int len, int64_t val) { | |
34 | snprintf(buf, len, "%"PRId64, val); | |
35 | } | |
36 | ||
37 | static int64_t l_deserialize(const char *buf) { | |
38 | int64_t data; | |
39 | int rv; | |
40 | // Support hex prefixed with '0x' | |
41 | if (strstr(buf, "0x") == buf) { | |
42 | rv = sscanf(buf, "%"PRIx64, &data); | |
43 | } else { | |
44 | rv = sscanf(buf, "%"PRId64, &data); | |
45 | } | |
46 | if (rv == 1) { | |
47 | return data; | |
48 | } | |
49 | return 0; // Failed | |
50 | } | |
51 | ||
52 | //////////////////////////////////////////////////////////////////////////////// | |
53 | ||
54 | static int l_new(lua_State *L) { | |
55 | int64_t val; | |
56 | const char *str = NULL; | |
57 | if (lua_type(L, 1) == LUA_TSTRING) { | |
58 | str = lua_tostring(L, 1); | |
59 | val = l_deserialize(str); | |
60 | } else if (lua_type(L, 1) == LUA_TNUMBER) { | |
61 | val = (int64_t)lua_tonumber(L, 1); | |
62 | str = (const char *)1; | |
63 | } | |
64 | lualongnumber_pushlong(L, (str ? &val : NULL)); | |
65 | return 1; | |
66 | } | |
67 | ||
68 | //////////////////////////////////////////////////////////////////////////////// | |
69 | ||
70 | // a + b | |
71 | static int l_add(lua_State *L) { | |
72 | int64_t a, b, c; | |
73 | a = lualongnumber_checklong(L, 1); | |
74 | b = lualongnumber_checklong(L, 2); | |
75 | c = a + b; | |
76 | lualongnumber_pushlong(L, &c); | |
77 | return 1; | |
78 | } | |
79 | ||
80 | // a / b | |
81 | static int l_div(lua_State *L) { | |
82 | int64_t a, b, c; | |
83 | a = lualongnumber_checklong(L, 1); | |
84 | b = lualongnumber_checklong(L, 2); | |
85 | c = a / b; | |
86 | lualongnumber_pushlong(L, &c); | |
87 | return 1; | |
88 | } | |
89 | ||
90 | // a == b (both a and b are lualongnumber's) | |
91 | static int l_eq(lua_State *L) { | |
92 | int64_t a, b; | |
93 | a = lualongnumber_checklong(L, 1); | |
94 | b = lualongnumber_checklong(L, 2); | |
95 | lua_pushboolean(L, (a == b ? 1 : 0)); | |
96 | return 1; | |
97 | } | |
98 | ||
99 | // garbage collection | |
100 | static int l_gc(lua_State *L) { | |
101 | lua_pushnil(L); | |
102 | lua_setmetatable(L, 1); | |
103 | return 0; | |
104 | } | |
105 | ||
106 | // a < b | |
107 | static int l_lt(lua_State *L) { | |
108 | int64_t a, b; | |
109 | a = lualongnumber_checklong(L, 1); | |
110 | b = lualongnumber_checklong(L, 2); | |
111 | lua_pushboolean(L, (a < b ? 1 : 0)); | |
112 | return 1; | |
113 | } | |
114 | ||
115 | // a <= b | |
116 | static int l_le(lua_State *L) { | |
117 | int64_t a, b; | |
118 | a = lualongnumber_checklong(L, 1); | |
119 | b = lualongnumber_checklong(L, 2); | |
120 | lua_pushboolean(L, (a <= b ? 1 : 0)); | |
121 | return 1; | |
122 | } | |
123 | ||
124 | // a % b | |
125 | static int l_mod(lua_State *L) { | |
126 | int64_t a, b, c; | |
127 | a = lualongnumber_checklong(L, 1); | |
128 | b = lualongnumber_checklong(L, 2); | |
129 | c = a % b; | |
130 | lualongnumber_pushlong(L, &c); | |
131 | return 1; | |
132 | } | |
133 | ||
134 | // a * b | |
135 | static int l_mul(lua_State *L) { | |
136 | int64_t a, b, c; | |
137 | a = lualongnumber_checklong(L, 1); | |
138 | b = lualongnumber_checklong(L, 2); | |
139 | c = a * b; | |
140 | lualongnumber_pushlong(L, &c); | |
141 | return 1; | |
142 | } | |
143 | ||
144 | // a ^ b | |
145 | static int l_pow(lua_State *L) { | |
146 | long double a, b; | |
147 | int64_t c; | |
148 | a = (long double)lualongnumber_checklong(L, 1); | |
149 | b = (long double)lualongnumber_checklong(L, 2); | |
150 | c = (int64_t)pow(a, b); | |
151 | lualongnumber_pushlong(L, &c); | |
152 | return 1; | |
153 | } | |
154 | ||
155 | // a - b | |
156 | static int l_sub(lua_State *L) { | |
157 | int64_t a, b, c; | |
158 | a = lualongnumber_checklong(L, 1); | |
159 | b = lualongnumber_checklong(L, 2); | |
160 | c = a - b; | |
161 | lualongnumber_pushlong(L, &c); | |
162 | return 1; | |
163 | } | |
164 | ||
165 | // tostring() | |
166 | static int l_tostring(lua_State *L) { | |
167 | int64_t a; | |
168 | char str[256]; | |
169 | l_serialize(str, 256, lualongnumber_checklong(L, 1)); | |
170 | lua_pushstring(L, str); | |
171 | return 1; | |
172 | } | |
173 | ||
174 | // -a | |
175 | static int l_unm(lua_State *L) { | |
176 | int64_t a, c; | |
177 | a = lualongnumber_checklong(L, 1); | |
178 | c = -a; | |
179 | lualongnumber_pushlong(L, &c); | |
180 | return 1; | |
181 | } | |
182 | ||
183 | //////////////////////////////////////////////////////////////////////////////// | |
184 | ||
185 | static const luaL_Reg methods[] = { | |
186 | {"__add", l_add}, | |
187 | {"__div", l_div}, | |
188 | {"__eq", l_eq}, | |
189 | {"__gc", l_gc}, | |
190 | {"__lt", l_lt}, | |
191 | {"__le", l_le}, | |
192 | {"__mod", l_mod}, | |
193 | {"__mul", l_mul}, | |
194 | {"__pow", l_pow}, | |
195 | {"__sub", l_sub}, | |
196 | {"__tostring", l_tostring}, | |
197 | {"__unm", l_unm}, | |
198 | {NULL, NULL}, | |
199 | }; | |
200 | ||
201 | static const luaL_Reg funcs[] = { | |
202 | {"new", l_new}, | |
203 | {NULL, NULL} | |
204 | }; | |
205 | ||
206 | //////////////////////////////////////////////////////////////////////////////// | |
207 | ||
208 | static void set_methods(lua_State *L, | |
209 | const char *metatablename, | |
210 | const struct luaL_Reg *methods) { | |
211 | luaL_getmetatable(L, metatablename); // mt | |
212 | // No need for a __index table since everything is __* | |
213 | for (; methods->name; methods++) { | |
214 | lua_pushstring(L, methods->name); // mt, "name" | |
215 | lua_pushcfunction(L, methods->func); // mt, "name", func | |
216 | lua_rawset(L, -3); // mt | |
217 | } | |
218 | lua_pop(L, 1); | |
219 | } | |
220 | ||
221 | LUALIB_API int luaopen_liblualongnumber(lua_State *L) { | |
222 | luaL_newmetatable(L, LONG_NUM_TYPE); | |
223 | lua_pop(L, 1); | |
224 | set_methods(L, LONG_NUM_TYPE, methods); | |
225 | ||
226 | luaL_register(L, "liblualongnumber", funcs); | |
227 | return 1; | |
228 | } |