New luaX_set_up_metatable() helper function

Reduces boilerplate code for initialization of Lua classes.
This commit is contained in:
Jochen Topf
2025-07-07 09:46:29 +02:00
parent 48a6bd4d77
commit 20f061d844
7 changed files with 85 additions and 130 deletions

View File

@ -99,31 +99,14 @@ int setup_flex_expire_output(lua_State *lua_state,
*/
void lua_wrapper_expire_output::init(lua_State *lua_state)
{
lua_getglobal(lua_state, "osm2pgsql");
if (luaL_newmetatable(lua_state, OSM2PGSQL_EXPIRE_OUTPUT_CLASS) != 1) {
throw std::runtime_error{"Internal error: Lua newmetatable failed."};
}
lua_pushvalue(lua_state, -1); // Copy of new metatable
// Add metatable as osm2pgsql.ExpireOutput so we can access it from Lua
lua_setfield(lua_state, -3, "ExpireOutput");
// Now add functions to metatable
lua_pushvalue(lua_state, -1);
lua_setfield(lua_state, -2, "__index");
luaX_add_table_func(lua_state, "__tostring",
lua_trampoline_expire_output_tostring);
luaX_add_table_func(lua_state, "filename",
lua_trampoline_expire_output_filename);
luaX_add_table_func(lua_state, "maxzoom",
lua_trampoline_expire_output_maxzoom);
luaX_add_table_func(lua_state, "minzoom",
lua_trampoline_expire_output_minzoom);
luaX_add_table_func(lua_state, "schema",
lua_trampoline_expire_output_schema);
luaX_add_table_func(lua_state, "table", lua_trampoline_expire_output_table);
lua_pop(lua_state, 2);
luaX_set_up_metatable(
lua_state, "ExpireOutput", OSM2PGSQL_EXPIRE_OUTPUT_CLASS,
{{"__tostring", lua_trampoline_expire_output_tostring},
{"filename", lua_trampoline_expire_output_filename},
{"maxzoom", lua_trampoline_expire_output_maxzoom},
{"minzoom", lua_trampoline_expire_output_minzoom},
{"schema", lua_trampoline_expire_output_schema},
{"table", lua_trampoline_expire_output_table}});
}
int lua_wrapper_expire_output::tostring() const

View File

@ -300,37 +300,25 @@ int geom_transform(lua_State *lua_state)
void init_geometry_class(lua_State *lua_state)
{
lua_getglobal(lua_state, "osm2pgsql");
if (luaL_newmetatable(lua_state, OSM2PGSQL_GEOMETRY_CLASS) != 1) {
throw std::runtime_error{"Internal error: Lua newmetatable failed."};
}
lua_pushvalue(lua_state, -1); // Copy of new metatable
// Add metatable as osm2pgsql.Geometry so we can access it from Lua
lua_setfield(lua_state, -3, "Geometry");
lua_pushvalue(lua_state, -1);
lua_setfield(lua_state, -2, "__index");
luaX_add_table_func(lua_state, "__gc", geom_gc);
luaX_add_table_func(lua_state, "__len", geom_num_geometries);
luaX_add_table_func(lua_state, "__tostring", geom_tostring);
luaX_add_table_func(lua_state, "area", geom_area);
luaX_add_table_func(lua_state, "length", geom_length);
luaX_add_table_func(lua_state, "centroid", geom_centroid);
luaX_add_table_func(lua_state, "get_bbox", geom_get_bbox);
luaX_add_table_func(lua_state, "geometry_n", geom_geometry_n);
luaX_add_table_func(lua_state, "geometry_type", geom_geometry_type);
luaX_add_table_func(lua_state, "is_null", geom_is_null);
luaX_add_table_func(lua_state, "line_merge", geom_line_merge);
luaX_add_table_func(lua_state, "reverse", geom_reverse);
luaX_add_table_func(lua_state, "num_geometries", geom_num_geometries);
luaX_add_table_func(lua_state, "pole_of_inaccessibility",
geom_pole_of_inaccessibility);
luaX_add_table_func(lua_state, "segmentize", geom_segmentize);
luaX_add_table_func(lua_state, "simplify", geom_simplify);
luaX_add_table_func(lua_state, "spherical_area", geom_spherical_area);
luaX_add_table_func(lua_state, "srid", geom_srid);
luaX_add_table_func(lua_state, "transform", geom_transform);
lua_pop(lua_state, 2); // __index, global osmp2gsql
luaX_set_up_metatable(
lua_state, "Geometry", OSM2PGSQL_GEOMETRY_CLASS,
{{"__gc", geom_gc},
{"__len", geom_num_geometries},
{"__tostring", geom_tostring},
{"area", geom_area},
{"length", geom_length},
{"centroid", geom_centroid},
{"get_bbox", geom_get_bbox},
{"geometry_n", geom_geometry_n},
{"geometry_type", geom_geometry_type},
{"is_null", geom_is_null},
{"line_merge", geom_line_merge},
{"reverse", geom_reverse},
{"num_geometries", geom_num_geometries},
{"pole_of_inaccessibility", geom_pole_of_inaccessibility},
{"segmentize", geom_segmentize},
{"simplify", geom_simplify},
{"spherical_area", geom_spherical_area},
{"srid", geom_srid},
{"transform", geom_transform}});
}

View File

@ -70,30 +70,14 @@ void lua_wrapper_locator::init(lua_State *lua_state,
{
s_connection_params = connection_params;
lua_getglobal(lua_state, "osm2pgsql");
if (luaL_newmetatable(lua_state, OSM2PGSQL_LOCATOR_CLASS) != 1) {
throw std::runtime_error{"Internal error: Lua newmetatable failed."};
}
lua_pushvalue(lua_state, -1); // Copy of new metatable
// Add metatable as osm2pgsql.Locator so we can access it from Lua
lua_setfield(lua_state, -3, "Locator");
// Now add functions to metatable
lua_pushvalue(lua_state, -1);
lua_setfield(lua_state, -2, "__index");
luaX_add_table_func(lua_state, "__tostring",
lua_trampoline_locator_tostring);
luaX_add_table_func(lua_state, "name", lua_trampoline_locator_name);
luaX_add_table_func(lua_state, "add_bbox", lua_trampoline_locator_add_bbox);
luaX_add_table_func(lua_state, "add_from_db",
lua_trampoline_locator_add_from_db);
luaX_add_table_func(lua_state, "all_intersecting",
lua_trampoline_locator_all_intersecting);
luaX_add_table_func(lua_state, "first_intersecting",
lua_trampoline_locator_first_intersecting);
lua_pop(lua_state, 2);
luaX_set_up_metatable(
lua_state, "Locator", OSM2PGSQL_LOCATOR_CLASS,
{{"__tostring", lua_trampoline_locator_tostring},
{"name", lua_trampoline_locator_name},
{"add_bbox", lua_trampoline_locator_add_bbox},
{"add_from_db", lua_trampoline_locator_add_from_db},
{"all_intersecting", lua_trampoline_locator_all_intersecting},
{"first_intersecting", lua_trampoline_locator_first_intersecting}});
}
int lua_wrapper_locator::tostring() const

View File

@ -457,27 +457,13 @@ int setup_flex_table(lua_State *lua_state, std::vector<flex_table_t> *tables,
*/
void lua_wrapper_table::init(lua_State *lua_state)
{
lua_getglobal(lua_state, "osm2pgsql");
if (luaL_newmetatable(lua_state, OSM2PGSQL_TABLE_CLASS) != 1) {
throw std::runtime_error{"Internal error: Lua newmetatable failed."};
}
lua_pushvalue(lua_state, -1); // Copy of new metatable
// Add metatable as osm2pgsql.Table so we can access it from Lua
lua_setfield(lua_state, -3, "Table");
// Now add functions to metatable
lua_pushvalue(lua_state, -1);
lua_setfield(lua_state, -2, "__index");
luaX_add_table_func(lua_state, "__tostring",
lua_trampoline_table_tostring);
luaX_add_table_func(lua_state, "insert", lua_trampoline_table_insert);
luaX_add_table_func(lua_state, "name", lua_trampoline_table_name);
luaX_add_table_func(lua_state, "schema", lua_trampoline_table_schema);
luaX_add_table_func(lua_state, "cluster", lua_trampoline_table_cluster);
luaX_add_table_func(lua_state, "columns", lua_trampoline_table_columns);
lua_pop(lua_state, 2);
luaX_set_up_metatable(lua_state, "Table", OSM2PGSQL_TABLE_CLASS,
{{"__tostring", lua_trampoline_table_tostring},
{"insert", lua_trampoline_table_insert},
{"name", lua_trampoline_table_name},
{"schema", lua_trampoline_table_schema},
{"cluster", lua_trampoline_table_cluster},
{"columns", lua_trampoline_table_columns}});
}
int lua_wrapper_table::tostring() const

View File

@ -115,6 +115,32 @@ void luaX_add_table_func(lua_State *lua_state, char const *key,
lua_rawset(lua_state, -3);
}
void luaX_set_up_metatable(
lua_State *lua_state, char const *name, char const *luaclass,
std::initializer_list<std::pair<char const *, lua_CFunction>> map)
{
lua_getglobal(lua_state, "osm2pgsql");
if (luaL_newmetatable(lua_state, luaclass) != 1) {
throw std::runtime_error{"Internal error: Lua newmetatable failed."};
}
lua_pushvalue(lua_state, -1); // Copy of new metatable
// Add metatable under the specified name so we can access it from Lua
lua_setfield(lua_state, -3, name);
// Now add functions to metatable
lua_pushvalue(lua_state, -1);
lua_setfield(lua_state, -2, "__index");
for (auto const &[key, func] : map) {
lua_pushstring(lua_state, key);
lua_pushcfunction(lua_state, func);
lua_rawset(lua_state, -3);
}
lua_settop(lua_state, 0);
}
char const *luaX_get_table_string(lua_State *lua_state, char const *key,
int table_index, char const *error_msg)
{

View File

@ -17,6 +17,7 @@
#include <cassert>
#include <cstdint>
#include <initializer_list>
#include <string_view>
#include <utility>
@ -38,6 +39,10 @@ void luaX_add_table_bool(lua_State *lua_state, char const *key,
void luaX_add_table_func(lua_State *lua_state, char const *key,
lua_CFunction func) noexcept;
void luaX_set_up_metatable(
lua_State *lua_state, char const *name, char const *luaclass,
std::initializer_list<std::pair<char const *, lua_CFunction>> map);
template <typename COLLECTION, typename FUNC>
void luaX_add_table_array(lua_State *lua_state, char const *key,
COLLECTION const &collection, FUNC const &func)

View File

@ -1305,33 +1305,16 @@ void output_flex_t::init_lua(std::string const &filename,
assert(lua_gettop(lua_state()) == 0);
lua_getglobal(lua_state(), "osm2pgsql");
if (luaL_newmetatable(lua_state(), OSM2PGSQL_OSMOBJECT_CLASS) != 1) {
throw std::runtime_error{"Internal error: Lua newmetatable failed."};
}
lua_pushvalue(lua_state(), -1); // Copy of new metatable
// Add metatable as osm2pgsql.OSMObject so we can access it from Lua
lua_setfield(lua_state(), -3, "OSMObject");
lua_pushvalue(lua_state(), -1);
lua_setfield(lua_state(), -2, "__index");
luaX_add_table_func(lua_state(), "get_bbox", lua_trampoline_app_get_bbox);
luaX_add_table_func(lua_state(), "as_linestring",
lua_trampoline_app_as_linestring);
luaX_add_table_func(lua_state(), "as_point",
lua_trampoline_app_as_point);
luaX_add_table_func(lua_state(), "as_polygon",
lua_trampoline_app_as_polygon);
luaX_add_table_func(lua_state(), "as_multipoint",
lua_trampoline_app_as_multipoint);
luaX_add_table_func(lua_state(), "as_multilinestring",
lua_trampoline_app_as_multilinestring);
luaX_add_table_func(lua_state(), "as_multipolygon",
lua_trampoline_app_as_multipolygon);
luaX_add_table_func(lua_state(), "as_geometrycollection",
lua_trampoline_app_as_geometrycollection);
lua_settop(lua_state(), 0);
luaX_set_up_metatable(
lua_state(), "OSMObject", OSM2PGSQL_OSMOBJECT_CLASS,
{{"get_bbox", lua_trampoline_app_get_bbox},
{"as_linestring", lua_trampoline_app_as_linestring},
{"as_point", lua_trampoline_app_as_point},
{"as_polygon", lua_trampoline_app_as_polygon},
{"as_multipoint", lua_trampoline_app_as_multipoint},
{"as_multilinestring", lua_trampoline_app_as_multilinestring},
{"as_multipolygon", lua_trampoline_app_as_multipolygon},
{"as_geometrycollection", lua_trampoline_app_as_geometrycollection}});
// Load compiled in init.lua
if (luaL_dostring(lua_state(), lua_init())) {