stack_get_unqualified.hpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059
  1. // sol2
  2. // The MIT License (MIT)
  3. // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy of
  5. // this software and associated documentation files (the "Software"), to deal in
  6. // the Software without restriction, including without limitation the rights to
  7. // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  8. // the Software, and to permit persons to whom the Software is furnished to do so,
  9. // subject to the following conditions:
  10. // The above copyright notice and this permission notice shall be included in all
  11. // copies or substantial portions of the Software.
  12. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  14. // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  15. // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  16. // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  17. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  18. #ifndef SOL_STACK_UNQUALIFIED_GET_HPP
  19. #define SOL_STACK_UNQUALIFIED_GET_HPP
  20. #include <sol/version.hpp>
  21. #include <sol/stack_core.hpp>
  22. #include <sol/usertype_traits.hpp>
  23. #include <sol/inheritance.hpp>
  24. #include <sol/overload.hpp>
  25. #include <sol/error.hpp>
  26. #include <sol/unicode.hpp>
  27. #include <sol/abort.hpp>
  28. #include <memory>
  29. #include <functional>
  30. #include <utility>
  31. #include <cstdlib>
  32. #include <cmath>
  33. #include <string_view>
  34. #if SOL_IS_ON(SOL_STD_VARIANT)
  35. #include <variant>
  36. #endif // Apple clang screwed up
  37. namespace sol { namespace stack {
  38. namespace stack_detail {
  39. template <typename Ch>
  40. struct count_code_units_utf {
  41. std::size_t needed_size;
  42. count_code_units_utf() : needed_size(0) {
  43. }
  44. void operator()(const unicode::encoded_result<Ch> er) {
  45. needed_size += er.code_units_size;
  46. }
  47. };
  48. template <typename Ch, typename ErCh>
  49. struct copy_code_units_utf {
  50. Ch* target_;
  51. copy_code_units_utf(Ch* target) : target_(target) {
  52. }
  53. void operator()(const unicode::encoded_result<ErCh> er) {
  54. std::memcpy(target_, er.code_units.data(), er.code_units_size * sizeof(ErCh));
  55. target_ += er.code_units_size;
  56. }
  57. };
  58. template <typename Ch, typename F>
  59. inline void convert(const char* strb, const char* stre, F&& f) {
  60. char32_t cp = 0;
  61. for (const char* strtarget = strb; strtarget < stre;) {
  62. auto dr = unicode::utf8_to_code_point(strtarget, stre);
  63. if (dr.error != unicode::error_code::ok) {
  64. cp = unicode::unicode_detail::replacement;
  65. ++strtarget;
  66. }
  67. else {
  68. cp = dr.codepoint;
  69. strtarget = dr.next;
  70. }
  71. if constexpr (std::is_same_v<Ch, char32_t>) {
  72. auto er = unicode::code_point_to_utf32(cp);
  73. f(er);
  74. }
  75. else {
  76. auto er = unicode::code_point_to_utf16(cp);
  77. f(er);
  78. }
  79. }
  80. }
  81. template <typename BaseCh, typename S>
  82. inline S get_into(lua_State* L, int index, record& tracking) {
  83. using Ch = typename S::value_type;
  84. tracking.use(1);
  85. size_t len;
  86. auto utf8p = lua_tolstring(L, index, &len);
  87. if (len < 1)
  88. return S();
  89. const char* strb = utf8p;
  90. const char* stre = utf8p + len;
  91. stack_detail::count_code_units_utf<BaseCh> count_units;
  92. convert<BaseCh>(strb, stre, count_units);
  93. S r(count_units.needed_size, static_cast<Ch>(0));
  94. r.resize(count_units.needed_size);
  95. Ch* target = &r[0];
  96. stack_detail::copy_code_units_utf<Ch, BaseCh> copy_units(target);
  97. convert<BaseCh>(strb, stre, copy_units);
  98. return r;
  99. }
  100. } // namespace stack_detail
  101. template <typename T, typename>
  102. struct unqualified_getter {
  103. static decltype(auto) get(lua_State* L, int index, record& tracking) {
  104. if constexpr (std::is_same_v<T, bool>) {
  105. tracking.use(1);
  106. return lua_toboolean(L, index) != 0;
  107. }
  108. else if constexpr (std::is_enum_v<T>) {
  109. tracking.use(1);
  110. return static_cast<T>(lua_tointegerx(L, index, nullptr));
  111. }
  112. else if constexpr (std::is_integral_v<T> || std::is_same_v<T, lua_Integer>) {
  113. tracking.use(1);
  114. #if SOL_LUA_VERSION_I_ >= 503
  115. if (lua_isinteger(L, index) != 0) {
  116. return static_cast<T>(lua_tointeger(L, index));
  117. }
  118. #endif
  119. return static_cast<T>(llround(lua_tonumber(L, index)));
  120. }
  121. else if constexpr (std::is_floating_point_v<T> || std::is_same_v<T, lua_Number>) {
  122. tracking.use(1);
  123. return static_cast<T>(lua_tonumber(L, index));
  124. }
  125. else if constexpr (is_lua_reference_v<T>) {
  126. if constexpr (is_global_table_v<T>) {
  127. tracking.use(1);
  128. return T(L, global_tag);
  129. }
  130. else {
  131. tracking.use(1);
  132. return T(L, index);
  133. }
  134. }
  135. else if constexpr (is_unique_usertype_v<T>) {
  136. using actual = unique_usertype_actual_t<T>;
  137. tracking.use(1);
  138. void* memory = lua_touserdata(L, index);
  139. void* aligned_memory = detail::align_usertype_unique<actual>(memory);
  140. actual* typed_memory = static_cast<actual*>(aligned_memory);
  141. return *typed_memory;
  142. }
  143. else if constexpr (meta::is_optional_v<T>) {
  144. using ValueType = typename T::value_type;
  145. return unqualified_check_getter<ValueType>::template get_using<T>(L, index, &no_panic, tracking);
  146. }
  147. else if constexpr (std::is_same_v<T, luaL_Stream*>) {
  148. luaL_Stream* pstream = static_cast<luaL_Stream*>(lua_touserdata(L, index));
  149. return pstream;
  150. }
  151. else if constexpr (std::is_same_v<T, luaL_Stream>) {
  152. luaL_Stream* pstream = static_cast<luaL_Stream*>(lua_touserdata(L, index));
  153. return *pstream;
  154. }
  155. #if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE)
  156. else if constexpr (std::is_function_v<T> || (std::is_pointer_v<T> && std::is_function_v<std::remove_pointer_t<T>>)) {
  157. return stack_detail::get_function_pointer<std::remove_pointer_t<T>>(L, index, tracking);
  158. }
  159. #endif
  160. else {
  161. return stack_detail::unchecked_unqualified_get<detail::as_value_tag<T>>(L, index, tracking);
  162. }
  163. }
  164. };
  165. template <typename X, typename>
  166. struct qualified_getter {
  167. static decltype(auto) get(lua_State* L, int index, record& tracking) {
  168. using Tu = meta::unqualified_t<X>;
  169. static constexpr bool is_maybe_userdata_of_some_kind
  170. = !std::is_reference_v<
  171. X> && is_container_v<Tu> && std::is_default_constructible_v<Tu> && !is_lua_primitive_v<Tu> && !is_transparent_argument_v<Tu>;
  172. if constexpr (is_maybe_userdata_of_some_kind) {
  173. if (type_of(L, index) == type::userdata) {
  174. return static_cast<Tu>(stack_detail::unchecked_unqualified_get<Tu>(L, index, tracking));
  175. }
  176. else {
  177. return stack_detail::unchecked_unqualified_get<sol::nested<Tu>>(L, index, tracking);
  178. }
  179. }
  180. else if constexpr (!std::is_reference_v<X> && is_unique_usertype_v<Tu> && !is_actual_type_rebindable_for_v<Tu>) {
  181. using element = unique_usertype_element_t<Tu>;
  182. using actual = unique_usertype_actual_t<Tu>;
  183. tracking.use(1);
  184. void* memory = lua_touserdata(L, index);
  185. memory = detail::align_usertype_unique_destructor(memory);
  186. detail::unique_destructor& pdx = *static_cast<detail::unique_destructor*>(memory);
  187. if (&detail::usertype_unique_alloc_destroy<element, Tu> == pdx) {
  188. memory = detail::align_usertype_unique_tag<true, false>(memory);
  189. memory = detail::align_usertype_unique<actual, true, false>(memory);
  190. actual* mem = static_cast<actual*>(memory);
  191. return static_cast<actual>(*mem);
  192. }
  193. actual r {};
  194. if constexpr (!derive<element>::value) {
  195. // In debug mode we would rather abort you for this grave failure rather
  196. // than let you deref a null pointer and fuck everything over
  197. SOL_DEBUG_ABORT();
  198. return static_cast<actual>(std::move(r));
  199. }
  200. else {
  201. memory = detail::align_usertype_unique_tag<true, false>(memory);
  202. detail::unique_tag& ic = *reinterpret_cast<detail::unique_tag*>(memory);
  203. memory = detail::align_usertype_unique<actual, true, false>(memory);
  204. string_view ti = usertype_traits<element>::qualified_name();
  205. int cast_operation;
  206. if constexpr (is_actual_type_rebindable_for_v<Tu>) {
  207. using rebound_actual_type = unique_usertype_rebind_actual_t<Tu, void>;
  208. string_view rebind_ti = usertype_traits<rebound_actual_type>::qualified_name();
  209. cast_operation = ic(memory, &r, ti, rebind_ti);
  210. }
  211. else {
  212. string_view rebind_ti("");
  213. cast_operation = ic(memory, &r, ti, rebind_ti);
  214. }
  215. switch (cast_operation) {
  216. case 1: {
  217. // it's a perfect match,
  218. // alias memory directly
  219. actual* mem = static_cast<actual*>(memory);
  220. return static_cast<actual>(*mem);
  221. }
  222. case 2:
  223. // it's a base match, return the
  224. // aliased creation
  225. return static_cast<actual>(std::move(r));
  226. default:
  227. // uh oh..
  228. break;
  229. }
  230. SOL_DEBUG_ABORT();
  231. return static_cast<actual>(r);
  232. }
  233. }
  234. else {
  235. return stack_detail::unchecked_unqualified_get<Tu>(L, index, tracking);
  236. }
  237. }
  238. };
  239. template <typename T>
  240. struct unqualified_getter<as_table_t<T>> {
  241. using Tu = meta::unqualified_t<T>;
  242. template <typename V>
  243. static void push_back_at_end(std::true_type, types<V>, lua_State* L, T& cont, std::size_t) {
  244. cont.push_back(stack::get<V>(L, -lua_size<V>::value));
  245. }
  246. template <typename V>
  247. static void push_back_at_end(std::false_type, types<V> t, lua_State* L, T& cont, std::size_t idx) {
  248. insert_at_end(meta::has_insert<Tu>(), t, L, cont, idx);
  249. }
  250. template <typename V>
  251. static void insert_at_end(std::true_type, types<V>, lua_State* L, T& cont, std::size_t) {
  252. using std::cend;
  253. cont.insert(cend(cont), stack::get<V>(L, -lua_size<V>::value));
  254. }
  255. template <typename V>
  256. static void insert_at_end(std::false_type, types<V>, lua_State* L, T& cont, std::size_t idx) {
  257. cont[idx] = stack::get<V>(L, -lua_size<V>::value);
  258. }
  259. static bool max_size_check(std::false_type, T&, std::size_t) {
  260. return false;
  261. }
  262. static bool max_size_check(std::true_type, T& cont, std::size_t idx) {
  263. return idx >= cont.max_size();
  264. }
  265. static T get(lua_State* L, int relindex, record& tracking) {
  266. return get(meta::is_associative<Tu>(), L, relindex, tracking);
  267. }
  268. static T get(std::false_type, lua_State* L, int relindex, record& tracking) {
  269. typedef typename Tu::value_type V;
  270. return get(types<V>(), L, relindex, tracking);
  271. }
  272. template <typename V>
  273. static T get(types<V> t, lua_State* L, int relindex, record& tracking) {
  274. tracking.use(1);
  275. // the W4 flag is really great,
  276. // so great that it can tell my for loops (twice nested)
  277. // below never actually terminate
  278. // without hitting where the gotos have infested
  279. // so now I would get the error W4XXX unreachable
  280. // me that the return cont at the end of this function
  281. // which is fair until other compilers complain
  282. // that there isn't a return and that based on
  283. // SOME MAGICAL FORCE
  284. // control flow falls off the end of a non-void function
  285. // so it needs to be there for the compilers that are
  286. // too flimsy to analyze the basic blocks...
  287. // (I'm sure I should file a bug but those compilers are already
  288. // in the wild; it doesn't matter if I fix them,
  289. // someone else is still going to get some old-ass compiler
  290. // and then bother me about the unclean build for the 30th
  291. // time)
  292. // "Why not an IIFE?"
  293. // Because additional lambdas / functions which serve as
  294. // capture-all-and-then-invoke bloat binary sizes
  295. // by an actually detectable amount
  296. // (one user uses sol2 pretty heavily and 22 MB of binary size
  297. // was saved by reducing reliance on lambdas in templates)
  298. // This would really be solved by having break N;
  299. // be a real, proper thing...
  300. // but instead, we have to use labels and gotos
  301. // and earn the universal vitriol of the dogmatic
  302. // programming community
  303. // all in all: W4 is great!~
  304. int index = lua_absindex(L, relindex);
  305. T cont;
  306. std::size_t idx = 0;
  307. #if SOL_LUA_VERSION_I_ >= 503
  308. // This method is HIGHLY performant over regular table iteration
  309. // thanks to the Lua API changes in 5.3
  310. // Questionable in 5.4
  311. for (lua_Integer i = 0;; i += lua_size<V>::value) {
  312. if (max_size_check(meta::has_max_size<Tu>(), cont, idx)) {
  313. // see above comment
  314. goto done;
  315. }
  316. bool isnil = false;
  317. for (int vi = 0; vi < lua_size<V>::value; ++vi) {
  318. #if SOL_IS_ON(SOL_LUA_NIL_IN_TABLES) && SOL_LUA_VERSION_I_ >= 600
  319. #if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
  320. luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
  321. #endif // make sure stack doesn't overflow
  322. lua_pushinteger(L, static_cast<lua_Integer>(i + vi));
  323. if (lua_keyin(L, index) == 0) {
  324. // it's time to stop
  325. isnil = true;
  326. }
  327. else {
  328. // we have a key, have to get the value
  329. lua_geti(L, index, i + vi);
  330. }
  331. #else
  332. type vt = static_cast<type>(lua_geti(L, index, i + vi));
  333. isnil = vt == type::none || vt == type::lua_nil;
  334. #endif
  335. if (isnil) {
  336. if (i == 0) {
  337. break;
  338. }
  339. #if SOL_IS_ON(SOL_LUA_NIL_IN_TABLES) && SOL_LUA_VERSION_I_ >= 600
  340. lua_pop(L, vi);
  341. #else
  342. lua_pop(L, (vi + 1));
  343. #endif
  344. // see above comment
  345. goto done;
  346. }
  347. }
  348. if (isnil) {
  349. #if SOL_IS_ON(SOL_LUA_NIL_IN_TABLES) && SOL_LUA_VERSION_I_ >= 600
  350. #else
  351. lua_pop(L, lua_size<V>::value);
  352. #endif
  353. continue;
  354. }
  355. push_back_at_end(meta::has_push_back<Tu>(), t, L, cont, idx);
  356. ++idx;
  357. lua_pop(L, lua_size<V>::value);
  358. }
  359. #else
  360. // Zzzz slower but necessary thanks to the lower version API and missing functions qq
  361. for (lua_Integer i = 0;; i += lua_size<V>::value, lua_pop(L, lua_size<V>::value)) {
  362. if (idx >= cont.max_size()) {
  363. // see above comment
  364. goto done;
  365. }
  366. #if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
  367. luaL_checkstack(L, 2, detail::not_enough_stack_space_generic);
  368. #endif // make sure stack doesn't overflow
  369. bool isnil = false;
  370. for (int vi = 0; vi < lua_size<V>::value; ++vi) {
  371. lua_pushinteger(L, i);
  372. lua_gettable(L, index);
  373. type vt = type_of(L, -1);
  374. isnil = vt == type::lua_nil;
  375. if (isnil) {
  376. if (i == 0) {
  377. break;
  378. }
  379. lua_pop(L, (vi + 1));
  380. // see above comment
  381. goto done;
  382. }
  383. }
  384. if (isnil)
  385. continue;
  386. push_back_at_end(meta::has_push_back<Tu>(), t, L, cont, idx);
  387. ++idx;
  388. }
  389. #endif
  390. done:
  391. return cont;
  392. }
  393. static T get(std::true_type, lua_State* L, int index, record& tracking) {
  394. typedef typename Tu::value_type P;
  395. typedef typename P::first_type K;
  396. typedef typename P::second_type V;
  397. return get(types<K, V>(), L, index, tracking);
  398. }
  399. template <typename K, typename V>
  400. static T get(types<K, V>, lua_State* L, int relindex, record& tracking) {
  401. tracking.use(1);
  402. #if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
  403. luaL_checkstack(L, 3, detail::not_enough_stack_space_generic);
  404. #endif // make sure stack doesn't overflow
  405. T associative;
  406. int index = lua_absindex(L, relindex);
  407. lua_pushnil(L);
  408. while (lua_next(L, index) != 0) {
  409. decltype(auto) key = stack::check_get<K>(L, -2);
  410. if (!key) {
  411. lua_pop(L, 1);
  412. continue;
  413. }
  414. associative.emplace(std::forward<decltype(*key)>(*key), stack::get<V>(L, -1));
  415. lua_pop(L, 1);
  416. }
  417. return associative;
  418. }
  419. };
  420. template <typename T, typename Al>
  421. struct unqualified_getter<as_table_t<std::forward_list<T, Al>>> {
  422. typedef std::forward_list<T, Al> C;
  423. static C get(lua_State* L, int relindex, record& tracking) {
  424. return get(meta::has_key_value_pair<C>(), L, relindex, tracking);
  425. }
  426. static C get(std::true_type, lua_State* L, int index, record& tracking) {
  427. typedef typename T::value_type P;
  428. typedef typename P::first_type K;
  429. typedef typename P::second_type V;
  430. return get(types<K, V>(), L, index, tracking);
  431. }
  432. static C get(std::false_type, lua_State* L, int relindex, record& tracking) {
  433. typedef typename C::value_type V;
  434. return get(types<V>(), L, relindex, tracking);
  435. }
  436. template <typename V>
  437. static C get(types<V>, lua_State* L, int relindex, record& tracking) {
  438. tracking.use(1);
  439. #if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
  440. luaL_checkstack(L, 3, detail::not_enough_stack_space_generic);
  441. #endif // make sure stack doesn't overflow
  442. int index = lua_absindex(L, relindex);
  443. C cont;
  444. auto at = cont.cbefore_begin();
  445. std::size_t idx = 0;
  446. #if SOL_LUA_VERSION_I_ >= 503
  447. // This method is HIGHLY performant over regular table iteration thanks to the Lua API changes in 5.3
  448. for (lua_Integer i = 0;; i += lua_size<V>::value, lua_pop(L, lua_size<V>::value)) {
  449. if (idx >= cont.max_size()) {
  450. goto done;
  451. }
  452. bool isnil = false;
  453. for (int vi = 0; vi < lua_size<V>::value; ++vi) {
  454. type t = static_cast<type>(lua_geti(L, index, i + vi));
  455. isnil = t == type::lua_nil;
  456. if (isnil) {
  457. if (i == 0) {
  458. break;
  459. }
  460. lua_pop(L, (vi + 1));
  461. goto done;
  462. }
  463. }
  464. if (isnil)
  465. continue;
  466. at = cont.insert_after(at, stack::get<V>(L, -lua_size<V>::value));
  467. ++idx;
  468. }
  469. #else
  470. // Zzzz slower but necessary thanks to the lower version API and missing functions qq
  471. for (lua_Integer i = 0;; i += lua_size<V>::value, lua_pop(L, lua_size<V>::value)) {
  472. if (idx >= cont.max_size()) {
  473. goto done;
  474. }
  475. bool isnil = false;
  476. for (int vi = 0; vi < lua_size<V>::value; ++vi) {
  477. lua_pushinteger(L, i);
  478. lua_gettable(L, index);
  479. type t = type_of(L, -1);
  480. isnil = t == type::lua_nil;
  481. if (isnil) {
  482. if (i == 0) {
  483. break;
  484. }
  485. lua_pop(L, (vi + 1));
  486. goto done;
  487. }
  488. }
  489. if (isnil)
  490. continue;
  491. at = cont.insert_after(at, stack::get<V>(L, -lua_size<V>::value));
  492. ++idx;
  493. }
  494. #endif
  495. done:
  496. return cont;
  497. }
  498. template <typename K, typename V>
  499. static C get(types<K, V>, lua_State* L, int relindex, record& tracking) {
  500. tracking.use(1);
  501. #if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
  502. luaL_checkstack(L, 3, detail::not_enough_stack_space_generic);
  503. #endif // make sure stack doesn't overflow
  504. C associative;
  505. auto at = associative.cbefore_begin();
  506. int index = lua_absindex(L, relindex);
  507. lua_pushnil(L);
  508. while (lua_next(L, index) != 0) {
  509. decltype(auto) key = stack::check_get<K>(L, -2);
  510. if (!key) {
  511. lua_pop(L, 1);
  512. continue;
  513. }
  514. at = associative.emplace_after(at, std::forward<decltype(*key)>(*key), stack::get<V>(L, -1));
  515. lua_pop(L, 1);
  516. }
  517. return associative;
  518. }
  519. };
  520. template <typename T>
  521. struct unqualified_getter<nested<T>> {
  522. static T get(lua_State* L, int index, record& tracking) {
  523. using Tu = meta::unqualified_t<T>;
  524. if constexpr (is_container_v<Tu>) {
  525. if constexpr (meta::is_associative<Tu>::value) {
  526. typedef typename Tu::value_type P;
  527. typedef typename P::first_type K;
  528. typedef typename P::second_type V;
  529. unqualified_getter<as_table_t<T>> g {};
  530. return g.get(types<K, nested<V>>(), L, index, tracking);
  531. }
  532. else {
  533. typedef typename Tu::value_type V;
  534. unqualified_getter<as_table_t<T>> g {};
  535. return g.get(types<nested<V>>(), L, index, tracking);
  536. }
  537. }
  538. else {
  539. unqualified_getter<Tu> g {};
  540. return g.get(L, index, tracking);
  541. }
  542. }
  543. };
  544. template <typename T>
  545. struct unqualified_getter<as_container_t<T>> {
  546. static decltype(auto) get(lua_State* L, int index, record& tracking) {
  547. return stack::unqualified_get<T>(L, index, tracking);
  548. }
  549. };
  550. template <typename T>
  551. struct unqualified_getter<as_container_t<T>*> {
  552. static decltype(auto) get(lua_State* L, int index, record& tracking) {
  553. return stack::unqualified_get<T*>(L, index, tracking);
  554. }
  555. };
  556. template <typename T>
  557. struct unqualified_getter<exhaustive<T>> {
  558. static decltype(auto) get(lua_State* arg_L, int index, record& tracking) {
  559. return stack::get<T>(arg_L, index, tracking);
  560. }
  561. };
  562. template <typename T>
  563. struct unqualified_getter<non_exhaustive<T>> {
  564. static decltype(auto) get(lua_State* arg_L, int index, record& tracking) {
  565. return stack::get<T>(arg_L, index, tracking);
  566. }
  567. };
  568. template <>
  569. struct unqualified_getter<userdata_value> {
  570. static userdata_value get(lua_State* L, int index, record& tracking) {
  571. tracking.use(1);
  572. return userdata_value(lua_touserdata(L, index));
  573. }
  574. };
  575. template <>
  576. struct unqualified_getter<lightuserdata_value> {
  577. static lightuserdata_value get(lua_State* L, int index, record& tracking) {
  578. tracking.use(1);
  579. return lightuserdata_value(lua_touserdata(L, index));
  580. }
  581. };
  582. template <typename T>
  583. struct unqualified_getter<light<T>> {
  584. static light<T> get(lua_State* L, int index, record& tracking) {
  585. tracking.use(1);
  586. void* memory = lua_touserdata(L, index);
  587. return light<T>(static_cast<T*>(memory));
  588. }
  589. };
  590. template <typename T>
  591. struct unqualified_getter<user<T>> {
  592. static std::add_lvalue_reference_t<T> get(lua_State* L, int index, record& tracking) {
  593. tracking.use(1);
  594. void* memory = lua_touserdata(L, index);
  595. memory = detail::align_user<T>(memory);
  596. return *static_cast<std::remove_reference_t<T>*>(memory);
  597. }
  598. };
  599. template <typename T>
  600. struct unqualified_getter<user<T*>> {
  601. static T* get(lua_State* L, int index, record& tracking) {
  602. tracking.use(1);
  603. void* memory = lua_touserdata(L, index);
  604. memory = detail::align_user<T*>(memory);
  605. return static_cast<T*>(memory);
  606. }
  607. };
  608. template <>
  609. struct unqualified_getter<type> {
  610. static type get(lua_State* L, int index, record& tracking) {
  611. tracking.use(1);
  612. return static_cast<type>(lua_type(L, index));
  613. }
  614. };
  615. template <>
  616. struct unqualified_getter<std::string> {
  617. static std::string get(lua_State* L, int index, record& tracking) {
  618. tracking.use(1);
  619. std::size_t len;
  620. auto str = lua_tolstring(L, index, &len);
  621. return std::string(str, len);
  622. }
  623. };
  624. template <>
  625. struct unqualified_getter<const char*> {
  626. static const char* get(lua_State* L, int index, record& tracking) {
  627. tracking.use(1);
  628. size_t sz;
  629. return lua_tolstring(L, index, &sz);
  630. }
  631. };
  632. template <>
  633. struct unqualified_getter<char> {
  634. static char get(lua_State* L, int index, record& tracking) {
  635. tracking.use(1);
  636. size_t len;
  637. auto str = lua_tolstring(L, index, &len);
  638. return len > 0 ? str[0] : '\0';
  639. }
  640. };
  641. template <typename Traits>
  642. struct unqualified_getter<basic_string_view<char, Traits>> {
  643. static string_view get(lua_State* L, int index, record& tracking) {
  644. tracking.use(1);
  645. size_t sz;
  646. const char* str = lua_tolstring(L, index, &sz);
  647. return basic_string_view<char, Traits>(str, sz);
  648. }
  649. };
  650. template <typename Traits, typename Al>
  651. struct unqualified_getter<std::basic_string<wchar_t, Traits, Al>> {
  652. using S = std::basic_string<wchar_t, Traits, Al>;
  653. static S get(lua_State* L, int index, record& tracking) {
  654. using Ch = meta::conditional_t<sizeof(wchar_t) == 2, char16_t, char32_t>;
  655. return stack_detail::get_into<Ch, S>(L, index, tracking);
  656. }
  657. };
  658. template <typename Traits, typename Al>
  659. struct unqualified_getter<std::basic_string<char16_t, Traits, Al>> {
  660. static std::basic_string<char16_t, Traits, Al> get(lua_State* L, int index, record& tracking) {
  661. return stack_detail::get_into<char16_t, std::basic_string<char16_t, Traits, Al>>(L, index, tracking);
  662. }
  663. };
  664. template <typename Traits, typename Al>
  665. struct unqualified_getter<std::basic_string<char32_t, Traits, Al>> {
  666. static std::basic_string<char32_t, Traits, Al> get(lua_State* L, int index, record& tracking) {
  667. return stack_detail::get_into<char32_t, std::basic_string<char32_t, Traits, Al>>(L, index, tracking);
  668. }
  669. };
  670. template <>
  671. struct unqualified_getter<char16_t> {
  672. static char16_t get(lua_State* L, int index, record& tracking) {
  673. string_view utf8 = stack::get<string_view>(L, index, tracking);
  674. const char* strb = utf8.data();
  675. const char* stre = utf8.data() + utf8.size();
  676. char32_t cp = 0;
  677. auto dr = unicode::utf8_to_code_point(strb, stre);
  678. if (dr.error != unicode::error_code::ok) {
  679. cp = unicode::unicode_detail::replacement;
  680. }
  681. else {
  682. cp = dr.codepoint;
  683. }
  684. auto er = unicode::code_point_to_utf16(cp);
  685. return er.code_units[0];
  686. }
  687. };
  688. template <>
  689. struct unqualified_getter<char32_t> {
  690. static char32_t get(lua_State* L, int index, record& tracking) {
  691. string_view utf8 = stack::get<string_view>(L, index, tracking);
  692. const char* strb = utf8.data();
  693. const char* stre = utf8.data() + utf8.size();
  694. char32_t cp = 0;
  695. auto dr = unicode::utf8_to_code_point(strb, stre);
  696. if (dr.error != unicode::error_code::ok) {
  697. cp = unicode::unicode_detail::replacement;
  698. }
  699. else {
  700. cp = dr.codepoint;
  701. }
  702. auto er = unicode::code_point_to_utf32(cp);
  703. return er.code_units[0];
  704. }
  705. };
  706. template <>
  707. struct unqualified_getter<wchar_t> {
  708. static wchar_t get(lua_State* L, int index, record& tracking) {
  709. typedef meta::conditional_t<sizeof(wchar_t) == 2, char16_t, char32_t> Ch;
  710. unqualified_getter<Ch> g;
  711. (void)g;
  712. auto c = g.get(L, index, tracking);
  713. return static_cast<wchar_t>(c);
  714. }
  715. };
  716. template <>
  717. struct unqualified_getter<meta_function> {
  718. static meta_function get(lua_State* L, int index, record& tracking) {
  719. tracking.use(1);
  720. const char* name = unqualified_getter<const char*> {}.get(L, index, tracking);
  721. const auto& mfnames = meta_function_names();
  722. for (std::size_t i = 0; i < mfnames.size(); ++i)
  723. if (mfnames[i] == name)
  724. return static_cast<meta_function>(i);
  725. return meta_function::construct;
  726. }
  727. };
  728. template <>
  729. struct unqualified_getter<lua_nil_t> {
  730. static lua_nil_t get(lua_State*, int, record& tracking) {
  731. tracking.use(1);
  732. return lua_nil;
  733. }
  734. };
  735. template <>
  736. struct unqualified_getter<std::nullptr_t> {
  737. static std::nullptr_t get(lua_State*, int, record& tracking) {
  738. tracking.use(1);
  739. return nullptr;
  740. }
  741. };
  742. template <>
  743. struct unqualified_getter<nullopt_t> {
  744. static nullopt_t get(lua_State*, int, record& tracking) {
  745. tracking.use(1);
  746. return nullopt;
  747. }
  748. };
  749. template <>
  750. struct unqualified_getter<this_state> {
  751. static this_state get(lua_State* L, int, record& tracking) {
  752. tracking.use(0);
  753. return this_state(L);
  754. }
  755. };
  756. template <>
  757. struct unqualified_getter<this_main_state> {
  758. static this_main_state get(lua_State* L, int, record& tracking) {
  759. tracking.use(0);
  760. return this_main_state(main_thread(L, L));
  761. }
  762. };
  763. template <>
  764. struct unqualified_getter<lua_CFunction> {
  765. static lua_CFunction get(lua_State* L, int index, record& tracking) {
  766. tracking.use(1);
  767. return lua_tocfunction(L, index);
  768. }
  769. };
  770. template <>
  771. struct unqualified_getter<c_closure> {
  772. static c_closure get(lua_State* L, int index, record& tracking) {
  773. tracking.use(1);
  774. return c_closure(lua_tocfunction(L, index), -1);
  775. }
  776. };
  777. template <>
  778. struct unqualified_getter<error> {
  779. static error get(lua_State* L, int index, record& tracking) {
  780. tracking.use(1);
  781. size_t sz = 0;
  782. const char* err = lua_tolstring(L, index, &sz);
  783. if (err == nullptr) {
  784. return error(detail::direct_error, "");
  785. }
  786. return error(detail::direct_error, std::string(err, sz));
  787. }
  788. };
  789. template <>
  790. struct unqualified_getter<void*> {
  791. static void* get(lua_State* L, int index, record& tracking) {
  792. tracking.use(1);
  793. return lua_touserdata(L, index);
  794. }
  795. };
  796. template <>
  797. struct unqualified_getter<const void*> {
  798. static const void* get(lua_State* L, int index, record& tracking) {
  799. tracking.use(1);
  800. return lua_touserdata(L, index);
  801. }
  802. };
  803. template <typename T>
  804. struct unqualified_getter<detail::as_value_tag<T>> {
  805. static T* get_no_lua_nil(lua_State* L, int index, record& tracking) {
  806. void* memory = lua_touserdata(L, index);
  807. #if SOL_IS_ON(SOL_USE_INTEROP)
  808. auto ugr = stack_detail::interop_get<T>(L, index, memory, tracking);
  809. if (ugr.first) {
  810. return ugr.second;
  811. }
  812. #endif // interop extensibility
  813. tracking.use(1);
  814. void* rawdata = detail::align_usertype_pointer(memory);
  815. void** pudata = static_cast<void**>(rawdata);
  816. void* udata = nullptr;
  817. if (pudata != nullptr)
  818. udata = *pudata;
  819. return get_no_lua_nil_from(L, udata, index, tracking);
  820. }
  821. static T* get_no_lua_nil_from(lua_State* L, void* udata, int index, record&) {
  822. bool has_derived = derive<T>::value || weak_derive<T>::value;
  823. if (has_derived) {
  824. if (lua_getmetatable(L, index) == 1) {
  825. lua_getfield(L, -1, &detail::base_class_cast_key()[0]);
  826. if (type_of(L, -1) != type::lua_nil) {
  827. void* basecastdata = lua_touserdata(L, -1);
  828. detail::inheritance_cast_function ic = reinterpret_cast<detail::inheritance_cast_function>(basecastdata);
  829. // use the casting function to properly adjust the pointer for the desired T
  830. udata = ic(udata, usertype_traits<T>::qualified_name());
  831. }
  832. lua_pop(L, 2);
  833. }
  834. }
  835. if constexpr (std::is_function_v<T>) {
  836. T* func = reinterpret_cast<T*>(udata);
  837. return func;
  838. }
  839. else {
  840. T* obj = static_cast<T*>(udata);
  841. return obj;
  842. }
  843. }
  844. static T& get(lua_State* L, int index, record& tracking) {
  845. return *get_no_lua_nil(L, index, tracking);
  846. }
  847. };
  848. template <typename T>
  849. struct unqualified_getter<detail::as_pointer_tag<T>> {
  850. static T* get(lua_State* L, int index, record& tracking) {
  851. type t = type_of(L, index);
  852. if (t == type::lua_nil) {
  853. tracking.use(1);
  854. return nullptr;
  855. }
  856. unqualified_getter<detail::as_value_tag<T>> g{};
  857. return g.get_no_lua_nil(L, index, tracking);
  858. }
  859. };
  860. template <typename T>
  861. struct unqualified_getter<non_null<T*>> {
  862. static T* get(lua_State* L, int index, record& tracking) {
  863. unqualified_getter<detail::as_value_tag<T>> g{};
  864. return g.get_no_lua_nil(L, index, tracking);
  865. }
  866. };
  867. template <typename T>
  868. struct unqualified_getter<T&> {
  869. static T& get(lua_State* L, int index, record& tracking) {
  870. unqualified_getter<detail::as_value_tag<T>> g{};
  871. return g.get(L, index, tracking);
  872. }
  873. };
  874. template <typename T>
  875. struct unqualified_getter<std::reference_wrapper<T>> {
  876. static T& get(lua_State* L, int index, record& tracking) {
  877. unqualified_getter<T&> g{};
  878. return g.get(L, index, tracking);
  879. }
  880. };
  881. template <typename T>
  882. struct unqualified_getter<T*> {
  883. static T* get(lua_State* L, int index, record& tracking) {
  884. #if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE)
  885. if constexpr (std::is_function_v<T>) {
  886. return stack_detail::get_function_pointer<T>(L, index, tracking);
  887. }
  888. else {
  889. unqualified_getter<detail::as_pointer_tag<T>> g{};
  890. return g.get(L, index, tracking);
  891. }
  892. #else
  893. unqualified_getter<detail::as_pointer_tag<T>> g{};
  894. return g.get(L, index, tracking);
  895. #endif
  896. }
  897. };
  898. template <typename... Tn>
  899. struct unqualified_getter<std::tuple<Tn...>> {
  900. typedef std::tuple<decltype(stack::get<Tn>(nullptr, 0))...> R;
  901. template <typename... Args>
  902. static R apply(std::index_sequence<>, lua_State*, int, record&, Args&&... args) {
  903. // Fuck you too, VC++
  904. return R { std::forward<Args>(args)... };
  905. }
  906. template <std::size_t I, std::size_t... Ix, typename... Args>
  907. static R apply(std::index_sequence<I, Ix...>, lua_State* L, int index, record& tracking, Args&&... args) {
  908. // Fuck you too, VC++
  909. typedef std::tuple_element_t<I, std::tuple<Tn...>> T;
  910. return apply(std::index_sequence<Ix...>(), L, index, tracking, std::forward<Args>(args)..., stack::get<T>(L, index + tracking.used, tracking));
  911. }
  912. static R get(lua_State* L, int index, record& tracking) {
  913. return apply(std::make_index_sequence<sizeof...(Tn)>(), L, index, tracking);
  914. }
  915. };
  916. template <typename A, typename B>
  917. struct unqualified_getter<std::pair<A, B>> {
  918. static decltype(auto) get(lua_State* L, int index, record& tracking) {
  919. return std::pair<decltype(stack::get<A>(L, index)), decltype(stack::get<B>(L, index))> { stack::get<A>(L, index, tracking),
  920. stack::get<B>(L, index + tracking.used, tracking) };
  921. }
  922. };
  923. #if SOL_IS_ON(SOL_STD_VARIANT)
  924. template <typename... Tn>
  925. struct unqualified_getter<std::variant<Tn...>> {
  926. using V = std::variant<Tn...>;
  927. static V get_one(std::integral_constant<std::size_t, std::variant_size_v<V>>, lua_State* L, int index, record& tracking) {
  928. (void)L;
  929. (void)index;
  930. (void)tracking;
  931. if constexpr (std::variant_size_v<V> == 0) {
  932. return V();
  933. }
  934. else {
  935. // using T = std::variant_alternative_t<0, V>;
  936. std::abort();
  937. // return V(std::in_place_index<0>, stack::get<T>(L, index, tracking));
  938. }
  939. }
  940. template <std::size_t I>
  941. static V get_one(std::integral_constant<std::size_t, I>, lua_State* L, int index, record& tracking) {
  942. typedef std::variant_alternative_t<I, V> T;
  943. record temp_tracking = tracking;
  944. if (stack::check<T>(L, index, &no_panic, temp_tracking)) {
  945. tracking = temp_tracking;
  946. return V(std::in_place_index<I>, stack::get<T>(L, index));
  947. }
  948. return get_one(std::integral_constant<std::size_t, I + 1>(), L, index, tracking);
  949. }
  950. static V get(lua_State* L, int index, record& tracking) {
  951. return get_one(std::integral_constant<std::size_t, 0>(), L, index, tracking);
  952. }
  953. };
  954. #endif // variant
  955. }} // namespace sol::stack
  956. #endif // SOL_STACK_UNQUALIFIED_GET_HPP