fix constructor of version with a string argument
[liba.git] / lua / src / version.c
blob4bdb9043a73333ae68fa00aea5e5b7a2b5cb30be
1 /***
2 algorithm library version
3 @module liba.version
4 */
6 #include "version.h"
7 #include "a/version.h"
8 #undef a_version_check
10 static int liba_version_tostring(lua_State *L)
12 a_version const *const ctx = (a_version const *)lua_touserdata(L, 1);
13 if (ctx)
15 char str[48];
16 a_version_tostr(ctx, str, sizeof(str));
17 lua_pushstring(L, str);
18 return 1;
20 return 0;
23 static int liba_version_init_(lua_State *L, a_version *ctx, int arg, int top)
25 ctx->alpha[0] = '.';
26 ctx->alpha[1] = 0;
27 ctx->alpha[2] = 0;
28 ctx->alpha[3] = 0;
29 switch (top)
31 default:
32 case 4:
33 ctx->extra = (unsigned int)luaL_checkinteger(L, arg + 4);
34 A_FALLTHROUGH;
35 case 3:
36 ctx->third = (unsigned int)luaL_checkinteger(L, arg + 3);
37 A_FALLTHROUGH;
38 case 2:
39 ctx->minor = (unsigned int)luaL_checkinteger(L, arg + 2);
40 A_FALLTHROUGH;
41 case 1:
42 if (lua_type(L, arg + 1) == LUA_TSTRING)
44 a_version_parse(ctx, lua_tostring(L, arg + 1));
45 break;
47 ctx->major = (unsigned int)luaL_checkinteger(L, arg + 1);
48 A_FALLTHROUGH;
49 case 0:;
51 return 1;
54 /***
55 constructor for algorithm library version
56 @tparam[opt] integer major version major number
57 @tparam[opt] integer minor version minor number
58 @tparam[opt] integer third version third number
59 @tparam[opt] integer extra version extra number
60 @treturn a.version algorithm library version userdata
61 @function new
63 int liba_version_new(lua_State *L)
65 int const top = lua_gettop(L);
66 a_version *const ctx = lua_newclass(L, a_version);
67 a_zero(ctx, sizeof(a_version));
68 lua_registry_get(L, liba_version_new);
69 lua_setmetatable(L, -2);
70 return liba_version_init_(L, ctx, 0, top);
73 /***
74 initialize for algorithm library version
75 @tparam a.version ctx algorithm library version userdata
76 @tparam[opt] integer major version major number
77 @tparam[opt] integer minor version minor number
78 @tparam[opt] integer third version third number
79 @tparam[opt] integer extra version extra number
80 @treturn a.version algorithm library version userdata
81 @function init
83 int liba_version_init(lua_State *L)
85 int const top = lua_gettop(L);
86 luaL_checktype(L, 1, LUA_TUSERDATA);
87 a_version *const ctx = (a_version *)lua_touserdata(L, 1);
88 lua_pushvalue(L, 1);
89 return liba_version_init_(L, ctx, 1, top - 1);
92 /***
93 parse version string to version
94 @tparam a.version ctx algorithm library version userdata
95 @tparam string version string to be parsed
96 @treturn a.version algorithm library version userdata
97 @function parse
99 int liba_version_parse(lua_State *L)
101 a_version *const ctx = (a_version *)lua_touserdata(L, 1);
102 if (ctx)
104 a_version_parse(ctx, lua_tostring(L, 2));
105 lua_pushvalue(L, 1);
106 return 1;
108 return 0;
111 /***
112 algorithm library version check
113 @tparam integer major required major number
114 @tparam integer minor required minor number
115 @tparam integer patch required patch number
116 @treturn integer <0 library version is higher than required version
117 @treturn integer >0 library version is lower than required version
118 @treturn integer 0 library version is equal to required version
119 @function check
121 static int liba_version_check(lua_State *L)
123 a_version v = A_VERSION_C(0, 0, 0);
124 switch (lua_gettop(L) & 0x3)
126 case 3:
127 v.third = (unsigned int)luaL_checkinteger(L, 3);
128 A_FALLTHROUGH;
129 case 2:
130 v.minor = (unsigned int)luaL_checkinteger(L, 2);
131 A_FALLTHROUGH;
132 case 1:
133 v.major = (unsigned int)luaL_checkinteger(L, 1);
134 A_FALLTHROUGH;
135 default:
136 break;
138 lua_pushinteger(L, a_version_check(v.major, v.minor, v.third));
139 return 1;
142 /***
143 compare the version lhs with the version rhs
144 @tparam a.version lhs version userdata on the left
145 @tparam a.version rhs version userdata on the right
146 @treturn integer <0 version lhs < version rhs
147 @treturn integer >0 version lhs > version rhs
148 @treturn integer 0 version lhs == version rhs
149 @function cmp
151 int liba_version_cmp(lua_State *L)
153 luaL_checktype(L, 1, LUA_TUSERDATA);
154 luaL_checktype(L, 2, LUA_TUSERDATA);
155 a_version const *const lhs = (a_version const *)lua_touserdata(L, 1);
156 a_version const *const rhs = (a_version const *)lua_touserdata(L, 2);
157 lua_pushinteger(L, a_version_cmp(lhs, rhs));
158 return 1;
161 #undef FUNC
162 #define FUNC(func) \
163 int liba_version_##func(lua_State *L) \
165 luaL_checktype(L, 1, LUA_TUSERDATA); \
166 luaL_checktype(L, 2, LUA_TUSERDATA); \
167 a_version *lhs = (a_version *)lua_touserdata(L, 1); \
168 a_version *rhs = (a_version *)lua_touserdata(L, 2); \
169 lua_pushboolean(L, a_version_##func(lhs, rhs)); \
170 return 1; \
172 /***
173 version lhs is less than version rhs
174 @tparam a.version lhs version userdata on the left
175 @tparam a.version rhs version userdata on the right
176 @treturn bool result of comparison
177 @function lt
179 FUNC(lt)
180 /***
181 version lhs is greater than version rhs
182 @tparam a.version lhs version userdata on the left
183 @tparam a.version rhs version userdata on the right
184 @treturn bool result of comparison
185 @function gt
187 FUNC(gt)
188 /***
189 version lhs is less than or equal to version rhs
190 @tparam a.version lhs version userdata on the left
191 @tparam a.version rhs version userdata on the right
192 @treturn bool result of comparison
193 @function le
195 FUNC(le)
196 /***
197 version lhs is greater than or equal to version rhs
198 @tparam a.version lhs version userdata on the left
199 @tparam a.version rhs version userdata on the right
200 @treturn bool result of comparison
201 @function ge
203 FUNC(ge)
204 /***
205 version lhs is equal to version rhs
206 @tparam a.version lhs version userdata on the left
207 @tparam a.version rhs version userdata on the right
208 @treturn bool result of comparison
209 @function eq
211 FUNC(eq)
212 /***
213 version lhs is not equal to version rhs
214 @tparam a.version lhs version userdata on the left
215 @tparam a.version rhs version userdata on the right
216 @treturn bool result of comparison
217 @function ne
219 FUNC(ne)
221 static int liba_version_set(lua_State *L)
223 a_version *const ctx = (a_version *)lua_touserdata(L, 1);
224 switch (a_hash_bkdr(lua_tostring(L, 2), 0))
226 case 0x86720331: // major
227 ctx->major = (unsigned int)luaL_checkinteger(L, 3);
228 break;
229 case 0x87857C2D: // minor
230 ctx->minor = (unsigned int)luaL_checkinteger(L, 3);
231 break;
232 case 0x0241DD17: // third
233 ctx->third = (unsigned int)luaL_checkinteger(L, 3);
234 break;
235 case 0xFD1BE968: // extra
236 ctx->extra = (unsigned int)luaL_checkinteger(L, 3);
237 break;
238 case 0xB5485B9E: // alpha
240 char const *alpha = luaL_checklstring(L, 3, 0);
241 a_version_set_alpha(ctx, alpha);
242 break;
244 case 0x0CD3E494: // __lt
245 case 0x0CD3E485: // __le
246 case 0x0CD3E0FC: // __eq
247 case 0xE8859EEB: // __name
248 case 0xE70C48C6: // __call
249 case 0xA65758B2: // __index
250 case 0xAEB551C6: // __newindex
251 case 0x5DA21A54: // __tostring
252 break;
253 default:
254 lua_getmetatable(L, 1);
255 lua_replace(L, 1);
256 lua_rawset(L, 1);
258 return 0;
261 static int liba_version_get(lua_State *L)
263 a_version const *const ctx = (a_version const *)lua_touserdata(L, 1);
264 switch (a_hash_bkdr(lua_tostring(L, 2), 0))
266 case 0x86720331: // major
267 lua_pushinteger(L, (lua_Integer)ctx->major);
268 break;
269 case 0x87857C2D: // minor
270 lua_pushinteger(L, (lua_Integer)ctx->minor);
271 break;
272 case 0x0241DD17: // third
273 lua_pushinteger(L, (lua_Integer)ctx->third);
274 break;
275 case 0xFD1BE968: // extra
276 lua_pushinteger(L, (lua_Integer)ctx->extra);
277 break;
278 case 0xB5485B9E: // alpha
280 char alpha[sizeof(ctx->alpha) + 1];
281 a_version_alpha(ctx, alpha);
282 lua_pushstring(L, alpha);
283 break;
285 case 0xA65758B2: // __index
286 lua_registry_get(L, liba_version_new);
287 lua_int_set(L, -1, "major", (lua_Integer)ctx->major);
288 lua_int_set(L, -1, "minor", (lua_Integer)ctx->minor);
289 lua_int_set(L, -1, "third", (lua_Integer)ctx->third);
290 lua_int_set(L, -1, "extra", (lua_Integer)ctx->extra);
291 lua_str_set(L, -1, "alpha", ".");
292 break;
293 default:
294 lua_getmetatable(L, 1);
295 lua_replace(L, 1);
296 lua_rawget(L, 1);
298 return 1;
301 static int liba_version_(lua_State *L)
303 lua_pushcfunction(L, liba_version_new);
304 lua_replace(L, 1);
305 lua_call(L, lua_gettop(L) - 1, 1);
306 return 1;
309 int luaopen_liba_version(lua_State *L)
311 /***
312 algorithm library version number
313 @field MAJOR algorithm library version major
314 @field MINOR algorithm library version minor
315 @field PATCH algorithm library version patch
316 @field TWEAK algorithm library version tweak
317 @table liba.version
319 static lua_int const enums[] = {
320 {"MAJOR", A_VERSION_MAJOR},
321 {"MINOR", A_VERSION_MINOR},
322 {"PATCH", A_VERSION_PATCH},
323 {"TWEAK", A_VERSION_TWEAK},
325 static lua_fun const funcs[] = {
326 {"check", liba_version_check},
327 {"parse", liba_version_parse},
328 {"init", liba_version_init},
329 {"new", liba_version_new},
330 {"cmp", liba_version_cmp},
331 {"lt", liba_version_lt},
332 {"gt", liba_version_gt},
333 {"le", liba_version_le},
334 {"ge", liba_version_ge},
335 {"eq", liba_version_eq},
336 {"ne", liba_version_ne},
338 lua_createtable(L, 0, A_LEN(enums) + A_LEN(funcs));
339 lua_int_reg(L, -1, enums, A_LEN(enums));
340 lua_fun_reg(L, -1, funcs, A_LEN(funcs));
341 lua_createtable(L, 0, 1);
342 lua_fun_set(L, -1, "__call", liba_version_);
343 lua_setmetatable(L, -2);
345 static lua_fun const metas[] = {
346 {"__tostring", liba_version_tostring},
347 {"__newindex", liba_version_set},
348 {"__index", liba_version_get},
349 {"__call", liba_version_init},
350 {"__eq", liba_version_eq},
351 {"__lt", liba_version_lt},
352 {"__le", liba_version_le},
354 lua_createtable(L, 0, A_LEN(metas) + A_LEN(funcs));
355 lua_fun_reg(L, -1, metas, A_LEN(metas));
356 lua_fun_reg(L, -1, funcs + 1, A_LEN(funcs) - 1);
357 lua_str_set(L, -1, "__name", "a.version");
358 lua_registry_set(L, liba_version_new);
360 return 1;