#include "version.h"
#include "a/version.h"
static int liba_version_tostring(lua_State *L)
{
a_version const *const ctx = (a_version const *)lua_touserdata(L, 1);
if (ctx)
{
char str[48];
a_version_tostr(ctx, str, sizeof(str));
lua_pushstring(L, str);
return 1;
}
return 0;
}
static int liba_version_init_(lua_State *L, a_version *ctx, int arg, int top)
{
ctx->alpha_[0] = '.';
ctx->alpha_[1] = 0;
ctx->alpha_[2] = 0;
ctx->alpha_[3] = 0;
switch (top)
{
default:
case 4:
ctx->extra = (unsigned int)luaL_checkinteger(L, arg + 4);
A_FALLTHROUGH;
case 3:
ctx->third = (unsigned int)luaL_checkinteger(L, arg + 3);
A_FALLTHROUGH;
case 2:
ctx->minor = (unsigned int)luaL_checkinteger(L, arg + 2);
A_FALLTHROUGH;
case 1:
if (lua_type(L, arg + 1) == LUA_TSTRING)
{
a_version_parse(ctx, lua_tostring(L, arg + 1));
break;
}
ctx->major = (unsigned int)luaL_checkinteger(L, arg + 1);
A_FALLTHROUGH;
case 0:;
}
return 1;
}
int liba_version_new(lua_State *L)
{
int const top = lua_gettop(L);
a_version *const ctx = lua_newclass(L, a_version);
a_zero(ctx, sizeof(a_version));
lua_registry_get(L, liba_version_new);
lua_setmetatable(L, -2);
return liba_version_init_(L, ctx, 0, top);
}
int liba_version_init(lua_State *L)
{
int const top = lua_gettop(L);
luaL_checktype(L, 1, LUA_TUSERDATA);
a_version *const ctx = (a_version *)lua_touserdata(L, 1);
lua_pushvalue(L, 1);
return liba_version_init_(L, ctx, 1, top - 1);
}
int liba_version_parse(lua_State *L)
{
a_version *const ctx = (a_version *)lua_touserdata(L, 1);
if (ctx)
{
a_version_parse(ctx, lua_tostring(L, 2));
lua_pushvalue(L, 1);
return 1;
}
return 0;
}
static int liba_version_check(lua_State *L)
{
a_version v = A_VERSION_0();
switch (lua_gettop(L) & 0x3)
{
case 3:
v.third = (unsigned int)luaL_checkinteger(L, 3);
A_FALLTHROUGH;
case 2:
v.minor = (unsigned int)luaL_checkinteger(L, 2);
A_FALLTHROUGH;
case 1:
v.major = (unsigned int)luaL_checkinteger(L, 1);
A_FALLTHROUGH;
default:
break;
}
lua_pushinteger(L, a_version_check(v.major, v.minor, v.third));
return 1;
}
int liba_version_cmp(lua_State *L)
{
luaL_checktype(L, 1, LUA_TUSERDATA);
luaL_checktype(L, 2, LUA_TUSERDATA);
a_version const *const lhs = (a_version const *)lua_touserdata(L, 1);
a_version const *const rhs = (a_version const *)lua_touserdata(L, 2);
lua_pushinteger(L, a_version_cmp(lhs, rhs));
return 1;
}
#undef F2
#define F2(func) \
int liba_version_##func(lua_State *L) \
{ \
luaL_checktype(L, 1, LUA_TUSERDATA); \
luaL_checktype(L, 2, LUA_TUSERDATA); \
a_version *lhs = (a_version *)lua_touserdata(L, 1); \
a_version *rhs = (a_version *)lua_touserdata(L, 2); \
lua_pushboolean(L, a_version_##func(lhs, rhs)); \
return 1; \
}
F2(lt)
F2(gt)
F2(le)
F2(ge)
F2(eq)
F2(ne)
static int liba_version_set(lua_State *L)
{
a_version *const ctx = (a_version *)lua_touserdata(L, 1);
switch (a_hash_bkdr(lua_tostring(L, 2), 0))
{
case 0x86720331: ctx->major = (unsigned int)luaL_checkinteger(L, 3);
break;
case 0x87857C2D: ctx->minor = (unsigned int)luaL_checkinteger(L, 3);
break;
case 0x0241DD17: ctx->third = (unsigned int)luaL_checkinteger(L, 3);
break;
case 0xFD1BE968: ctx->extra = (unsigned int)luaL_checkinteger(L, 3);
break;
case 0xB5485B9E: {
char const *alpha = luaL_checklstring(L, 3, 0);
a_version_set_alpha(ctx, alpha);
break;
}
case 0x0CD3E494: case 0x0CD3E485: case 0x0CD3E0FC: case 0xE8859EEB: case 0xE70C48C6: case 0xA65758B2: case 0xAEB551C6: case 0x5DA21A54: break;
default:
lua_getmetatable(L, 1);
lua_replace(L, 1);
lua_rawset(L, 1);
}
return 0;
}
static int liba_version_get(lua_State *L)
{
a_version const *const ctx = (a_version const *)lua_touserdata(L, 1);
switch (a_hash_bkdr(lua_tostring(L, 2), 0))
{
case 0x86720331: lua_pushinteger(L, (lua_Integer)ctx->major);
break;
case 0x87857C2D: lua_pushinteger(L, (lua_Integer)ctx->minor);
break;
case 0x0241DD17: lua_pushinteger(L, (lua_Integer)ctx->third);
break;
case 0xFD1BE968: lua_pushinteger(L, (lua_Integer)ctx->extra);
break;
case 0xB5485B9E: {
char alpha[sizeof(ctx->alpha_) + 1];
a_version_alpha(ctx, alpha);
lua_pushstring(L, alpha);
break;
}
case 0xA65758B2: lua_registry_get(L, liba_version_new);
lua_int_set(L, -1, "major", (lua_Integer)ctx->major);
lua_int_set(L, -1, "minor", (lua_Integer)ctx->minor);
lua_int_set(L, -1, "third", (lua_Integer)ctx->third);
lua_int_set(L, -1, "extra", (lua_Integer)ctx->extra);
lua_str_set(L, -1, "alpha", ".");
break;
default:
lua_getmetatable(L, 1);
lua_replace(L, 1);
lua_rawget(L, 1);
}
return 1;
}
static int liba_version_(lua_State *L)
{
lua_pushcfunction(L, liba_version_new);
lua_replace(L, 1);
lua_call(L, lua_gettop(L) - 1, 1);
return 1;
}
int luaopen_liba_version(lua_State *L)
{
static lua_int const enums[] = {
{"MAJOR", A_VERSION_MAJOR},
{"MINOR", A_VERSION_MINOR},
{"PATCH", A_VERSION_PATCH},
{"TWEAK", A_VERSION_TWEAK},
};
static lua_fun const funcs[] = {
{"check", liba_version_check},
{"parse", liba_version_parse},
{"init", liba_version_init},
{"new", liba_version_new},
{"cmp", liba_version_cmp},
{"lt", liba_version_lt},
{"gt", liba_version_gt},
{"le", liba_version_le},
{"ge", liba_version_ge},
{"eq", liba_version_eq},
{"ne", liba_version_ne},
};
lua_createtable(L, 0, A_LEN(enums) + A_LEN(funcs));
lua_int_reg(L, -1, enums, A_LEN(enums));
lua_fun_reg(L, -1, funcs, A_LEN(funcs));
lua_createtable(L, 0, 1);
lua_fun_set(L, -1, "__call", liba_version_);
lua_setmetatable(L, -2);
static lua_fun const metas[] = {
{"__tostring", liba_version_tostring},
{"__newindex", liba_version_set},
{"__index", liba_version_get},
{"__call", liba_version_init},
{"__eq", liba_version_eq},
{"__lt", liba_version_lt},
{"__le", liba_version_le},
};
lua_createtable(L, 0, A_LEN(metas) + A_LEN(funcs));
lua_fun_reg(L, -1, metas, A_LEN(metas));
lua_fun_reg(L, -1, funcs + 1, A_LEN(funcs) - 1);
lua_str_set(L, -1, "__name", "a.version");
lua_registry_set(L, liba_version_new);
return 1;
}