@@ -106,15 +106,15 @@ static ui_main_c* GetUIPtr(lua_State* L)
106106* unwound with normal C++ exception semantics.
107107*
108108* Example use site:
109- * SG_LUA_FUN_BEGIN (DoTheThing)
109+ * SG_LUA_CPP_FUN_BEGIN (DoTheThing)
110110* {
111111* ui_main_c* ui = GetUIPtr(L);
112112* auto foo = std::make_shared<Foo>();
113113* ui->LExpect(L, lua_gettop(L) >= 1), "Usage: DoTheThing(x)");
114114* ui->LExpect(L, lua_isstring(L, 1), "DoTheThing() argument 1: expected string, got %s", luaL_typename(L, 1));
115115* return 0;
116116* }
117- * SG_LUA_FUN_END ()
117+ * SG_LUA_CPP_FUN_END ()
118118*/
119119
120120#ifdef _WIN32
@@ -318,6 +318,35 @@ static int l_imgHandleImageSize(lua_State* L)
318318 return 2 ;
319319}
320320
321+ // ===============
322+ // Data validation
323+ // ===============
324+
325+ /*
326+ * ui_luaReader_c wraps the common validation of arguments or values from Lua in a class
327+ * that ensures a consistent assertion message and reduces the risk of mistakes in
328+ * parameter validation.
329+ *
330+ * As it has scoped RAII resources and uses ui->LExcept() it must only be used in functions
331+ * exposed to Lua through the SG_LUA_CPP_FUN_BEGIN/END scheme as that ensures proper cleanup
332+ * when unwinding.
333+ *
334+ * Example use site:
335+ * SG_LUA_CPP_FUN_BEGIN(DoTheThing)
336+ * {
337+ * ui_main_c* ui = GetUIPtr(L);
338+ * ui_luaReader_c reader(ui, L, "DoTheThing");
339+ * ui->LExpect(L, lua_gettop(L) >= 2), "Usage: DoTheThing(table, number)");
340+ * reader.ArgCheckTable(1); // short-hand to validate formal arguments to function
341+ * reader.ArgCheckNumber(2); // -''-
342+ * reader.ValCheckNumber(-1, "descriptive name"); // validates any value on the Lua stack, indicating what the value represents
343+ * // Do the thing
344+ * return 0;
345+ * }
346+ * SG_LUA_CPP_FUN_END()
347+ */
348+
349+
321350class ui_luaReader_c {
322351public:
323352 ui_luaReader_c (ui_main_c* ui, lua_State* L, std::string funName) : ui(ui), L(L), funName(funName) {}
0 commit comments