Skip to content

Commit 87b9417

Browse files
committed
Refactor: Split out some code from output_flex_t class
The class output_flex_t is huge, output-flex.cpp with over 1000 lines is the largest source code file we have. This change moves some code out of there. This change introduces a new templated wrapper base class (lua_wrapper_base) for wrapping C++ objects in Lua. It is then used for the "Table" and "ExpireOutput" Lua objects. Functions that are called from Lua on those objects are called through the wrapper on the underlying C++ objects using little wrapper functions in the wrapper classes. A new macro TRAMPOLINE_WRAPPED_OBJECT() is used to call these functions where we used the TRAMPOLINE() macro before. One problem is though that more complex functions need more of the machinery in the output_flex_t class to work, specifically this is the "insert" function for tables which can not be implemented without full access to the output_flex_t class. So this function keeps using the old mechanism. This also changes the get_from_idx_param() helper function and the functions using it (output_flex_t::[get_table|expire_output]_from_param()) to return a reference instead of a const reference so that the wrapper will be initialized with a mutable pointer to the underlying C++ class. Currently all functions that can be called through the wrapper are const functions, but this will not necessarily always be the case in the future.
1 parent e0c6cdf commit 87b9417

File tree

7 files changed

+295
-223
lines changed

7 files changed

+295
-223
lines changed

src/flex-lua-expire-output.cpp

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
#include "expire-output.hpp"
1313
#include "format.hpp"
1414
#include "lua-utils.hpp"
15-
#include "pgsql.hpp"
16-
#include "util.hpp"
1715

1816
#include <lua.hpp>
1917

@@ -67,6 +65,13 @@ create_expire_output(lua_State *lua_state, std::string const &default_schema,
6765
return new_expire_output;
6866
}
6967

68+
TRAMPOLINE_WRAPPED_OBJECT(expire_output, __tostring)
69+
TRAMPOLINE_WRAPPED_OBJECT(expire_output, filename)
70+
TRAMPOLINE_WRAPPED_OBJECT(expire_output, maxzoom)
71+
TRAMPOLINE_WRAPPED_OBJECT(expire_output, minzoom)
72+
TRAMPOLINE_WRAPPED_OBJECT(expire_output, schema)
73+
TRAMPOLINE_WRAPPED_OBJECT(expire_output, table)
74+
7075
} // anonymous namespace
7176

7277
int setup_flex_expire_output(lua_State *lua_state,
@@ -88,3 +93,77 @@ int setup_flex_expire_output(lua_State *lua_state,
8893

8994
return 1;
9095
}
96+
97+
/**
98+
* Define the osm2pgsql.ExpireOutput class/metatable.
99+
*/
100+
void lua_wrapper_expire_output::init(lua_State *lua_state)
101+
{
102+
lua_getglobal(lua_state, "osm2pgsql");
103+
if (luaL_newmetatable(lua_state, osm2pgsql_expire_output_name) != 1) {
104+
throw std::runtime_error{"Internal error: Lua newmetatable failed."};
105+
}
106+
lua_pushvalue(lua_state, -1); // Copy of new metatable
107+
108+
// Add metatable as osm2pgsql.ExpireOutput so we can access it from Lua
109+
lua_setfield(lua_state, -3, "ExpireOutput");
110+
111+
// Now add functions to metatable
112+
lua_pushvalue(lua_state, -1);
113+
lua_setfield(lua_state, -2, "__index");
114+
luaX_add_table_func(lua_state, "__tostring",
115+
lua_trampoline_expire_output___tostring);
116+
luaX_add_table_func(lua_state, "filename",
117+
lua_trampoline_expire_output_filename);
118+
luaX_add_table_func(lua_state, "maxzoom",
119+
lua_trampoline_expire_output_maxzoom);
120+
luaX_add_table_func(lua_state, "minzoom",
121+
lua_trampoline_expire_output_minzoom);
122+
luaX_add_table_func(lua_state, "schema",
123+
lua_trampoline_expire_output_schema);
124+
luaX_add_table_func(lua_state, "table", lua_trampoline_expire_output_table);
125+
126+
lua_pop(lua_state, 2);
127+
}
128+
129+
int lua_wrapper_expire_output::__tostring() const
130+
{
131+
std::string const str =
132+
fmt::format("osm2pgsql.ExpireOutput[minzoom={},maxzoom={},filename={},"
133+
"schema={},table={}]",
134+
self().minzoom(), self().maxzoom(), self().filename(),
135+
self().schema(), self().table());
136+
luaX_pushstring(lua_state(), str);
137+
138+
return 1;
139+
}
140+
141+
int lua_wrapper_expire_output::filename() const
142+
{
143+
luaX_pushstring(lua_state(), self().filename());
144+
return 1;
145+
}
146+
147+
int lua_wrapper_expire_output::maxzoom() const
148+
{
149+
lua_pushinteger(lua_state(), self().maxzoom());
150+
return 1;
151+
}
152+
153+
int lua_wrapper_expire_output::minzoom() const
154+
{
155+
lua_pushinteger(lua_state(), self().minzoom());
156+
return 1;
157+
}
158+
159+
int lua_wrapper_expire_output::schema() const
160+
{
161+
luaX_pushstring(lua_state(), self().schema());
162+
return 1;
163+
}
164+
165+
int lua_wrapper_expire_output::table() const
166+
{
167+
luaX_pushstring(lua_state(), self().table());
168+
return 1;
169+
}

src/flex-lua-expire-output.hpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
* For a full list of authors see the git log.
1111
*/
1212

13-
#include "expire-output.hpp"
13+
#include "flex-lua-wrapper.hpp"
1414

15+
#include <string>
1516
#include <vector>
1617

18+
class expire_output_t;
1719
struct lua_State;
1820

1921
static char const *const osm2pgsql_expire_output_name =
@@ -23,4 +25,24 @@ int setup_flex_expire_output(lua_State *lua_state,
2325
std::string const &default_schema,
2426
std::vector<expire_output_t> *expire_outputs);
2527

28+
class lua_wrapper_expire_output : public lua_wrapper_base<expire_output_t>
29+
{
30+
public:
31+
static void init(lua_State *lua_state);
32+
33+
lua_wrapper_expire_output(lua_State *lua_state,
34+
expire_output_t *expire_output)
35+
: lua_wrapper_base(lua_state, expire_output)
36+
{
37+
}
38+
39+
int __tostring() const;
40+
int filename() const;
41+
int maxzoom() const;
42+
int minzoom() const;
43+
int schema() const;
44+
int table() const;
45+
46+
}; // class lua_wrapper_expire_output
47+
2648
#endif // OSM2PGSQL_FLEX_LUA_EXPIRE_OUTPUT_HPP

src/flex-lua-table.cpp

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
#include "flex-lua-index.hpp"
1515
#include "flex-table.hpp"
1616
#include "lua-utils.hpp"
17+
#include "output-flex.hpp"
1718
#include "pgsql-capabilities.hpp"
19+
#include "util.hpp"
1820

1921
#include <lua.hpp>
2022

@@ -416,6 +418,12 @@ void setup_flex_table_indexes(lua_State *lua_state, flex_table_t *table,
416418
lua_pop(lua_state, 1); // "indexes"
417419
}
418420

421+
TRAMPOLINE_WRAPPED_OBJECT(table, __tostring)
422+
TRAMPOLINE_WRAPPED_OBJECT(table, cluster)
423+
TRAMPOLINE_WRAPPED_OBJECT(table, columns)
424+
TRAMPOLINE_WRAPPED_OBJECT(table, name)
425+
TRAMPOLINE_WRAPPED_OBJECT(table, schema)
426+
419427
} // anonymous namespace
420428

421429
int setup_flex_table(lua_State *lua_state, std::vector<flex_table_t> *tables,
@@ -442,3 +450,81 @@ int setup_flex_table(lua_State *lua_state, std::vector<flex_table_t> *tables,
442450

443451
return 1;
444452
}
453+
454+
/**
455+
* Define the osm2pgsql.Table class/metatable.
456+
*/
457+
void lua_wrapper_table::init(lua_State *lua_state)
458+
{
459+
lua_getglobal(lua_state, "osm2pgsql");
460+
if (luaL_newmetatable(lua_state, osm2pgsql_table_name) != 1) {
461+
throw std::runtime_error{"Internal error: Lua newmetatable failed."};
462+
}
463+
lua_pushvalue(lua_state, -1); // Copy of new metatable
464+
465+
// Add metatable as osm2pgsql.Table so we can access it from Lua
466+
lua_setfield(lua_state, -3, "Table");
467+
468+
// Now add functions to metatable
469+
lua_pushvalue(lua_state, -1);
470+
lua_setfield(lua_state, -2, "__index");
471+
luaX_add_table_func(lua_state, "__tostring",
472+
lua_trampoline_table___tostring);
473+
luaX_add_table_func(lua_state, "insert", lua_trampoline_table_insert);
474+
luaX_add_table_func(lua_state, "name", lua_trampoline_table_name);
475+
luaX_add_table_func(lua_state, "schema", lua_trampoline_table_schema);
476+
luaX_add_table_func(lua_state, "cluster", lua_trampoline_table_cluster);
477+
luaX_add_table_func(lua_state, "columns", lua_trampoline_table_columns);
478+
479+
lua_pop(lua_state, 2);
480+
}
481+
482+
int lua_wrapper_table::__tostring() const
483+
{
484+
std::string const str{fmt::format("osm2pgsql.Table[{}]", self().name())};
485+
luaX_pushstring(lua_state(), str);
486+
487+
return 1;
488+
}
489+
490+
int lua_wrapper_table::cluster() const
491+
{
492+
lua_pushboolean(lua_state(), self().cluster_by_geom());
493+
return 1;
494+
}
495+
496+
int lua_wrapper_table::columns() const
497+
{
498+
lua_createtable(lua_state(), (int)self().num_columns(), 0);
499+
500+
int n = 0;
501+
for (auto const &column : self().columns()) {
502+
lua_pushinteger(lua_state(), ++n);
503+
lua_newtable(lua_state());
504+
505+
luaX_add_table_str(lua_state(), "name", column.name().c_str());
506+
luaX_add_table_str(lua_state(), "type", column.type_name().c_str());
507+
luaX_add_table_str(lua_state(), "sql_type",
508+
column.sql_type_name().c_str());
509+
luaX_add_table_str(lua_state(), "sql_modifiers",
510+
column.sql_modifiers().c_str());
511+
luaX_add_table_bool(lua_state(), "not_null", column.not_null());
512+
luaX_add_table_bool(lua_state(), "create_only", column.create_only());
513+
514+
lua_rawset(lua_state(), -3);
515+
}
516+
517+
return 1;
518+
}
519+
520+
int lua_wrapper_table::name() const
521+
{
522+
luaX_pushstring(lua_state(), self().name());
523+
return 1;
524+
}
525+
526+
int lua_wrapper_table::schema() const
527+
{
528+
luaX_pushstring(lua_state(), self().schema());
529+
return 1;
530+
}

src/flex-lua-table.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
* For a full list of authors see the git log.
1111
*/
1212

13+
#include "flex-lua-wrapper.hpp"
14+
1315
#include <string>
1416
#include <vector>
1517

@@ -24,4 +26,22 @@ int setup_flex_table(lua_State *lua_state, std::vector<flex_table_t> *tables,
2426
std::string const &default_schema, bool updatable,
2527
bool append_mode);
2628

29+
class lua_wrapper_table : public lua_wrapper_base<flex_table_t>
30+
{
31+
public:
32+
static void init(lua_State *lua_state);
33+
34+
lua_wrapper_table(lua_State *lua_state, flex_table_t *table)
35+
: lua_wrapper_base(lua_state, table)
36+
{
37+
}
38+
39+
int __tostring() const;
40+
int cluster() const;
41+
int columns() const;
42+
int name() const;
43+
int schema() const;
44+
45+
}; // class lua_wrapper_table
46+
2747
#endif // OSM2PGSQL_FLEX_LUA_TABLE_HPP

src/flex-lua-wrapper.hpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#ifndef OSM2PGSQL_FLEX_LUA_WRAPPER_HPP
2+
#define OSM2PGSQL_FLEX_LUA_WRAPPER_HPP
3+
4+
/**
5+
* SPDX-License-Identifier: GPL-2.0-or-later
6+
*
7+
* This file is part of osm2pgsql (https://osm2pgsql.org/).
8+
*
9+
* Copyright (C) 2006-2025 by the osm2pgsql developer community.
10+
* For a full list of authors see the git log.
11+
*/
12+
13+
#include "output-flex.hpp"
14+
15+
#include <exception>
16+
17+
#define TRAMPOLINE_WRAPPED_OBJECT(obj_name, func_name) \
18+
int lua_trampoline_##obj_name##_##func_name(lua_State *lua_state) \
19+
{ \
20+
try { \
21+
auto *flex = \
22+
static_cast<output_flex_t *>(luaX_get_context(lua_state)); \
23+
auto &obj = flex->get_##obj_name##_from_param(); \
24+
return lua_wrapper_##obj_name{lua_state, &obj}.func_name(); \
25+
} catch (std::exception const &e) { \
26+
return luaL_error(lua_state, "Error in '" #func_name "': %s\n", \
27+
e.what()); \
28+
} catch (...) { \
29+
return luaL_error(lua_state, \
30+
"Unknown error in '" #func_name "'.\n"); \
31+
} \
32+
}
33+
34+
struct lua_State;
35+
36+
/**
37+
* Helper class for wrapping C++ classes in Lua "classes".
38+
*/
39+
template <typename WRAPPED>
40+
class lua_wrapper_base
41+
{
42+
public:
43+
lua_wrapper_base(lua_State *lua_state, WRAPPED *wrapped)
44+
: m_lua_state(lua_state), m_self(wrapped)
45+
{
46+
}
47+
48+
protected:
49+
lua_State *lua_state() const noexcept { return m_lua_state; }
50+
51+
WRAPPED const &self() const noexcept { return *m_self; }
52+
WRAPPED &self() noexcept { return *m_self; }
53+
54+
private:
55+
lua_State *m_lua_state;
56+
WRAPPED *m_self;
57+
58+
}; // class lua_wrapper_base;
59+
60+
#endif // OSM2PGSQL_FLEX_LUA_WRAPPER_HPP

0 commit comments

Comments
 (0)