0
|
1 /* intutils lua library to support various types such as i64 and u64 */
|
|
2 /* critical to dyncall: needed to interact with C systems using long long */
|
|
3
|
|
4 #include "lua.hpp"
|
|
5 #include <cstdlib>
|
|
6 #include <cstdio>
|
|
7
|
|
8 typedef long long i64;
|
|
9 typedef unsigned long long u64;
|
|
10
|
|
11 template<typename T> const char* get_typename();
|
|
12
|
|
13 template<> inline const char* get_typename<u64>() { return "u64"; }
|
|
14 template<> inline const char* get_typename<i64>() { return "i64"; }
|
|
15
|
|
16 template<typename T> inline void lua_push(lua_State *L, T x)
|
|
17 {
|
|
18 T *ptr = (T*) lua_newuserdata(L, sizeof(T));
|
|
19 * ptr = x;
|
|
20 luaL_getmetatable(L, get_typename<T>() );
|
|
21 lua_setmetatable(L, -2);
|
|
22 }
|
|
23
|
|
24 template<typename T> int tostring(lua_State *L);
|
|
25
|
|
26 template<> int tostring<u64>(lua_State *L)
|
|
27 {
|
|
28 char buf[1024];
|
|
29 u64 v = * (u64*) lua_topointer(L, 1);
|
|
30 sprintf(buf, "%016llx", v);
|
|
31 lua_pushstring(L, buf);
|
|
32 return 1;
|
|
33 }
|
|
34
|
|
35 template<> int tostring<i64>(lua_State *L)
|
|
36 {
|
|
37 char buf[1024];
|
|
38 i64 v = * (i64*) lua_topointer(L, 1);
|
|
39 sprintf(buf, "%016llx", v);
|
|
40 lua_pushstring(L, buf);
|
|
41 return 1;
|
|
42 }
|
|
43
|
|
44 template<typename T>
|
|
45 struct lua_ops
|
|
46 {
|
|
47 template<typename OP>
|
|
48 static int binop(lua_State *L)
|
|
49 {
|
|
50 T op1;
|
|
51 switch( lua_type(L, 1) ) {
|
|
52 case LUA_TNUMBER: op1 = (T) lua_tonumber(L, 1); break;
|
|
53 case LUA_TUSERDATA: op1 = * (T*) lua_touserdata(L, 1); break;
|
|
54 default: luaL_error(L, "invalid left-hand side operand");
|
|
55 }
|
|
56 T op2;
|
|
57 switch( lua_type(L, 2) ) {
|
|
58 case LUA_TNUMBER: op2 = (T) lua_tonumber(L, 2); break;
|
|
59 case LUA_TUSERDATA: op2 = * (T*) lua_touserdata(L, 2); break;
|
|
60 default: luaL_error(L, "invalid right-hand side operand");
|
|
61 }
|
|
62 lua_push(L, OP(op1,op2) );
|
|
63 }
|
|
64 static T add1(T op1, T op2) { return op1 + op2 ; }
|
|
65 static int add(lua_State *L)
|
|
66 {
|
|
67 T op1;
|
|
68 switch( lua_type(L, 1) ) {
|
|
69 case LUA_TNUMBER: op1 = (T) lua_tonumber(L, 1); break;
|
|
70 case LUA_TUSERDATA: op1 = * (T*) lua_touserdata(L, 1); break;
|
|
71 default: luaL_error(L, "invalid left-hand side operand");
|
|
72 }
|
|
73 T op2;
|
|
74 switch( lua_type(L, 2) ) {
|
|
75 case LUA_TNUMBER: op2 = (T) lua_tonumber(L, 2); break;
|
|
76 case LUA_TUSERDATA: op2 = * (T*) lua_touserdata(L, 2); break;
|
|
77 default: luaL_error(L, "invalid right-hand side operand");
|
|
78 }
|
|
79 lua_push(L, op1 + op2);
|
|
80 return 1;
|
|
81 }
|
|
82 static int sub(lua_State *L)
|
|
83 {
|
|
84 T op1 = * (T*) lua_topointer(L, 1);
|
|
85 T op2 = * (T*) lua_topointer(L, 2);
|
|
86 lua_push(L, op1 - op2);
|
|
87 return 1;
|
|
88 }
|
|
89 };
|
|
90 #define OPS(X) lua_ops<X>
|
|
91 template<typename T>
|
|
92 void register_type(lua_State *L, const char *tname)
|
|
93 {
|
|
94 luaL_newmetatable(L, tname);
|
|
95 const char* names[] = {
|
|
96 "__add", "__sub", "__tostring" // , "__mul", "__div", "__mod", "__unm", "__eq", "__lt"
|
|
97 };
|
|
98 lua_CFunction funs[] = {
|
|
99 OPS(T)::add, OPS(T)::sub, tostring<T> // , T::mul, T::div, T::mod, T::unm, T::eq, T::lt
|
|
100 };
|
|
101 size_t n = sizeof(names)/sizeof(const char*);
|
|
102 for (int i = 0; i < n ; ++i ) {
|
|
103 lua_pushstring(L, names[i]);
|
|
104 lua_pushcfunction(L, funs[i]);
|
|
105 lua_settable(L, -3);
|
|
106 }
|
|
107 }
|
|
108
|
|
109 // conversion utilities: l_to*
|
|
110
|
|
111 template<typename T> T to_string(const char* s);
|
|
112
|
|
113 int l_u64(lua_State *L)
|
|
114 {
|
|
115 switch( lua_type(L, 1) ) {
|
|
116 case LUA_TNIL: lua_push(L, (u64) 0 ); break;
|
|
117 case LUA_TNUMBER: lua_push(L, (u64) lua_tonumber(L, 1) ); break;
|
|
118 case LUA_TBOOLEAN: lua_push(L, (u64) lua_toboolean(L,1) ); break;
|
|
119 case LUA_TLIGHTUSERDATA: lua_push(L, (u64) lua_topointer(L, 1) ); break;
|
|
120 case LUA_TSTRING:
|
|
121 {
|
|
122 const char* ptr = lua_tostring(L, 1);
|
|
123 int base = 10;
|
|
124 if ( ptr[0] == '0' && ptr[1] == 'x' ) {
|
|
125 base = 16;
|
|
126 ptr += 2;
|
|
127 }
|
|
128 lua_push(L, (u64) strtoull( lua_tostring(L, 1), NULL, base ) );
|
|
129 break;
|
|
130 }
|
|
131 case LUA_TTABLE:
|
|
132 case LUA_TFUNCTION:
|
|
133 case LUA_TUSERDATA:
|
|
134 case LUA_TTHREAD:
|
|
135 return 0;
|
|
136 }
|
|
137 return 1;
|
|
138 }
|
|
139
|
|
140 int l_i64(lua_State *L)
|
|
141 {
|
|
142 switch( lua_type(L, 1) ) {
|
|
143 case LUA_TNIL: lua_push(L, (i64) 0 ); break;
|
|
144 case LUA_TNUMBER: lua_push(L, (i64) lua_tonumber(L, 1) ); break;
|
|
145 case LUA_TBOOLEAN: lua_push(L, (i64) lua_toboolean(L,1) ); break;
|
|
146 case LUA_TLIGHTUSERDATA: lua_push(L, (i64) lua_topointer(L, 1) ); break;
|
|
147 case LUA_TSTRING:
|
|
148 {
|
|
149 const char* ptr = lua_tostring(L, 1);
|
|
150 int base = 10;
|
|
151 if ( ptr[0] == '0' && ptr[1] == 'x' ) {
|
|
152 base = 16;
|
|
153 ptr += 2;
|
|
154 }
|
|
155 lua_push(L, (i64) strtoll( lua_tostring(L, 1), NULL, base ) );
|
|
156 break;
|
|
157 }
|
|
158 case LUA_TTABLE:
|
|
159 case LUA_TFUNCTION:
|
|
160 case LUA_TUSERDATA:
|
|
161 case LUA_TTHREAD:
|
|
162 return 0;
|
|
163 }
|
|
164 return 1;
|
|
165 }
|
|
166
|
|
167 extern "C" int luaopen_intutils(lua_State *L)
|
|
168 {
|
|
169 static luaL_Reg intutils[] = {
|
|
170 { "u64", l_u64 },
|
|
171 { "i64", l_i64 },
|
|
172 { NULL, NULL }
|
|
173 };
|
|
174 register_type<u64>(L, "u64");
|
|
175 register_type<i64>(L, "i64");
|
|
176 luaL_register(L, "intutils", intutils);
|
|
177 return 0;
|
|
178 }
|