Pioneer
Loading...
Searching...
No Matches
LuaFlags.h
Go to the documentation of this file.
1// Copyright © 2008-2024 Pioneer Developers. See AUTHORS.txt for details
2// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
3
4#pragma once
5
6#include "enum_table.h"
7#include "utils.h"
8#include <lua.hpp>
9#include <stdexcept>
10#include <string>
11#include <vector>
12
13template <typename FlagType>
14struct LuaFlags {
15 std::vector<std::pair<const char *, FlagType>> LUT;
16 std::string typeName;
17 int lookupTableRef = LUA_NOREF;
18
19 // directly emplace from an initializer_list
20 LuaFlags(std::initializer_list<std::pair<const char *, FlagType>> init) :
21 LUT(init) {}
22
23 // Build the flags table from a c++ enum table
24 LuaFlags(const EnumItem enumEntries[])
25 {
26 for (size_t idx = 0; enumEntries[idx].name != nullptr; idx++) {
27 LUT.emplace_back(enumEntries[idx].name, static_cast<FlagType>(enumEntries[idx].value));
28 }
29 }
30
31 void Register(lua_State *l, std::string name)
32 {
33 if (lookupTableRef != LUA_NOREF)
34 throw std::runtime_error(std::string("Class ") + name + " is already registered.");
35
36 lua_newtable(l);
37 typeName = name;
38
39 for (auto &pair : LUT) {
40 lua_pushstring(l, pair.first);
41 lua_pushinteger(l, static_cast<unsigned int>(pair.second));
42 lua_settable(l, -3);
43 }
44
45 // luaL_ref pops the table off the stack.
46 lookupTableRef = luaL_ref(l, LUA_REGISTRYINDEX);
47 }
48
49 void Unregister(lua_State *l)
50 {
51 luaL_unref(l, LUA_REGISTRYINDEX, lookupTableRef);
52 lookupTableRef = LUA_NOREF;
53 }
54
55 // Parse a table of string flags or single flag into a bitwise-or'd bitflag value
56 FlagType LookupTable(lua_State *l, int index)
57 {
58 FlagType flagAccum = FlagType(0);
59 index = lua_absindex(l, index);
60 if (!lua_istable(l, index) || lookupTableRef == LUA_NOREF) return flagAccum;
61
62 lua_checkstack(l, 2);
63 lua_pushinteger(l, lookupTableRef);
64 lua_gettable(l, LUA_REGISTRYINDEX);
65
66 int table_idx = 1;
67 while (true) {
68 lua_pushinteger(l, table_idx++);
69 lua_gettable(l, index);
70
71 if (!lua_isstring(l, -1)) {
72 lua_pop(l, 1);
73 break;
74 }
75
76 flagAccum = static_cast<FlagType>(flagAccum | checkFlag(l, -1, -2));
77 }
78
79 lua_pop(l, 1);
80 return flagAccum;
81 }
82
83 // Parse a single string flag value into an enum value directly
84 FlagType LookupEnum(lua_State *l, int index)
85 {
86 FlagType flagAccum = FlagType(0);
87 index = lua_absindex(l, index);
88 if (!lua_isstring(l, index) || lookupTableRef == LUA_NOREF) return flagAccum;
89
90 lua_checkstack(l, 2);
91 lua_pushinteger(l, lookupTableRef);
92 lua_gettable(l, LUA_REGISTRYINDEX);
93
94 return checkFlag(l, index, -1);
95 }
96
97private:
98 inline FlagType checkFlag(lua_State *l, int index, int lookup_index)
99 {
100 lookup_index = lua_absindex(l, lookup_index);
101 lua_pushvalue(l, index);
102 lua_gettable(l, lookup_index);
103 if (lua_isnumber(l, -1)) {
104 // bitwise operations implicitly convert to int, so we must explicitly convert back to FlagType.
105 FlagType fl_ret = static_cast<FlagType>(lua_tointeger(l, -1));
106 lua_pop(l, 2); // clean up the stack!
107 return fl_ret;
108 } else {
109 lua_pop(l, 1);
110 std::string index_name = lua_tostring(l, index);
111 lua_pop(l, 2); // clean up the stack!
112 luaL_error(l, "Unknown %s %s", typeName.c_str(), index_name.c_str());
113 }
114 return FlagType(0);
115 }
116};
Definition: enum_table.h:10
const char * name
Definition: enum_table.h:11
Definition: LuaFlags.h:14
FlagType LookupEnum(lua_State *l, int index)
Definition: LuaFlags.h:84
void Unregister(lua_State *l)
Definition: LuaFlags.h:49
LuaFlags(const EnumItem enumEntries[])
Definition: LuaFlags.h:24
void Register(lua_State *l, std::string name)
Definition: LuaFlags.h:31
LuaFlags(std::initializer_list< std::pair< const char *, FlagType > > init)
Definition: LuaFlags.h:20
FlagType LookupTable(lua_State *l, int index)
Definition: LuaFlags.h:56
std::vector< std::pair< const char *, FlagType > > LUT
Definition: LuaFlags.h:15
std::string typeName
Definition: LuaFlags.h:16
int lookupTableRef
Definition: LuaFlags.h:17