stack_get_unqualified.hpp 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057
  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 = *pudata;
  817. return get_no_lua_nil_from(L, udata, index, tracking);
  818. }
  819. static T* get_no_lua_nil_from(lua_State* L, void* udata, int index, record&) {
  820. bool has_derived = derive<T>::value || weak_derive<T>::value;
  821. if (has_derived) {
  822. if (lua_getmetatable(L, index) == 1) {
  823. lua_getfield(L, -1, &detail::base_class_cast_key()[0]);
  824. if (type_of(L, -1) != type::lua_nil) {
  825. void* basecastdata = lua_touserdata(L, -1);
  826. detail::inheritance_cast_function ic = reinterpret_cast<detail::inheritance_cast_function>(basecastdata);
  827. // use the casting function to properly adjust the pointer for the desired T
  828. udata = ic(udata, usertype_traits<T>::qualified_name());
  829. }
  830. lua_pop(L, 2);
  831. }
  832. }
  833. if constexpr (std::is_function_v<T>) {
  834. T* func = reinterpret_cast<T*>(udata);
  835. return func;
  836. }
  837. else {
  838. T* obj = static_cast<T*>(udata);
  839. return obj;
  840. }
  841. }
  842. static T& get(lua_State* L, int index, record& tracking) {
  843. return *get_no_lua_nil(L, index, tracking);
  844. }
  845. };
  846. template <typename T>
  847. struct unqualified_getter<detail::as_pointer_tag<T>> {
  848. static T* get(lua_State* L, int index, record& tracking) {
  849. type t = type_of(L, index);
  850. if (t == type::lua_nil) {
  851. tracking.use(1);
  852. return nullptr;
  853. }
  854. unqualified_getter<detail::as_value_tag<T>> g{};
  855. return g.get_no_lua_nil(L, index, tracking);
  856. }
  857. };
  858. template <typename T>
  859. struct unqualified_getter<non_null<T*>> {
  860. static T* get(lua_State* L, int index, record& tracking) {
  861. unqualified_getter<detail::as_value_tag<T>> g{};
  862. return g.get_no_lua_nil(L, index, tracking);
  863. }
  864. };
  865. template <typename T>
  866. struct unqualified_getter<T&> {
  867. static T& get(lua_State* L, int index, record& tracking) {
  868. unqualified_getter<detail::as_value_tag<T>> g{};
  869. return g.get(L, index, tracking);
  870. }
  871. };
  872. template <typename T>
  873. struct unqualified_getter<std::reference_wrapper<T>> {
  874. static T& get(lua_State* L, int index, record& tracking) {
  875. unqualified_getter<T&> g{};
  876. return g.get(L, index, tracking);
  877. }
  878. };
  879. template <typename T>
  880. struct unqualified_getter<T*> {
  881. static T* get(lua_State* L, int index, record& tracking) {
  882. #if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE)
  883. if constexpr (std::is_function_v<T>) {
  884. return stack_detail::get_function_pointer<T>(L, index, tracking);
  885. }
  886. else {
  887. unqualified_getter<detail::as_pointer_tag<T>> g{};
  888. return g.get(L, index, tracking);
  889. }
  890. #else
  891. unqualified_getter<detail::as_pointer_tag<T>> g{};
  892. return g.get(L, index, tracking);
  893. #endif
  894. }
  895. };
  896. template <typename... Tn>
  897. struct unqualified_getter<std::tuple<Tn...>> {
  898. typedef std::tuple<decltype(stack::get<Tn>(nullptr, 0))...> R;
  899. template <typename... Args>
  900. static R apply(std::index_sequence<>, lua_State*, int, record&, Args&&... args) {
  901. // Fuck you too, VC++
  902. return R { std::forward<Args>(args)... };
  903. }
  904. template <std::size_t I, std::size_t... Ix, typename... Args>
  905. static R apply(std::index_sequence<I, Ix...>, lua_State* L, int index, record& tracking, Args&&... args) {
  906. // Fuck you too, VC++
  907. typedef std::tuple_element_t<I, std::tuple<Tn...>> T;
  908. return apply(std::index_sequence<Ix...>(), L, index, tracking, std::forward<Args>(args)..., stack::get<T>(L, index + tracking.used, tracking));
  909. }
  910. static R get(lua_State* L, int index, record& tracking) {
  911. return apply(std::make_index_sequence<sizeof...(Tn)>(), L, index, tracking);
  912. }
  913. };
  914. template <typename A, typename B>
  915. struct unqualified_getter<std::pair<A, B>> {
  916. static decltype(auto) get(lua_State* L, int index, record& tracking) {
  917. return std::pair<decltype(stack::get<A>(L, index)), decltype(stack::get<B>(L, index))> { stack::get<A>(L, index, tracking),
  918. stack::get<B>(L, index + tracking.used, tracking) };
  919. }
  920. };
  921. #if SOL_IS_ON(SOL_STD_VARIANT)
  922. template <typename... Tn>
  923. struct unqualified_getter<std::variant<Tn...>> {
  924. using V = std::variant<Tn...>;
  925. static V get_one(std::integral_constant<std::size_t, std::variant_size_v<V>>, lua_State* L, int index, record& tracking) {
  926. (void)L;
  927. (void)index;
  928. (void)tracking;
  929. if constexpr (std::variant_size_v<V> == 0) {
  930. return V();
  931. }
  932. else {
  933. // using T = std::variant_alternative_t<0, V>;
  934. std::abort();
  935. // return V(std::in_place_index<0>, stack::get<T>(L, index, tracking));
  936. }
  937. }
  938. template <std::size_t I>
  939. static V get_one(std::integral_constant<std::size_t, I>, lua_State* L, int index, record& tracking) {
  940. typedef std::variant_alternative_t<I, V> T;
  941. record temp_tracking = tracking;
  942. if (stack::check<T>(L, index, &no_panic, temp_tracking)) {
  943. tracking = temp_tracking;
  944. return V(std::in_place_index<I>, stack::get<T>(L, index));
  945. }
  946. return get_one(std::integral_constant<std::size_t, I + 1>(), L, index, tracking);
  947. }
  948. static V get(lua_State* L, int index, record& tracking) {
  949. return get_one(std::integral_constant<std::size_t, 0>(), L, index, tracking);
  950. }
  951. };
  952. #endif // variant
  953. }} // namespace sol::stack
  954. #endif // SOL_STACK_UNQUALIFIED_GET_HPP