The Battle for Wesnoth  1.19.6+dev
lua_attributes.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2024 - 2024
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
16 #include "scripting/lua_common.hpp"
17 #include "scripting/lua_kernel_base.hpp" // for luaW_get_attributes
18 #include "scripting/push_check.hpp"
19 #include <sstream>
20 
21 luaW_Registry::luaW_Registry(const std::initializer_list<std::string>& mt) : public_metatable(mt) {
23  public_metatable.pop_back();
24  lookup.emplace(private_metatable, std::ref(*this));
25 }
26 
29 }
30 
31 int luaW_Registry::get(lua_State* L) {
32  std::string_view str = lua_check<std::string_view>(L, 2);
33 
34  auto it = getters.find(std::string(str));
35  if(it != getters.end()) {
36  if(it->second(L, false)) {
37  return 1;
38  }
39  }
40  if(!public_metatable.empty()) {
41  auto method = public_metatable;
42  method.push_back(std::string(str));
43  if(luaW_getglobal(L, method)) {
44  return 1;
45  }
46  }
47 
48  std::ostringstream err;
49  err << "invalid property of " << private_metatable << ": " << str;
50  return luaL_argerror(L, 2, err.str().c_str());
51 }
52 
53 int luaW_Registry::set(lua_State* L) {
54  std::string_view str = lua_check<std::string_view>(L, 2);
55 
56  auto it = setters.find(std::string(str));
57  if(it != setters.end()) {
58  if(it->second(L, 3, false)) {
59  return 0;
60  }
61  }
62 
63  std::ostringstream err;
64  err << "invalid modifiable property of " << private_metatable << ": " << str;
65  return luaL_argerror(L, 2, err.str().c_str());
66 }
67 
68 int luaW_Registry::dir(lua_State *L) {
69  std::vector<std::string> keys;
70  if(lua_istable(L, 2)) {
71  keys = lua_check<std::vector<std::string>>(L, 2);
72  }
73  // Check for inactive keys
74  std::set<std::string> inactive;
75  for(const auto& [key, func] : validators) {
76  if(!func(L)) {
77  inactive.insert(key);
78  }
79  }
80  // Add any readable keys
81  for(const auto& [key, func] : getters) {
82  if(inactive.count(key) > 0) continue;
83  if(func(L, true)){
84  keys.push_back(key);
85  }
86  }
87  // Add any writable keys
88  for(const auto& [key, func] : setters) {
89  if(inactive.count(key) > 0) continue;
90  if(func(L, 0, true)){
91  keys.push_back(key);
92  }
93  }
94  // Add the metatable methods
95  if(!public_metatable.empty()) {
97  auto methods = luaW_get_attributes(L, -1);
98  keys.insert(keys.end(), methods.begin(), methods.end());
99  }
100  lua_push(L, keys);
101  return 1;
102 }
bool luaW_getglobal(lua_State *L, const std::vector< std::string > &path)
Pushes the value found by following the variadic names (char *), if the value is not nil.
Definition: lua_common.cpp:979
std::vector< std::string > luaW_get_attributes(lua_State *L, int idx)
This function does the actual work of grabbing all the attribute names.
logger & err()
Definition: log.cpp:307
void lua_push(lua_State *L, const T &val)
Definition: push_check.hpp:425
int dir(lua_State *L)
Implement __dir metamethod.
getters_list getters
A map of callbacks that read data from the object.
setters_list setters
A map of callbacks that write data to the object.
validators_list validators
A map of callbacks that check if a member is available.
static std::map< std::string_view, std::reference_wrapper< luaW_Registry > > lookup
std::string private_metatable
The internal metatable string for the object (from __metatable)
std::vector< std::string > public_metatable
Optional external metatable for the object (eg "wesnoth", "units") All entries of this table will be ...
luaW_Registry()=delete
int set(lua_State *L)
Implement __newindex metamethod.
int get(lua_State *L)
Implement __index metamethod.