1// Aseprite
2// Copyright (C) 2018 Igara Studio S.A.
3// Copyright (C) 2018 David Capello
4//
5// This program is distributed under the terms of
6// the End-User License Agreement for Aseprite.
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "app/script/luacpp.h"
13
14#include <cstdio>
15
16namespace app {
17namespace script {
18
19static const char mt_index_code[] =
20 "__generic_mt_index = function(t, k) "
21 " local mt = getmetatable(t) "
22 " local f = mt[k] "
23 " if f then return f end "
24 " f = mt.__getters[k] "
25 " if f then return f(t) end "
26 " if type(t) == 'table' then return rawget(t, k) end "
27 " error(debug.traceback()..': Field '..tostring(k)..' does not exist')"
28 "end "
29 "__generic_mt_newindex = function(t, k, v) "
30 " local mt = getmetatable(t) "
31 " local f = mt[k] "
32 " if f then return f end "
33 " f = mt.__setters[k] "
34 " if f then return f(t, v) end "
35 " if type(t) == 'table' then return rawset(t, k, v) end "
36 " error(debug.traceback()..': Cannot set field '..tostring(k))"
37 "end";
38
39void run_mt_index_code(lua_State* L)
40{
41 if (luaL_loadbuffer(L, mt_index_code, sizeof(mt_index_code)-1, "internal") ||
42 lua_pcall(L, 0, 0, 0)) {
43 // Error case
44 const char* s = lua_tostring(L, -1);
45 if (s)
46 std::puts(s);
47 }
48}
49
50void create_mt_getters_setters(lua_State* L,
51 const char* tname,
52 const Property* properties)
53{
54#ifdef _DEBUG
55 const int top = lua_gettop(L);
56#endif
57
58 bool withGetters = false;
59 bool withSetters = false;
60 for (auto p=properties; p->name; ++p) {
61 if (p->getter) withGetters = true;
62 if (p->setter) withSetters = true;
63 }
64 ASSERT(withGetters || withSetters);
65
66 luaL_getmetatable(L, tname);
67 if (withGetters) {
68 lua_newtable(L);
69 lua_pushvalue(L, -1);
70 lua_setfield(L, -3, "__getters");
71 for (auto p=properties; p->name; ++p) {
72 if (p->getter) {
73 lua_pushcclosure(L, p->getter, 0);
74 lua_setfield(L, -2, p->name);
75 }
76 }
77 lua_pop(L, 1);
78 }
79 if (withSetters) {
80 lua_newtable(L);
81 lua_pushvalue(L, -1);
82 lua_setfield(L, -3, "__setters");
83 for (auto p=properties; p->name; ++p) {
84 if (p->setter) {
85 lua_pushcclosure(L, p->setter, 0);
86 lua_setfield(L, -2, p->name);
87 }
88 }
89 lua_pop(L, 1);
90 }
91 lua_pop(L, 1);
92
93 ASSERT(lua_gettop(L) == top);
94}
95
96bool lua_is_key_true(lua_State* L, int tableIndex, const char* keyName)
97{
98 bool result = false;
99 int type = lua_getfield(L, tableIndex, keyName);
100 if (type != LUA_TNIL && lua_toboolean(L, -1))
101 result = true;
102 lua_pop(L, 1);
103 return result;
104}
105
106} // namespace script
107} // namespace app
108