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) void lua_wrapper_expire_output::init(lua_State *lua_state)
{ {
lua_getglobal(lua_state, "osm2pgsql"); luaX_set_up_metatable(
if (luaL_newmetatable(lua_state, OSM2PGSQL_EXPIRE_OUTPUT_CLASS) != 1) { lua_state, "ExpireOutput", OSM2PGSQL_EXPIRE_OUTPUT_CLASS,
throw std::runtime_error{"Internal error: Lua newmetatable failed."}; {{"__tostring", lua_trampoline_expire_output_tostring},
} {"filename", lua_trampoline_expire_output_filename},
lua_pushvalue(lua_state, -1); // Copy of new metatable {"maxzoom", lua_trampoline_expire_output_maxzoom},
{"minzoom", lua_trampoline_expire_output_minzoom},
// Add metatable as osm2pgsql.ExpireOutput so we can access it from Lua {"schema", lua_trampoline_expire_output_schema},
lua_setfield(lua_state, -3, "ExpireOutput"); {"table", lua_trampoline_expire_output_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_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);
} }
int lua_wrapper_expire_output::tostring() const 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) void init_geometry_class(lua_State *lua_state)
{ {
lua_getglobal(lua_state, "osm2pgsql"); luaX_set_up_metatable(
if (luaL_newmetatable(lua_state, OSM2PGSQL_GEOMETRY_CLASS) != 1) { lua_state, "Geometry", OSM2PGSQL_GEOMETRY_CLASS,
throw std::runtime_error{"Internal error: Lua newmetatable failed."}; {{"__gc", geom_gc},
} {"__len", geom_num_geometries},
lua_pushvalue(lua_state, -1); // Copy of new metatable {"__tostring", geom_tostring},
{"area", geom_area},
// Add metatable as osm2pgsql.Geometry so we can access it from Lua {"length", geom_length},
lua_setfield(lua_state, -3, "Geometry"); {"centroid", geom_centroid},
{"get_bbox", geom_get_bbox},
lua_pushvalue(lua_state, -1); {"geometry_n", geom_geometry_n},
lua_setfield(lua_state, -2, "__index"); {"geometry_type", geom_geometry_type},
luaX_add_table_func(lua_state, "__gc", geom_gc); {"is_null", geom_is_null},
luaX_add_table_func(lua_state, "__len", geom_num_geometries); {"line_merge", geom_line_merge},
luaX_add_table_func(lua_state, "__tostring", geom_tostring); {"reverse", geom_reverse},
luaX_add_table_func(lua_state, "area", geom_area); {"num_geometries", geom_num_geometries},
luaX_add_table_func(lua_state, "length", geom_length); {"pole_of_inaccessibility", geom_pole_of_inaccessibility},
luaX_add_table_func(lua_state, "centroid", geom_centroid); {"segmentize", geom_segmentize},
luaX_add_table_func(lua_state, "get_bbox", geom_get_bbox); {"simplify", geom_simplify},
luaX_add_table_func(lua_state, "geometry_n", geom_geometry_n); {"spherical_area", geom_spherical_area},
luaX_add_table_func(lua_state, "geometry_type", geom_geometry_type); {"srid", geom_srid},
luaX_add_table_func(lua_state, "is_null", geom_is_null); {"transform", geom_transform}});
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
} }

View File

@ -70,30 +70,14 @@ void lua_wrapper_locator::init(lua_State *lua_state,
{ {
s_connection_params = connection_params; s_connection_params = connection_params;
lua_getglobal(lua_state, "osm2pgsql"); luaX_set_up_metatable(
if (luaL_newmetatable(lua_state, OSM2PGSQL_LOCATOR_CLASS) != 1) { lua_state, "Locator", OSM2PGSQL_LOCATOR_CLASS,
throw std::runtime_error{"Internal error: Lua newmetatable failed."}; {{"__tostring", lua_trampoline_locator_tostring},
} {"name", lua_trampoline_locator_name},
lua_pushvalue(lua_state, -1); // Copy of new metatable {"add_bbox", lua_trampoline_locator_add_bbox},
{"add_from_db", lua_trampoline_locator_add_from_db},
// Add metatable as osm2pgsql.Locator so we can access it from Lua {"all_intersecting", lua_trampoline_locator_all_intersecting},
lua_setfield(lua_state, -3, "Locator"); {"first_intersecting", lua_trampoline_locator_first_intersecting}});
// 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);
} }
int lua_wrapper_locator::tostring() const 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) void lua_wrapper_table::init(lua_State *lua_state)
{ {
lua_getglobal(lua_state, "osm2pgsql"); luaX_set_up_metatable(lua_state, "Table", OSM2PGSQL_TABLE_CLASS,
if (luaL_newmetatable(lua_state, OSM2PGSQL_TABLE_CLASS) != 1) { {{"__tostring", lua_trampoline_table_tostring},
throw std::runtime_error{"Internal error: Lua newmetatable failed."}; {"insert", lua_trampoline_table_insert},
} {"name", lua_trampoline_table_name},
lua_pushvalue(lua_state, -1); // Copy of new metatable {"schema", lua_trampoline_table_schema},
{"cluster", lua_trampoline_table_cluster},
// Add metatable as osm2pgsql.Table so we can access it from Lua {"columns", lua_trampoline_table_columns}});
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);
} }
int lua_wrapper_table::tostring() const 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); 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, char const *luaX_get_table_string(lua_State *lua_state, char const *key,
int table_index, char const *error_msg) int table_index, char const *error_msg)
{ {

View File

@ -17,6 +17,7 @@
#include <cassert> #include <cassert>
#include <cstdint> #include <cstdint>
#include <initializer_list>
#include <string_view> #include <string_view>
#include <utility> #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, void luaX_add_table_func(lua_State *lua_state, char const *key,
lua_CFunction func) noexcept; 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> template <typename COLLECTION, typename FUNC>
void luaX_add_table_array(lua_State *lua_state, char const *key, void luaX_add_table_array(lua_State *lua_state, char const *key,
COLLECTION const &collection, FUNC const &func) 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); assert(lua_gettop(lua_state()) == 0);
lua_getglobal(lua_state(), "osm2pgsql"); luaX_set_up_metatable(
if (luaL_newmetatable(lua_state(), OSM2PGSQL_OSMOBJECT_CLASS) != 1) { lua_state(), "OSMObject", OSM2PGSQL_OSMOBJECT_CLASS,
throw std::runtime_error{"Internal error: Lua newmetatable failed."}; {{"get_bbox", lua_trampoline_app_get_bbox},
} {"as_linestring", lua_trampoline_app_as_linestring},
lua_pushvalue(lua_state(), -1); // Copy of new metatable {"as_point", lua_trampoline_app_as_point},
{"as_polygon", lua_trampoline_app_as_polygon},
// Add metatable as osm2pgsql.OSMObject so we can access it from Lua {"as_multipoint", lua_trampoline_app_as_multipoint},
lua_setfield(lua_state(), -3, "OSMObject"); {"as_multilinestring", lua_trampoline_app_as_multilinestring},
{"as_multipolygon", lua_trampoline_app_as_multipolygon},
lua_pushvalue(lua_state(), -1); {"as_geometrycollection", lua_trampoline_app_as_geometrycollection}});
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);
// Load compiled in init.lua // Load compiled in init.lua
if (luaL_dostring(lua_state(), lua_init())) { if (luaL_dostring(lua_state(), lua_init())) {