diff options
Diffstat (limited to '')
-rw-r--r-- | src/linda.cpp | 176 |
1 files changed, 89 insertions, 87 deletions
diff --git a/src/linda.cpp b/src/linda.cpp index ad40eef..a7cf011 100644 --- a/src/linda.cpp +++ b/src/linda.cpp | |||
@@ -39,6 +39,72 @@ THE SOFTWARE. | |||
39 | #include <functional> | 39 | #include <functional> |
40 | 40 | ||
41 | // ################################################################################################# | 41 | // ################################################################################################# |
42 | |||
43 | static void check_key_types(lua_State* L_, int start_, int end_) | ||
44 | { | ||
45 | for (int _i{ start_ }; _i <= end_; ++_i) { | ||
46 | LuaType const t{ lua_type_as_enum(L_, _i) }; | ||
47 | switch (t) { | ||
48 | case LuaType::BOOLEAN: | ||
49 | case LuaType::NUMBER: | ||
50 | case LuaType::STRING: | ||
51 | continue; | ||
52 | |||
53 | case LuaType::LIGHTUSERDATA: | ||
54 | static constexpr std::array<std::reference_wrapper<UniqueKey const>, 3> kKeysToCheck{ kLindaBatched, kCancelError, kNilSentinel }; | ||
55 | for (UniqueKey const& key : kKeysToCheck) { | ||
56 | if (key.equals(L_, _i)) { | ||
57 | raise_luaL_error(L_, "argument #%d: can't use %s as a key", _i, key.debugName); | ||
58 | break; | ||
59 | } | ||
60 | } | ||
61 | break; | ||
62 | } | ||
63 | raise_luaL_error(L_, "argument #%d: invalid key type (not a boolean, string, number or light userdata)", _i); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | // ################################################################################################# | ||
68 | |||
69 | /* | ||
70 | * string = linda:__tostring( linda_ud) | ||
71 | * | ||
72 | * Return the stringification of a linda | ||
73 | * | ||
74 | * Useful for concatenation or debugging purposes | ||
75 | */ | ||
76 | |||
77 | template <bool OPT> | ||
78 | [[nodiscard]] static int LindaToString(lua_State* L_, int idx_) | ||
79 | { | ||
80 | Linda* const _linda{ ToLinda<OPT>(L_, idx_) }; | ||
81 | if (_linda != nullptr) { | ||
82 | char _text[128]; | ||
83 | int _len; | ||
84 | if (_linda->getName()) | ||
85 | _len = sprintf(_text, "Linda: %.*s", (int) sizeof(_text) - 8, _linda->getName()); | ||
86 | else | ||
87 | _len = sprintf(_text, "Linda: %p", _linda); | ||
88 | lua_pushlstring(L_, _text, _len); | ||
89 | return 1; | ||
90 | } | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | // ################################################################################################# | ||
95 | |||
96 | template <bool OPT> | ||
97 | [[nodiscard]] static inline Linda* ToLinda(lua_State* L_, int idx_) | ||
98 | { | ||
99 | Linda* const _linda{ static_cast<Linda*>(LindaFactory::Instance.toDeep(L_, idx_)) }; | ||
100 | if constexpr (!OPT) { | ||
101 | luaL_argcheck(L_, _linda != nullptr, idx_, "expecting a linda object"); // doesn't return if linda is nullptr | ||
102 | LUA_ASSERT(L_, _linda->U == universe_get(L_)); | ||
103 | } | ||
104 | return _linda; | ||
105 | } | ||
106 | |||
107 | // ################################################################################################# | ||
42 | // ################################################################################################# | 108 | // ################################################################################################# |
43 | 109 | ||
44 | // Any hashing will do that maps pointers to [0..Universe::nb_keepers[ consistently. | 110 | // Any hashing will do that maps pointers to [0..Universe::nb_keepers[ consistently. |
@@ -66,27 +132,6 @@ Linda::~Linda() | |||
66 | 132 | ||
67 | // ################################################################################################# | 133 | // ################################################################################################# |
68 | 134 | ||
69 | void Linda::setName(char const* name_, size_t len_) | ||
70 | { | ||
71 | // keep default | ||
72 | if (!name_ || len_ == 0) { | ||
73 | return; | ||
74 | } | ||
75 | ++len_; // don't forget terminating 0 | ||
76 | if (len_ < kEmbeddedNameLength) { | ||
77 | nameVariant.emplace<EmbeddedName>(); | ||
78 | char* const _name{ std::get<EmbeddedName>(nameVariant).data() }; | ||
79 | memcpy(_name, name_, len_); | ||
80 | } else { | ||
81 | AllocatedName& _name = std::get<AllocatedName>(nameVariant); | ||
82 | _name.name = static_cast<char*>(U->internalAllocator.alloc(len_)); | ||
83 | _name.len = len_; | ||
84 | memcpy(_name.name, name_, len_); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | // ################################################################################################# | ||
89 | |||
90 | char const* Linda::getName() const | 135 | char const* Linda::getName() const |
91 | { | 136 | { |
92 | if (std::holds_alternative<AllocatedName>(nameVariant)) { | 137 | if (std::holds_alternative<AllocatedName>(nameVariant)) { |
@@ -102,45 +147,6 @@ char const* Linda::getName() const | |||
102 | 147 | ||
103 | // ################################################################################################# | 148 | // ################################################################################################# |
104 | 149 | ||
105 | template <bool OPT> | ||
106 | [[nodiscard]] static inline Linda* ToLinda(lua_State* L_, int idx_) | ||
107 | { | ||
108 | Linda* const _linda{ static_cast<Linda*>(LindaFactory::Instance.toDeep(L_, idx_)) }; | ||
109 | if constexpr (!OPT) { | ||
110 | luaL_argcheck(L_, _linda != nullptr, idx_, "expecting a linda object"); // doesn't return if linda is nullptr | ||
111 | LUA_ASSERT(L_, _linda->U == universe_get(L_)); | ||
112 | } | ||
113 | return _linda; | ||
114 | } | ||
115 | |||
116 | // ################################################################################################# | ||
117 | |||
118 | static void check_key_types(lua_State* L_, int start_, int end_) | ||
119 | { | ||
120 | for (int _i{ start_ }; _i <= end_; ++_i) { | ||
121 | LuaType const t{ lua_type_as_enum(L_, _i) }; | ||
122 | switch (t) { | ||
123 | case LuaType::BOOLEAN: | ||
124 | case LuaType::NUMBER: | ||
125 | case LuaType::STRING: | ||
126 | continue; | ||
127 | |||
128 | case LuaType::LIGHTUSERDATA: | ||
129 | static constexpr std::array<std::reference_wrapper<UniqueKey const>, 3> kKeysToCheck{ kLindaBatched, kCancelError, kNilSentinel }; | ||
130 | for (UniqueKey const& key : kKeysToCheck) { | ||
131 | if (key.equals(L_, _i)) { | ||
132 | raise_luaL_error(L_, "argument #%d: can't use %s as a key", _i, key.debugName); | ||
133 | break; | ||
134 | } | ||
135 | } | ||
136 | break; | ||
137 | } | ||
138 | raise_luaL_error(L_, "argument #%d: invalid key type (not a boolean, string, number or light userdata)", _i); | ||
139 | } | ||
140 | } | ||
141 | |||
142 | // ################################################################################################# | ||
143 | |||
144 | // used to perform all linda operations that access keepers | 150 | // used to perform all linda operations that access keepers |
145 | int Linda::ProtectedCall(lua_State* L_, lua_CFunction f_) | 151 | int Linda::ProtectedCall(lua_State* L_, lua_CFunction f_) |
146 | { | 152 | { |
@@ -175,6 +181,29 @@ int Linda::ProtectedCall(lua_State* L_, lua_CFunction f_) | |||
175 | 181 | ||
176 | // ################################################################################################# | 182 | // ################################################################################################# |
177 | 183 | ||
184 | void Linda::setName(char const* name_, size_t len_) | ||
185 | { | ||
186 | // keep default | ||
187 | if (!name_ || len_ == 0) { | ||
188 | return; | ||
189 | } | ||
190 | ++len_; // don't forget terminating 0 | ||
191 | if (len_ < kEmbeddedNameLength) { | ||
192 | nameVariant.emplace<EmbeddedName>(); | ||
193 | char* const _name{ std::get<EmbeddedName>(nameVariant).data() }; | ||
194 | memcpy(_name, name_, len_); | ||
195 | } else { | ||
196 | AllocatedName& _name = std::get<AllocatedName>(nameVariant); | ||
197 | _name.name = static_cast<char*>(U->internalAllocator.alloc(len_)); | ||
198 | _name.len = len_; | ||
199 | memcpy(_name.name, name_, len_); | ||
200 | } | ||
201 | } | ||
202 | |||
203 | // ################################################################################################# | ||
204 | // ########################################## Lua API ############################################## | ||
205 | // ################################################################################################# | ||
206 | |||
178 | /* | 207 | /* |
179 | * bool= linda:linda_send([timeout_secs=nil,] key_num|str|bool|lightuserdata, ...) | 208 | * bool= linda:linda_send([timeout_secs=nil,] key_num|str|bool|lightuserdata, ...) |
180 | * | 209 | * |
@@ -649,33 +678,6 @@ LUAG_FUNC(linda_deep) | |||
649 | 678 | ||
650 | // ################################################################################################# | 679 | // ################################################################################################# |
651 | 680 | ||
652 | /* | ||
653 | * string = linda:__tostring( linda_ud) | ||
654 | * | ||
655 | * Return the stringification of a linda | ||
656 | * | ||
657 | * Useful for concatenation or debugging purposes | ||
658 | */ | ||
659 | |||
660 | template <bool OPT> | ||
661 | [[nodiscard]] static int LindaToString(lua_State* L_, int idx_) | ||
662 | { | ||
663 | Linda* const _linda{ ToLinda<OPT>(L_, idx_) }; | ||
664 | if (_linda != nullptr) { | ||
665 | char _text[128]; | ||
666 | int _len; | ||
667 | if (_linda->getName()) | ||
668 | _len = sprintf(_text, "Linda: %.*s", (int) sizeof(_text) - 8, _linda->getName()); | ||
669 | else | ||
670 | _len = sprintf(_text, "Linda: %p", _linda); | ||
671 | lua_pushlstring(L_, _text, _len); | ||
672 | return 1; | ||
673 | } | ||
674 | return 0; | ||
675 | } | ||
676 | |||
677 | // ################################################################################################# | ||
678 | |||
679 | LUAG_FUNC(linda_tostring) | 681 | LUAG_FUNC(linda_tostring) |
680 | { | 682 | { |
681 | return LindaToString<false>(L_, 1); | 683 | return LindaToString<false>(L_, 1); |