Mercurial > pub > dyncall > bindings
comparison lua/luadyncall/src/intutils.cpp @ 0:0cfcc391201f
initial from svn dyncall-1745
author | Daniel Adler |
---|---|
date | Thu, 19 Mar 2015 22:26:28 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:0cfcc391201f |
---|---|
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 } |