annotate lua/luadyncall/src/intutils.cpp @ 62:4a9f6c7c09c1 default tip

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