stack_core.hpp 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446
  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_CORE_HPP
  19. #define SOL_STACK_CORE_HPP
  20. #include <sol/types.hpp>
  21. #include <sol/inheritance.hpp>
  22. #include <sol/error_handler.hpp>
  23. #include <sol/reference.hpp>
  24. #include <sol/stack_reference.hpp>
  25. #include <sol/tuple.hpp>
  26. #include <sol/traits.hpp>
  27. #include <sol/tie.hpp>
  28. #include <sol/stack_guard.hpp>
  29. #include <sol/demangle.hpp>
  30. #include <sol/forward_detail.hpp>
  31. #include <vector>
  32. #include <bitset>
  33. #include <forward_list>
  34. #include <string>
  35. #include <limits>
  36. #include <algorithm>
  37. #include <sstream>
  38. #include <optional>
  39. #include <type_traits>
  40. namespace sol {
  41. namespace detail {
  42. struct with_function_tag { };
  43. struct as_reference_tag { };
  44. template <typename T>
  45. struct as_pointer_tag { };
  46. template <typename T>
  47. struct as_value_tag { };
  48. template <typename T>
  49. struct as_unique_tag { };
  50. template <typename T>
  51. struct as_table_tag { };
  52. template <typename Tag>
  53. inline constexpr bool is_tagged_v
  54. = meta::is_specialization_of_v<Tag,
  55. detail::
  56. as_pointer_tag> || meta::is_specialization_of_v<Tag, as_value_tag> || meta::is_specialization_of_v<Tag, as_unique_tag> || meta::is_specialization_of_v<Tag, as_table_tag> || std::is_same_v<Tag, as_reference_tag> || std::is_same_v<Tag, with_function_tag>;
  57. using lua_reg_table = luaL_Reg[64];
  58. using unique_destructor = void (*)(void*);
  59. using unique_tag = detail::inheritance_unique_cast_function;
  60. inline void* alloc_newuserdata(lua_State* L, std::size_t bytesize) {
  61. #if SOL_LUA_VERSION_I_ >= 504
  62. return lua_newuserdatauv(L, bytesize, 1);
  63. #else
  64. return lua_newuserdata(L, bytesize);
  65. #endif
  66. }
  67. constexpr std::uintptr_t align(std::size_t alignment, std::uintptr_t ptr, std::size_t& space) {
  68. // this handles arbitrary alignments...
  69. // make this into a power-of-2-only?
  70. // actually can't: this is a C++14-compatible framework,
  71. // power of 2 alignment is C++17
  72. std::uintptr_t offby = static_cast<std::uintptr_t>(ptr % alignment);
  73. std::uintptr_t padding = (alignment - offby) % alignment;
  74. ptr += padding;
  75. space -= padding;
  76. return ptr;
  77. }
  78. inline void* align(std::size_t alignment, void* ptr, std::size_t& space) {
  79. return reinterpret_cast<void*>(align(alignment, reinterpret_cast<std::uintptr_t>(ptr), space));
  80. }
  81. constexpr std::uintptr_t align_one(std::size_t alignment, std::size_t size, std::uintptr_t ptr) {
  82. std::size_t space = (std::numeric_limits<std::size_t>::max)();
  83. return align(alignment, ptr, space) + size;
  84. }
  85. template <typename... Args>
  86. constexpr std::size_t aligned_space_for(std::uintptr_t ptr) {
  87. std::uintptr_t end = ptr;
  88. ((end = align_one(alignof(Args), sizeof(Args), end)), ...);
  89. return static_cast<std::size_t>(end - ptr);
  90. }
  91. template <typename... Args>
  92. constexpr std::size_t aligned_space_for() {
  93. static_assert(sizeof...(Args) > 0);
  94. constexpr std::size_t max_arg_alignment = (std::max)({ alignof(Args)... });
  95. if constexpr (max_arg_alignment <= alignof(std::max_align_t)) {
  96. // If all types are `good enough`, simply calculate alignment in case of the worst allocator
  97. std::size_t worst_required_size = 0;
  98. for (std::size_t ptr = 0; ptr < max_arg_alignment; ptr++) {
  99. worst_required_size = (std::max)(worst_required_size, aligned_space_for<Args...>(ptr));
  100. }
  101. return worst_required_size;
  102. }
  103. else {
  104. // For over-aligned types let's assume that every Arg in Args starts at the worst aligned address
  105. return (aligned_space_for<Args>(0x1) + ...);
  106. }
  107. }
  108. inline void* align_usertype_pointer(void* ptr) {
  109. using use_align = std::integral_constant<bool,
  110. #if SOL_IS_OFF(SOL_ALIGN_MEMORY)
  111. false
  112. #else
  113. (std::alignment_of<void*>::value > 1)
  114. #endif
  115. >;
  116. if (!use_align::value) {
  117. return ptr;
  118. }
  119. std::size_t space = (std::numeric_limits<std::size_t>::max)();
  120. return align(std::alignment_of<void*>::value, ptr, space);
  121. }
  122. template <bool pre_aligned = false, bool pre_shifted = false>
  123. void* align_usertype_unique_destructor(void* ptr) {
  124. using use_align = std::integral_constant<bool,
  125. #if SOL_IS_OFF(SOL_ALIGN_MEMORY)
  126. false
  127. #else
  128. (std::alignment_of<unique_destructor>::value > 1)
  129. #endif
  130. >;
  131. if (!pre_aligned) {
  132. ptr = align_usertype_pointer(ptr);
  133. }
  134. if (!pre_shifted) {
  135. ptr = static_cast<void*>(static_cast<char*>(ptr) + sizeof(void*));
  136. }
  137. if (!use_align::value) {
  138. return static_cast<void*>(static_cast<void**>(ptr) + 1);
  139. }
  140. std::size_t space = (std::numeric_limits<std::size_t>::max)();
  141. return align(std::alignment_of<unique_destructor>::value, ptr, space);
  142. }
  143. template <bool pre_aligned = false, bool pre_shifted = false>
  144. void* align_usertype_unique_tag(void* ptr) {
  145. using use_align = std::integral_constant<bool,
  146. #if SOL_IS_OFF(SOL_ALIGN_MEMORY)
  147. false
  148. #else
  149. (std::alignment_of<unique_tag>::value > 1)
  150. #endif
  151. >;
  152. if (!pre_aligned) {
  153. ptr = align_usertype_unique_destructor(ptr);
  154. }
  155. if (!pre_shifted) {
  156. ptr = static_cast<void*>(static_cast<char*>(ptr) + sizeof(unique_destructor));
  157. }
  158. if (!use_align::value) {
  159. return ptr;
  160. }
  161. std::size_t space = (std::numeric_limits<std::size_t>::max)();
  162. return align(std::alignment_of<unique_tag>::value, ptr, space);
  163. }
  164. template <typename T, bool pre_aligned = false, bool pre_shifted = false>
  165. void* align_usertype_unique(void* ptr) {
  166. typedef std::integral_constant<bool,
  167. #if SOL_IS_OFF(SOL_ALIGN_MEMORY)
  168. false
  169. #else
  170. (std::alignment_of_v<T> > 1)
  171. #endif
  172. >
  173. use_align;
  174. if (!pre_aligned) {
  175. ptr = align_usertype_unique_tag(ptr);
  176. }
  177. if (!pre_shifted) {
  178. ptr = static_cast<void*>(static_cast<char*>(ptr) + sizeof(unique_tag));
  179. }
  180. if (!use_align::value) {
  181. return ptr;
  182. }
  183. std::size_t space = (std::numeric_limits<std::size_t>::max)();
  184. return align(std::alignment_of_v<T>, ptr, space);
  185. }
  186. template <typename T>
  187. void* align_user(void* ptr) {
  188. typedef std::integral_constant<bool,
  189. #if SOL_IS_OFF(SOL_ALIGN_MEMORY)
  190. false
  191. #else
  192. (std::alignment_of_v<T> > 1)
  193. #endif
  194. >
  195. use_align;
  196. if (!use_align::value) {
  197. return ptr;
  198. }
  199. std::size_t space = (std::numeric_limits<std::size_t>::max)();
  200. return align(std::alignment_of_v<T>, ptr, space);
  201. }
  202. template <typename T>
  203. T** usertype_allocate_pointer(lua_State* L) {
  204. typedef std::integral_constant<bool,
  205. #if SOL_IS_OFF(SOL_ALIGN_MEMORY)
  206. false
  207. #else
  208. (std::alignment_of<T*>::value > 1)
  209. #endif
  210. >
  211. use_align;
  212. if (!use_align::value) {
  213. T** pointerpointer = static_cast<T**>(alloc_newuserdata(L, sizeof(T*)));
  214. return pointerpointer;
  215. }
  216. constexpr std::size_t initial_size = aligned_space_for<T*>();
  217. std::size_t allocated_size = initial_size;
  218. void* unadjusted = alloc_newuserdata(L, initial_size);
  219. void* adjusted = align(std::alignment_of<T*>::value, unadjusted, allocated_size);
  220. if (adjusted == nullptr) {
  221. // trash allocator can burn in hell
  222. lua_pop(L, 1);
  223. // luaL_error(L, "if you are the one that wrote this allocator you should feel bad for doing a
  224. // worse job than malloc/realloc and should go read some books, yeah?");
  225. luaL_error(L, "cannot properly align memory for '%s'", detail::demangle<T*>().data());
  226. }
  227. return static_cast<T**>(adjusted);
  228. }
  229. inline bool attempt_alloc(lua_State* L, std::size_t ptr_align, std::size_t ptr_size, std::size_t value_align,
  230. std::size_t allocated_size, void*& pointer_adjusted, void*& data_adjusted) {
  231. void* adjusted = alloc_newuserdata(L, allocated_size);
  232. pointer_adjusted = align(ptr_align, adjusted, allocated_size);
  233. if (pointer_adjusted == nullptr) {
  234. lua_pop(L, 1);
  235. return false;
  236. }
  237. // subtract size of what we're going to allocate there
  238. allocated_size -= ptr_size;
  239. adjusted = static_cast<void*>(static_cast<char*>(pointer_adjusted) + ptr_size);
  240. data_adjusted = align(value_align, adjusted, allocated_size);
  241. if (data_adjusted == nullptr) {
  242. lua_pop(L, 1);
  243. return false;
  244. }
  245. return true;
  246. }
  247. inline bool attempt_alloc_unique(lua_State* L, std::size_t ptr_align, std::size_t ptr_size, std::size_t real_align,
  248. std::size_t allocated_size, void*& pointer_adjusted, void*& dx_adjusted, void*& id_adjusted, void*& data_adjusted) {
  249. void* adjusted = alloc_newuserdata(L, allocated_size);
  250. pointer_adjusted = align(ptr_align, adjusted, allocated_size);
  251. if (pointer_adjusted == nullptr) {
  252. lua_pop(L, 1);
  253. return false;
  254. }
  255. allocated_size -= ptr_size;
  256. adjusted = static_cast<void*>(static_cast<char*>(pointer_adjusted) + ptr_size);
  257. dx_adjusted = align(std::alignment_of_v<unique_destructor>, adjusted, allocated_size);
  258. if (dx_adjusted == nullptr) {
  259. lua_pop(L, 1);
  260. return false;
  261. }
  262. allocated_size -= sizeof(unique_destructor);
  263. adjusted = static_cast<void*>(static_cast<char*>(dx_adjusted) + sizeof(unique_destructor));
  264. id_adjusted = align(std::alignment_of_v<unique_tag>, adjusted, allocated_size);
  265. if (id_adjusted == nullptr) {
  266. lua_pop(L, 1);
  267. return false;
  268. }
  269. allocated_size -= sizeof(unique_tag);
  270. adjusted = static_cast<void*>(static_cast<char*>(id_adjusted) + sizeof(unique_tag));
  271. data_adjusted = align(real_align, adjusted, allocated_size);
  272. if (data_adjusted == nullptr) {
  273. lua_pop(L, 1);
  274. return false;
  275. }
  276. return true;
  277. }
  278. template <typename T>
  279. T* usertype_allocate(lua_State* L) {
  280. typedef std::integral_constant<bool,
  281. #if SOL_IS_OFF(SOL_ALIGN_MEMORY)
  282. false
  283. #else
  284. (std::alignment_of<T*>::value > 1 || std::alignment_of_v<T> > 1)
  285. #endif
  286. >
  287. use_align;
  288. if (!use_align::value) {
  289. T** pointerpointer = static_cast<T**>(alloc_newuserdata(L, sizeof(T*) + sizeof(T)));
  290. T*& pointerreference = *pointerpointer;
  291. T* allocationtarget = reinterpret_cast<T*>(pointerpointer + 1);
  292. pointerreference = allocationtarget;
  293. return allocationtarget;
  294. }
  295. constexpr std::size_t initial_size = aligned_space_for<T*, T>();
  296. void* pointer_adjusted;
  297. void* data_adjusted;
  298. bool result
  299. = attempt_alloc(L, std::alignment_of_v<T*>, sizeof(T*), std::alignment_of_v<T>, initial_size, pointer_adjusted, data_adjusted);
  300. if (!result) {
  301. if (pointer_adjusted == nullptr) {
  302. luaL_error(L, "aligned allocation of userdata block (pointer section) for '%s' failed", detail::demangle<T>().c_str());
  303. }
  304. else {
  305. luaL_error(L, "aligned allocation of userdata block (data section) for '%s' failed", detail::demangle<T>().c_str());
  306. }
  307. return nullptr;
  308. }
  309. T** pointerpointer = reinterpret_cast<T**>(pointer_adjusted);
  310. T*& pointerreference = *pointerpointer;
  311. T* allocationtarget = reinterpret_cast<T*>(data_adjusted);
  312. pointerreference = allocationtarget;
  313. return allocationtarget;
  314. }
  315. template <typename T, typename Real>
  316. Real* usertype_unique_allocate(lua_State* L, T**& pref, unique_destructor*& dx, unique_tag*& id) {
  317. typedef std::integral_constant<bool,
  318. #if SOL_IS_OFF(SOL_ALIGN_MEMORY)
  319. false
  320. #else
  321. (std::alignment_of<T*>::value > 1 || std::alignment_of<unique_tag>::value > 1 || std::alignment_of<unique_destructor>::value > 1
  322. || std::alignment_of<Real>::value > 1)
  323. #endif
  324. >
  325. use_align;
  326. if (!use_align::value) {
  327. pref = static_cast<T**>(alloc_newuserdata(L, sizeof(T*) + sizeof(detail::unique_destructor) + sizeof(unique_tag) + sizeof(Real)));
  328. dx = static_cast<detail::unique_destructor*>(static_cast<void*>(pref + 1));
  329. id = static_cast<unique_tag*>(static_cast<void*>(dx + 1));
  330. Real* mem = static_cast<Real*>(static_cast<void*>(id + 1));
  331. return mem;
  332. }
  333. constexpr std::size_t initial_size = aligned_space_for<T*, unique_destructor, unique_tag, Real>();
  334. void* pointer_adjusted = nullptr;
  335. void* dx_adjusted = nullptr;
  336. void* id_adjusted = nullptr;
  337. void* data_adjusted = nullptr;
  338. bool result = attempt_alloc_unique(L,
  339. std::alignment_of_v<T*>,
  340. sizeof(T*),
  341. std::alignment_of_v<Real>,
  342. initial_size,
  343. pointer_adjusted,
  344. dx_adjusted,
  345. id_adjusted,
  346. data_adjusted);
  347. if (!result) {
  348. if (pointer_adjusted == nullptr) {
  349. luaL_error(L, "aligned allocation of userdata block (pointer section) for '%s' failed", detail::demangle<T>().c_str());
  350. }
  351. else if (dx_adjusted == nullptr) {
  352. luaL_error(L, "aligned allocation of userdata block (deleter section) for '%s' failed", detail::demangle<T>().c_str());
  353. }
  354. else {
  355. luaL_error(L, "aligned allocation of userdata block (data section) for '%s' failed", detail::demangle<T>().c_str());
  356. }
  357. return nullptr;
  358. }
  359. pref = static_cast<T**>(pointer_adjusted);
  360. dx = static_cast<detail::unique_destructor*>(dx_adjusted);
  361. id = static_cast<unique_tag*>(id_adjusted);
  362. Real* mem = static_cast<Real*>(data_adjusted);
  363. return mem;
  364. }
  365. template <typename T>
  366. T* user_allocate(lua_State* L) {
  367. typedef std::integral_constant<bool,
  368. #if SOL_IS_OFF(SOL_ALIGN_MEMORY)
  369. false
  370. #else
  371. (std::alignment_of_v<T> > 1)
  372. #endif
  373. >
  374. use_align;
  375. if (!use_align::value) {
  376. T* pointer = static_cast<T*>(alloc_newuserdata(L, sizeof(T)));
  377. return pointer;
  378. }
  379. constexpr std::size_t initial_size = aligned_space_for<T>();
  380. std::size_t allocated_size = initial_size;
  381. void* unadjusted = alloc_newuserdata(L, allocated_size);
  382. void* adjusted = align(std::alignment_of_v<T>, unadjusted, allocated_size);
  383. if (adjusted == nullptr) {
  384. lua_pop(L, 1);
  385. luaL_error(L, "cannot properly align memory for '%s'", detail::demangle<T>().data());
  386. }
  387. return static_cast<T*>(adjusted);
  388. }
  389. template <typename T>
  390. int usertype_alloc_destroy(lua_State* L) noexcept {
  391. void* memory = lua_touserdata(L, 1);
  392. memory = align_usertype_pointer(memory);
  393. T** pdata = static_cast<T**>(memory);
  394. T* data = *pdata;
  395. std::allocator<T> alloc {};
  396. std::allocator_traits<std::allocator<T>>::destroy(alloc, data);
  397. return 0;
  398. }
  399. template <typename T>
  400. int unique_destroy(lua_State* L) noexcept {
  401. void* memory = lua_touserdata(L, 1);
  402. memory = align_usertype_unique_destructor(memory);
  403. unique_destructor& dx = *static_cast<unique_destructor*>(memory);
  404. memory = align_usertype_unique_tag<true>(memory);
  405. (dx)(memory);
  406. return 0;
  407. }
  408. template <typename T>
  409. int user_alloc_destroy(lua_State* L) noexcept {
  410. void* memory = lua_touserdata(L, 1);
  411. void* aligned_memory = align_user<T>(memory);
  412. T* typed_memory = static_cast<T*>(aligned_memory);
  413. std::allocator<T> alloc;
  414. std::allocator_traits<std::allocator<T>>::destroy(alloc, typed_memory);
  415. return 0;
  416. }
  417. template <typename T, typename Real>
  418. void usertype_unique_alloc_destroy(void* memory) {
  419. void* aligned_memory = align_usertype_unique<Real, true>(memory);
  420. Real* typed_memory = static_cast<Real*>(aligned_memory);
  421. std::allocator<Real> alloc;
  422. std::allocator_traits<std::allocator<Real>>::destroy(alloc, typed_memory);
  423. }
  424. template <typename T>
  425. int cannot_destroy(lua_State* L) {
  426. return luaL_error(L,
  427. "cannot call the destructor for '%s': it is either hidden (protected/private) or removed with '= "
  428. "delete' and thusly this type is being destroyed without properly destroying, invoking undefined "
  429. "behavior: please bind a usertype and specify a custom destructor to define the behavior properly",
  430. detail::demangle<T>().data());
  431. }
  432. template <typename T>
  433. void reserve(T&, std::size_t) {
  434. }
  435. template <typename T, typename Al>
  436. void reserve(std::vector<T, Al>& vec, std::size_t hint) {
  437. vec.reserve(hint);
  438. }
  439. template <typename T, typename Tr, typename Al>
  440. void reserve(std::basic_string<T, Tr, Al>& str, std::size_t hint) {
  441. str.reserve(hint);
  442. }
  443. inline bool property_always_true(meta_function) {
  444. return true;
  445. }
  446. struct properties_enrollment_allowed {
  447. int& times_through;
  448. std::bitset<64>& properties;
  449. automagic_enrollments& enrollments;
  450. properties_enrollment_allowed(int& times_through_, std::bitset<64>& properties_, automagic_enrollments& enrollments_)
  451. : times_through(times_through_), properties(properties_), enrollments(enrollments_) {
  452. }
  453. bool operator()(meta_function mf) const {
  454. bool p = properties[static_cast<std::size_t>(mf)];
  455. if (times_through > 0) {
  456. return p;
  457. }
  458. switch (mf) {
  459. case meta_function::length:
  460. return enrollments.length_operator && !p;
  461. case meta_function::pairs:
  462. return enrollments.pairs_operator && !p;
  463. case meta_function::call:
  464. return enrollments.call_operator && !p;
  465. case meta_function::less_than:
  466. return enrollments.less_than_operator && !p;
  467. case meta_function::less_than_or_equal_to:
  468. return enrollments.less_than_or_equal_to_operator && !p;
  469. case meta_function::equal_to:
  470. return enrollments.equal_to_operator && !p;
  471. default:
  472. break;
  473. }
  474. return !p;
  475. }
  476. };
  477. struct indexed_insert {
  478. lua_reg_table& registration_table;
  479. int& index;
  480. indexed_insert(lua_reg_table& registration_table_, int& index_ref_) : registration_table(registration_table_), index(index_ref_) {
  481. }
  482. void operator()(meta_function meta_function_name_, lua_CFunction c_function_) {
  483. registration_table[index] = luaL_Reg { to_string(meta_function_name_).c_str(), c_function_ };
  484. ++index;
  485. }
  486. };
  487. } // namespace detail
  488. namespace stack {
  489. template <typename T, bool global = false, bool raw = false, typename = void>
  490. struct field_getter;
  491. template <typename T, typename P, bool global = false, bool raw = false, typename = void>
  492. struct probe_field_getter;
  493. template <typename T, bool global = false, bool raw = false, typename = void>
  494. struct field_setter;
  495. template <typename T, typename = void>
  496. struct unqualified_getter;
  497. template <typename T, typename = void>
  498. struct qualified_getter;
  499. template <typename T, typename = void>
  500. struct qualified_interop_getter;
  501. template <typename T, typename = void>
  502. struct unqualified_interop_getter;
  503. template <typename T, typename = void>
  504. struct popper;
  505. template <typename T, typename = void>
  506. struct unqualified_pusher;
  507. template <typename T, type t, typename = void>
  508. struct unqualified_checker;
  509. template <typename T, type t, typename = void>
  510. struct qualified_checker;
  511. template <typename T, typename = void>
  512. struct unqualified_check_getter;
  513. template <typename T, typename = void>
  514. struct qualified_check_getter;
  515. struct probe {
  516. bool success;
  517. int levels;
  518. probe(bool s, int l) : success(s), levels(l) {
  519. }
  520. operator bool() const {
  521. return success;
  522. };
  523. };
  524. struct record {
  525. int last;
  526. int used;
  527. record() noexcept : last(), used() {
  528. }
  529. void use(int count) noexcept {
  530. last = count;
  531. used += count;
  532. }
  533. };
  534. namespace stack_detail {
  535. template <typename Function>
  536. Function* get_function_pointer(lua_State*, int, record&) noexcept;
  537. template <typename Function, typename Handler>
  538. bool check_function_pointer(lua_State* L, int index, Handler&& handler, record& tracking) noexcept;
  539. } // namespace stack_detail
  540. } // namespace stack
  541. namespace meta { namespace meta_detail {
  542. template <typename T>
  543. using adl_sol_lua_get_test_t = decltype(sol_lua_get(types<T>(), static_cast<lua_State*>(nullptr), -1, std::declval<stack::record&>()));
  544. template <typename T>
  545. using adl_sol_lua_interop_get_test_t
  546. = decltype(sol_lua_interop_get(types<T>(), static_cast<lua_State*>(nullptr), -1, static_cast<void*>(nullptr), std::declval<stack::record&>()));
  547. template <typename T>
  548. using adl_sol_lua_check_test_t = decltype(sol_lua_check(types<T>(), static_cast<lua_State*>(nullptr), -1, &no_panic, std::declval<stack::record&>()));
  549. template <typename T>
  550. using adl_sol_lua_interop_check_test_t
  551. = decltype(sol_lua_interop_check(types<T>(), static_cast<lua_State*>(nullptr), -1, type::none, &no_panic, std::declval<stack::record&>()));
  552. template <typename T>
  553. using adl_sol_lua_check_get_test_t
  554. = decltype(sol_lua_check_get(types<T>(), static_cast<lua_State*>(nullptr), -1, &no_panic, std::declval<stack::record&>()));
  555. template <typename... Args>
  556. using adl_sol_lua_push_test_t = decltype(sol_lua_push(static_cast<lua_State*>(nullptr), std::declval<Args>()...));
  557. template <typename T, typename... Args>
  558. using adl_sol_lua_push_exact_test_t = decltype(sol_lua_push(types<T>(), static_cast<lua_State*>(nullptr), std::declval<Args>()...));
  559. template <typename T>
  560. inline constexpr bool is_adl_sol_lua_get_v = meta::is_detected_v<adl_sol_lua_get_test_t, T>;
  561. template <typename T>
  562. inline constexpr bool is_adl_sol_lua_interop_get_v = meta::is_detected_v<adl_sol_lua_interop_get_test_t, T>;
  563. template <typename T>
  564. inline constexpr bool is_adl_sol_lua_check_v = meta::is_detected_v<adl_sol_lua_check_test_t, T>;
  565. template <typename T>
  566. inline constexpr bool is_adl_sol_lua_interop_check_v = meta::is_detected_v<adl_sol_lua_interop_check_test_t, T>;
  567. template <typename T>
  568. inline constexpr bool is_adl_sol_lua_check_get_v = meta::is_detected_v<adl_sol_lua_check_get_test_t, T>;
  569. template <typename... Args>
  570. inline constexpr bool is_adl_sol_lua_push_v = meta::is_detected_v<adl_sol_lua_push_test_t, Args...>;
  571. template <typename T, typename... Args>
  572. inline constexpr bool is_adl_sol_lua_push_exact_v = meta::is_detected_v<adl_sol_lua_push_exact_test_t, T, Args...>;
  573. }} // namespace meta::meta_detail
  574. namespace stack {
  575. namespace stack_detail {
  576. constexpr const char* not_enough_stack_space = "not enough space left on Lua stack";
  577. constexpr const char* not_enough_stack_space_floating = "not enough space left on Lua stack for a floating point number";
  578. constexpr const char* not_enough_stack_space_integral = "not enough space left on Lua stack for an integral number";
  579. constexpr const char* not_enough_stack_space_string = "not enough space left on Lua stack for a string";
  580. constexpr const char* not_enough_stack_space_meta_function_name = "not enough space left on Lua stack for the name of a meta_function";
  581. constexpr const char* not_enough_stack_space_userdata = "not enough space left on Lua stack to create a sol2 userdata";
  582. constexpr const char* not_enough_stack_space_generic = "not enough space left on Lua stack to push valuees";
  583. constexpr const char* not_enough_stack_space_environment = "not enough space left on Lua stack to retrieve environment";
  584. template <typename T>
  585. struct strip {
  586. typedef T type;
  587. };
  588. template <typename T>
  589. struct strip<std::reference_wrapper<T>> {
  590. typedef T& type;
  591. };
  592. template <typename T>
  593. struct strip<user<T>> {
  594. typedef T& type;
  595. };
  596. template <typename T>
  597. struct strip<non_null<T>> {
  598. typedef T type;
  599. };
  600. template <typename T>
  601. using strip_t = typename strip<T>::type;
  602. template <typename C>
  603. static int get_size_hint(C& c) {
  604. return static_cast<int>(c.size());
  605. }
  606. template <typename V, typename Al>
  607. static int get_size_hint(const std::forward_list<V, Al>&) {
  608. // forward_list makes me sad
  609. return static_cast<int>(32);
  610. }
  611. template <typename T>
  612. decltype(auto) unchecked_unqualified_get(lua_State* L, int index, record& tracking) {
  613. using Tu = meta::unqualified_t<T>;
  614. if constexpr (meta::meta_detail::is_adl_sol_lua_get_v<Tu>) {
  615. return sol_lua_get(types<Tu>(), L, index, tracking);
  616. }
  617. else {
  618. unqualified_getter<Tu> g {};
  619. return g.get(L, index, tracking);
  620. }
  621. }
  622. template <typename T>
  623. decltype(auto) unchecked_get(lua_State* L, int index, record& tracking) {
  624. if constexpr (meta::meta_detail::is_adl_sol_lua_get_v<T>) {
  625. return sol_lua_get(types<T>(), L, index, tracking);
  626. }
  627. else {
  628. qualified_getter<T> g {};
  629. return g.get(L, index, tracking);
  630. }
  631. }
  632. template <typename T>
  633. decltype(auto) unqualified_interop_get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) {
  634. using Tu = meta::unqualified_t<T>;
  635. if constexpr (meta::meta_detail::is_adl_sol_lua_interop_get_v<Tu>) {
  636. return sol_lua_interop_get(types<Tu>(), L, index, unadjusted_pointer, tracking);
  637. }
  638. else {
  639. (void)L;
  640. (void)index;
  641. (void)unadjusted_pointer;
  642. (void)tracking;
  643. using Ti = stack_detail::strip_t<Tu>;
  644. return std::pair<bool, Ti*> { false, nullptr };
  645. }
  646. }
  647. template <typename T>
  648. decltype(auto) interop_get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) {
  649. if constexpr (meta::meta_detail::is_adl_sol_lua_interop_get_v<T>) {
  650. return sol_lua_interop_get(types<T>(), L, index, unadjusted_pointer, tracking);
  651. }
  652. else {
  653. return unqualified_interop_get<T>(L, index, unadjusted_pointer, tracking);
  654. }
  655. }
  656. template <typename T, typename Handler>
  657. bool unqualified_interop_check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
  658. using Tu = meta::unqualified_t<T>;
  659. if constexpr (meta::meta_detail::is_adl_sol_lua_interop_check_v<Tu>) {
  660. return sol_lua_interop_check(types<Tu>(), L, index, index_type, std::forward<Handler>(handler), tracking);
  661. }
  662. else {
  663. (void)L;
  664. (void)index;
  665. (void)index_type;
  666. (void)handler;
  667. (void)tracking;
  668. return false;
  669. }
  670. }
  671. template <typename T, typename Handler>
  672. bool interop_check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
  673. if constexpr (meta::meta_detail::is_adl_sol_lua_interop_check_v<T>) {
  674. return sol_lua_interop_check(types<T>(), L, index, index_type, std::forward<Handler>(handler), tracking);
  675. }
  676. else {
  677. return unqualified_interop_check<T>(L, index, index_type, std::forward<Handler>(handler), tracking);
  678. }
  679. }
  680. using undefined_method_func = void (*)(stack_reference);
  681. struct undefined_metatable {
  682. lua_State* L;
  683. const char* key;
  684. undefined_method_func on_new_table;
  685. undefined_metatable(lua_State* l, const char* k, undefined_method_func umf) : L(l), key(k), on_new_table(umf) {
  686. }
  687. void operator()() const {
  688. if (luaL_newmetatable(L, key) == 1) {
  689. on_new_table(stack_reference(L, -1));
  690. }
  691. lua_setmetatable(L, -2);
  692. }
  693. };
  694. } // namespace stack_detail
  695. inline bool maybe_indexable(lua_State* L, int index = -1) {
  696. type t = type_of(L, index);
  697. return t == type::userdata || t == type::table;
  698. }
  699. inline int top(lua_State* L) {
  700. return lua_gettop(L);
  701. }
  702. inline bool is_main_thread(lua_State* L) {
  703. int ismainthread = lua_pushthread(L);
  704. lua_pop(L, 1);
  705. return ismainthread == 1;
  706. }
  707. inline void coroutine_create_guard(lua_State* L) {
  708. if (is_main_thread(L)) {
  709. return;
  710. }
  711. int stacksize = lua_gettop(L);
  712. if (stacksize < 1) {
  713. return;
  714. }
  715. if (type_of(L, 1) != type::function) {
  716. return;
  717. }
  718. // well now we're screwed...
  719. // we can clean the stack and pray it doesn't destroy anything?
  720. lua_pop(L, stacksize);
  721. }
  722. inline void clear(lua_State* L, int table_index) {
  723. lua_pushnil(L);
  724. while (lua_next(L, table_index) != 0) {
  725. // remove value
  726. lua_pop(L, 1);
  727. // duplicate key to protect form rawset
  728. lua_pushvalue(L, -1);
  729. // push new value
  730. lua_pushnil(L);
  731. // table_index%[key] = nil
  732. lua_rawset(L, table_index);
  733. }
  734. }
  735. inline void clear(reference& r) {
  736. auto pp = push_pop<false>(r);
  737. int stack_index = pp.index_of(r);
  738. clear(r.lua_state(), stack_index);
  739. }
  740. inline void clear(stack_reference& r) {
  741. clear(r.lua_state(), r.stack_index());
  742. }
  743. inline void clear(lua_State* L_, stateless_reference& r) {
  744. r.push(L_);
  745. int stack_index = absolute_index(L_, -1);
  746. clear(L_, stack_index);
  747. r.pop(L_);
  748. }
  749. inline void clear(lua_State* L_, stateless_stack_reference& r) {
  750. clear(L_, r.stack_index());
  751. }
  752. template <typename T, typename... Args>
  753. int push(lua_State* L, T&& t, Args&&... args) {
  754. using Tu = meta::unqualified_t<T>;
  755. if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v<T, T, Args...>) {
  756. return sol_lua_push(types<T>(), L, std::forward<T>(t), std::forward<Args>(args)...);
  757. }
  758. else if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v<Tu, T, Args...>) {
  759. return sol_lua_push(types<Tu>(), L, std::forward<T>(t), std::forward<Args>(args)...);
  760. }
  761. else if constexpr (meta::meta_detail::is_adl_sol_lua_push_v<T, Args...>) {
  762. return sol_lua_push(L, std::forward<T>(t), std::forward<Args>(args)...);
  763. }
  764. else {
  765. unqualified_pusher<Tu> p {};
  766. return p.push(L, std::forward<T>(t), std::forward<Args>(args)...);
  767. }
  768. }
  769. // overload allows to use a pusher of a specific type, but pass in any kind of args
  770. template <typename T, typename Arg, typename... Args, typename = std::enable_if_t<!std::is_same<T, Arg>::value>>
  771. int push(lua_State* L, Arg&& arg, Args&&... args) {
  772. using Tu = meta::unqualified_t<T>;
  773. if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v<T, Arg, Args...>) {
  774. return sol_lua_push(types<T>(), L, std::forward<Arg>(arg), std::forward<Args>(args)...);
  775. }
  776. else if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v<Tu, Arg, Args...>) {
  777. return sol_lua_push(types<Tu>(), L, std::forward<Arg>(arg), std::forward<Args>(args)...);
  778. }
  779. else if constexpr (meta::meta_detail::is_adl_sol_lua_push_v<Arg, Args...> && !detail::is_tagged_v<Tu>) {
  780. return sol_lua_push(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
  781. }
  782. else {
  783. unqualified_pusher<Tu> p {};
  784. return p.push(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
  785. }
  786. }
  787. template <typename T, typename... Args>
  788. int push_userdata(lua_State* L, T&& t, Args&&... args) {
  789. using U = meta::unqualified_t<T>;
  790. using Tr = meta::conditional_t<std::is_pointer_v<U>,
  791. detail::as_pointer_tag<std::remove_pointer_t<U>>,
  792. meta::conditional_t<is_unique_usertype_v<U>, detail::as_unique_tag<U>, detail::as_value_tag<U>>>;
  793. return stack::push<Tr>(L, std::forward<T>(t), std::forward<Args>(args)...);
  794. }
  795. template <typename T, typename Arg, typename... Args>
  796. int push_userdata(lua_State* L, Arg&& arg, Args&&... args) {
  797. using U = meta::unqualified_t<T>;
  798. using Tr = meta::conditional_t<std::is_pointer_v<U>,
  799. detail::as_pointer_tag<std::remove_pointer_t<U>>,
  800. meta::conditional_t<is_unique_usertype_v<U>, detail::as_unique_tag<U>, detail::as_value_tag<U>>>;
  801. return stack::push<Tr>(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
  802. }
  803. namespace stack_detail {
  804. template <typename T, typename Arg, typename... Args>
  805. int push_reference(lua_State* L, Arg&& arg, Args&&... args) {
  806. // clang-format off
  807. using use_reference_tag =
  808. meta::all<
  809. meta::neg<is_value_semantic_for_function<T>>
  810. #if SOL_IS_OFF(SOL_FUNCTION_CALL_VALUE_SEMANTICS)
  811. , std::is_lvalue_reference<T>,
  812. meta::neg<std::is_const<std::remove_reference_t<T>>>,
  813. meta::neg<is_lua_primitive<meta::unqualified_t<T>>>,
  814. meta::neg<is_unique_usertype<meta::unqualified_t<T>>>
  815. #endif
  816. >;
  817. // clang-format on
  818. using Tr = meta::conditional_t<use_reference_tag::value, detail::as_reference_tag, meta::unqualified_t<T>>;
  819. return stack::push<Tr>(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
  820. }
  821. } // namespace stack_detail
  822. template <typename T, typename... Args>
  823. int push_reference(lua_State* L, T&& t, Args&&... args) {
  824. return stack_detail::push_reference<T>(L, std::forward<T>(t), std::forward<Args>(args)...);
  825. }
  826. template <typename T, typename Arg, typename... Args>
  827. int push_reference(lua_State* L, Arg&& arg, Args&&... args) {
  828. return stack_detail::push_reference<T>(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
  829. }
  830. inline int multi_push(lua_State*) {
  831. // do nothing
  832. return 0;
  833. }
  834. template <typename T, typename... Args>
  835. int multi_push(lua_State* L, T&& t, Args&&... args) {
  836. int pushcount = push(L, std::forward<T>(t));
  837. void(detail::swallow { (pushcount += stack::push(L, std::forward<Args>(args)), 0)... });
  838. return pushcount;
  839. }
  840. inline int multi_push_reference(lua_State*) {
  841. // do nothing
  842. return 0;
  843. }
  844. template <typename T, typename... Args>
  845. int multi_push_reference(lua_State* L, T&& t, Args&&... args) {
  846. int pushcount = stack::push_reference(L, std::forward<T>(t));
  847. void(detail::swallow { (pushcount += stack::push_reference(L, std::forward<Args>(args)), 0)... });
  848. return pushcount;
  849. }
  850. template <typename T, typename Handler>
  851. bool unqualified_check(lua_State* L, int index, Handler&& handler, record& tracking) {
  852. using Tu = meta::unqualified_t<T>;
  853. if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<Tu>) {
  854. return sol_lua_check(types<Tu>(), L, index, std::forward<Handler>(handler), tracking);
  855. }
  856. else {
  857. unqualified_checker<Tu, lua_type_of_v<Tu>> c{};
  858. return c.check(L, index, std::forward<Handler>(handler), tracking);
  859. }
  860. }
  861. template <typename T, typename Handler>
  862. bool unqualified_check(lua_State* L, int index, Handler&& handler) {
  863. record tracking {};
  864. return unqualified_check<T>(L, index, std::forward<Handler>(handler), tracking);
  865. }
  866. template <typename T>
  867. bool unqualified_check(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
  868. auto handler = &no_panic;
  869. return unqualified_check<T>(L, index, handler);
  870. }
  871. template <typename T, typename Handler>
  872. bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
  873. if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<T>) {
  874. return sol_lua_check(types<T>(), L, index, std::forward<Handler>(handler), tracking);
  875. }
  876. else {
  877. using Tu = meta::unqualified_t<T>;
  878. qualified_checker<T, lua_type_of_v<Tu>> c{};
  879. return c.check(L, index, std::forward<Handler>(handler), tracking);
  880. }
  881. }
  882. template <typename T, typename Handler>
  883. bool check(lua_State* L, int index, Handler&& handler) {
  884. record tracking {};
  885. return check<T>(L, index, std::forward<Handler>(handler), tracking);
  886. }
  887. template <typename T>
  888. bool check(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
  889. auto handler = &no_panic;
  890. return check<T>(L, index, handler);
  891. }
  892. template <typename T, typename Handler>
  893. bool check_usertype(lua_State* L, int index, type, Handler&& handler, record& tracking) {
  894. using Tu = meta::unqualified_t<T>;
  895. using detail_t = meta::conditional_t<std::is_pointer_v<T>, detail::as_pointer_tag<Tu>, detail::as_value_tag<Tu>>;
  896. return check<detail_t>(L, index, std::forward<Handler>(handler), tracking);
  897. }
  898. template <typename T, typename Handler>
  899. bool check_usertype(lua_State* L, int index, Handler&& handler, record& tracking) {
  900. using Tu = meta::unqualified_t<T>;
  901. using detail_t = meta::conditional_t<std::is_pointer_v<T>, detail::as_pointer_tag<Tu>, detail::as_value_tag<Tu>>;
  902. return check<detail_t>(L, index, std::forward<Handler>(handler), tracking);
  903. }
  904. template <typename T, typename Handler>
  905. bool check_usertype(lua_State* L, int index, Handler&& handler) {
  906. record tracking {};
  907. return check_usertype<T>(L, index, std::forward<Handler>(handler), tracking);
  908. }
  909. template <typename T>
  910. bool check_usertype(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
  911. auto handler = &no_panic;
  912. return check_usertype<T>(L, index, handler);
  913. }
  914. template <typename T, typename Handler>
  915. decltype(auto) unqualified_check_get(lua_State* L, int index, Handler&& handler, record& tracking) {
  916. using Tu = meta::unqualified_t<T>;
  917. if constexpr (meta::meta_detail::is_adl_sol_lua_check_get_v<T>) {
  918. return sol_lua_check_get(types<T>(), L, index, std::forward<Handler>(handler), tracking);
  919. }
  920. else if constexpr (meta::meta_detail::is_adl_sol_lua_check_get_v<Tu>) {
  921. return sol_lua_check_get(types<Tu>(), L, index, std::forward<Handler>(handler), tracking);
  922. }
  923. else {
  924. unqualified_check_getter<Tu> cg {};
  925. return cg.get(L, index, std::forward<Handler>(handler), tracking);
  926. }
  927. }
  928. template <typename T, typename Handler>
  929. decltype(auto) unqualified_check_get(lua_State* L, int index, Handler&& handler) {
  930. record tracking {};
  931. return unqualified_check_get<T>(L, index, handler, tracking);
  932. }
  933. template <typename T>
  934. decltype(auto) unqualified_check_get(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
  935. auto handler = &no_panic;
  936. return unqualified_check_get<T>(L, index, handler);
  937. }
  938. template <typename T, typename Handler>
  939. decltype(auto) check_get(lua_State* L, int index, Handler&& handler, record& tracking) {
  940. if constexpr (meta::meta_detail::is_adl_sol_lua_check_get_v<T>) {
  941. return sol_lua_check_get(types<T>(), L, index, std::forward<Handler>(handler), tracking);
  942. }
  943. else {
  944. qualified_check_getter<T> cg {};
  945. return cg.get(L, index, std::forward<Handler>(handler), tracking);
  946. }
  947. }
  948. template <typename T, typename Handler>
  949. decltype(auto) check_get(lua_State* L, int index, Handler&& handler) {
  950. record tracking {};
  951. return check_get<T>(L, index, handler, tracking);
  952. }
  953. template <typename T>
  954. decltype(auto) check_get(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
  955. auto handler = &no_panic;
  956. return check_get<T>(L, index, handler);
  957. }
  958. namespace stack_detail {
  959. template <typename Handler>
  960. bool check_types(lua_State*, int, Handler&&, record&) {
  961. return true;
  962. }
  963. template <typename T, typename... Args, typename Handler>
  964. bool check_types(lua_State* L, int firstargument, Handler&& handler, record& tracking) {
  965. if (!stack::check<T>(L, firstargument + tracking.used, handler, tracking))
  966. return false;
  967. return check_types<Args...>(L, firstargument, std::forward<Handler>(handler), tracking);
  968. }
  969. template <typename... Args, typename Handler>
  970. bool check_types(types<Args...>, lua_State* L, int index, Handler&& handler, record& tracking) {
  971. return check_types<Args...>(L, index, std::forward<Handler>(handler), tracking);
  972. }
  973. } // namespace stack_detail
  974. template <typename... Args, typename Handler>
  975. bool multi_check(lua_State* L, int index, Handler&& handler, record& tracking) {
  976. return stack_detail::check_types<Args...>(L, index, std::forward<Handler>(handler), tracking);
  977. }
  978. template <typename... Args, typename Handler>
  979. bool multi_check(lua_State* L, int index, Handler&& handler) {
  980. record tracking {};
  981. return multi_check<Args...>(L, index, std::forward<Handler>(handler), tracking);
  982. }
  983. template <typename... Args>
  984. bool multi_check(lua_State* L, int index) {
  985. return multi_check<Args...>(L, index);
  986. }
  987. template <typename T>
  988. auto unqualified_get(lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_unqualified_get<T>(L, index, tracking)) {
  989. #if SOL_IS_ON(SOL_SAFE_GETTER)
  990. static constexpr bool is_op = meta::is_optional_v<T>;
  991. if constexpr (is_op) {
  992. return stack_detail::unchecked_unqualified_get<T>(L, index, tracking);
  993. }
  994. else {
  995. if (is_lua_reference<T>::value) {
  996. return stack_detail::unchecked_unqualified_get<T>(L, index, tracking);
  997. }
  998. auto op = unqualified_check_get<T>(L, index, type_panic_c_str, tracking);
  999. return *std::move(op);
  1000. }
  1001. #else
  1002. return stack_detail::unchecked_unqualified_get<T>(L, index, tracking);
  1003. #endif
  1004. }
  1005. template <typename T>
  1006. decltype(auto) unqualified_get(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
  1007. record tracking {};
  1008. return unqualified_get<T>(L, index, tracking);
  1009. }
  1010. template <typename T>
  1011. auto get(lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_get<T>(L, index, tracking)) {
  1012. #if SOL_IS_ON(SOL_SAFE_GETTER)
  1013. static constexpr bool is_op = meta::is_optional_v<T>;
  1014. if constexpr (is_op) {
  1015. return stack_detail::unchecked_get<T>(L, index, tracking);
  1016. }
  1017. else {
  1018. if (is_lua_reference<T>::value) {
  1019. return stack_detail::unchecked_get<T>(L, index, tracking);
  1020. }
  1021. auto op = check_get<T>(L, index, type_panic_c_str, tracking);
  1022. return *std::move(op);
  1023. }
  1024. #else
  1025. return stack_detail::unchecked_get<T>(L, index, tracking);
  1026. #endif
  1027. }
  1028. template <typename T>
  1029. decltype(auto) get(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
  1030. record tracking {};
  1031. return get<T>(L, index, tracking);
  1032. }
  1033. template <typename T>
  1034. decltype(auto) get_usertype(lua_State* L, int index, record& tracking) {
  1035. using UT = meta::conditional_t<std::is_pointer<T>::value, detail::as_pointer_tag<std::remove_pointer_t<T>>, detail::as_value_tag<T>>;
  1036. return get<UT>(L, index, tracking);
  1037. }
  1038. template <typename T>
  1039. decltype(auto) get_usertype(lua_State* L, int index = -lua_size_v<meta::unqualified_t<T>>) {
  1040. record tracking {};
  1041. return get_usertype<T>(L, index, tracking);
  1042. }
  1043. template <typename T>
  1044. decltype(auto) pop(lua_State* L) {
  1045. return popper<T> {}.pop(L);
  1046. }
  1047. template <bool global = false, bool raw = false, typename Key>
  1048. void get_field(lua_State* L, Key&& key) {
  1049. field_getter<meta::unqualified_t<Key>, global, raw> {}.get(L, std::forward<Key>(key));
  1050. }
  1051. template <bool global = false, bool raw = false, typename Key>
  1052. void get_field(lua_State* L, Key&& key, int tableindex) {
  1053. field_getter<meta::unqualified_t<Key>, global, raw> {}.get(L, std::forward<Key>(key), tableindex);
  1054. }
  1055. template <bool global = false, typename Key>
  1056. void raw_get_field(lua_State* L, Key&& key) {
  1057. get_field<global, true>(L, std::forward<Key>(key));
  1058. }
  1059. template <bool global = false, typename Key>
  1060. void raw_get_field(lua_State* L, Key&& key, int tableindex) {
  1061. get_field<global, true>(L, std::forward<Key>(key), tableindex);
  1062. }
  1063. template <bool global = false, bool raw = false, typename C = detail::non_lua_nil_t, typename Key>
  1064. probe probe_get_field(lua_State* L, Key&& key) {
  1065. return probe_field_getter<meta::unqualified_t<Key>, C, global, raw> {}.get(L, std::forward<Key>(key));
  1066. }
  1067. template <bool global = false, bool raw = false, typename C = detail::non_lua_nil_t, typename Key>
  1068. probe probe_get_field(lua_State* L, Key&& key, int tableindex) {
  1069. return probe_field_getter<meta::unqualified_t<Key>, C, global, raw> {}.get(L, std::forward<Key>(key), tableindex);
  1070. }
  1071. template <bool global = false, typename C = detail::non_lua_nil_t, typename Key>
  1072. probe probe_raw_get_field(lua_State* L, Key&& key) {
  1073. return probe_get_field<global, true, C>(L, std::forward<Key>(key));
  1074. }
  1075. template <bool global = false, typename C = detail::non_lua_nil_t, typename Key>
  1076. probe probe_raw_get_field(lua_State* L, Key&& key, int tableindex) {
  1077. return probe_get_field<global, true, C>(L, std::forward<Key>(key), tableindex);
  1078. }
  1079. template <bool global = false, bool raw = false, typename Key, typename Value>
  1080. void set_field(lua_State* L, Key&& key, Value&& value) {
  1081. field_setter<meta::unqualified_t<Key>, global, raw> {}.set(L, std::forward<Key>(key), std::forward<Value>(value));
  1082. }
  1083. template <bool global = false, bool raw = false, typename Key, typename Value>
  1084. void set_field(lua_State* L, Key&& key, Value&& value, int tableindex) {
  1085. field_setter<meta::unqualified_t<Key>, global, raw> {}.set(L, std::forward<Key>(key), std::forward<Value>(value), tableindex);
  1086. }
  1087. template <bool global = false, typename Key, typename Value>
  1088. void raw_set_field(lua_State* L, Key&& key, Value&& value) {
  1089. set_field<global, true>(L, std::forward<Key>(key), std::forward<Value>(value));
  1090. }
  1091. template <bool global = false, typename Key, typename Value>
  1092. void raw_set_field(lua_State* L, Key&& key, Value&& value, int tableindex) {
  1093. set_field<global, true>(L, std::forward<Key>(key), std::forward<Value>(value), tableindex);
  1094. }
  1095. template <typename T, typename F>
  1096. void modify_unique_usertype_as(const stack_reference& obj, F&& f) {
  1097. void* raw = lua_touserdata(obj.lua_state(), obj.stack_index());
  1098. void* ptr_memory = detail::align_usertype_pointer(raw);
  1099. void* uu_memory = detail::align_usertype_unique<T>(raw);
  1100. T& uu = *static_cast<T*>(uu_memory);
  1101. f(uu);
  1102. *static_cast<void**>(ptr_memory) = static_cast<void*>(detail::unique_get(obj.lua_state(), uu));
  1103. }
  1104. template <typename F>
  1105. void modify_unique_usertype(const stack_reference& obj, F&& f) {
  1106. using bt = meta::bind_traits<meta::unqualified_t<F>>;
  1107. using T = typename bt::template arg_at<0>;
  1108. using Tu = meta::unqualified_t<T>;
  1109. modify_unique_usertype_as<Tu>(obj, std::forward<F>(f));
  1110. }
  1111. namespace stack_detail {
  1112. template <typename T, typename Handler>
  1113. decltype(auto) check_get_arg(lua_State* L_, int index_, Handler&& handler_, record& tracking_) {
  1114. if constexpr (meta::meta_detail::is_adl_sol_lua_check_access_v<T>) {
  1115. sol_lua_check_access(types<meta::unqualified_t<T>>(), L_, index_, tracking_);
  1116. }
  1117. return check_get<T>(L_, index_, std::forward<Handler>(handler_), tracking_);
  1118. }
  1119. template <typename T>
  1120. decltype(auto) unchecked_get_arg(lua_State* L_, int index_, record& tracking_) {
  1121. if constexpr (meta::meta_detail::is_adl_sol_lua_check_access_v<T>) {
  1122. sol_lua_check_access(types<meta::unqualified_t<T>>(), L_, index_, tracking_);
  1123. }
  1124. return unchecked_get<T>(L_, index_, tracking_);
  1125. }
  1126. } // namespace stack_detail
  1127. } // namespace stack
  1128. namespace detail {
  1129. template <typename T>
  1130. lua_CFunction make_destructor(std::true_type) {
  1131. if constexpr (is_unique_usertype_v<T>) {
  1132. return &unique_destroy<T>;
  1133. }
  1134. else if constexpr (!std::is_pointer_v<T>) {
  1135. return &usertype_alloc_destroy<T>;
  1136. }
  1137. else {
  1138. return &cannot_destroy<T>;
  1139. }
  1140. }
  1141. template <typename T>
  1142. lua_CFunction make_destructor(std::false_type) {
  1143. return &cannot_destroy<T>;
  1144. }
  1145. template <typename T>
  1146. lua_CFunction make_destructor() {
  1147. return make_destructor<T>(std::is_destructible<T>());
  1148. }
  1149. struct no_comp {
  1150. template <typename A, typename B>
  1151. bool operator()(A&&, B&&) const {
  1152. return false;
  1153. }
  1154. };
  1155. template <typename T>
  1156. int is_check(lua_State* L) {
  1157. return stack::push(L, stack::check<T>(L, 1, &no_panic));
  1158. }
  1159. template <typename T>
  1160. int member_default_to_string(std::true_type, lua_State* L) {
  1161. decltype(auto) ts = stack::get<T>(L, 1).to_string();
  1162. return stack::push(L, std::forward<decltype(ts)>(ts));
  1163. }
  1164. template <typename T>
  1165. int member_default_to_string(std::false_type, lua_State* L) {
  1166. return luaL_error(L,
  1167. "cannot perform to_string on '%s': no 'to_string' overload in namespace, 'to_string' member "
  1168. "function, or operator<<(ostream&, ...) present",
  1169. detail::demangle<T>().data());
  1170. }
  1171. template <typename T>
  1172. int adl_default_to_string(std::true_type, lua_State* L) {
  1173. using namespace std;
  1174. decltype(auto) ts = to_string(stack::get<T>(L, 1));
  1175. return stack::push(L, std::forward<decltype(ts)>(ts));
  1176. }
  1177. template <typename T>
  1178. int adl_default_to_string(std::false_type, lua_State* L) {
  1179. return member_default_to_string<T>(meta::supports_to_string_member<T>(), L);
  1180. }
  1181. template <typename T>
  1182. int oss_default_to_string(std::true_type, lua_State* L) {
  1183. std::ostringstream oss;
  1184. oss << stack::unqualified_get<T>(L, 1);
  1185. return stack::push(L, oss.str());
  1186. }
  1187. template <typename T>
  1188. int oss_default_to_string(std::false_type, lua_State* L) {
  1189. return adl_default_to_string<T>(meta::supports_adl_to_string<T>(), L);
  1190. }
  1191. template <typename T>
  1192. int default_to_string(lua_State* L) {
  1193. return oss_default_to_string<T>(meta::supports_op_left_shift<std::ostream, T>(), L);
  1194. }
  1195. template <typename T>
  1196. int default_size(lua_State* L) {
  1197. decltype(auto) self = stack::unqualified_get<T>(L, 1);
  1198. return stack::push(L, self.size());
  1199. }
  1200. template <typename T, typename Op>
  1201. int comparsion_operator_wrap(lua_State* L) {
  1202. if constexpr (std::is_void_v<T>) {
  1203. return stack::push(L, false);
  1204. }
  1205. else {
  1206. auto maybel = stack::unqualified_check_get<T>(L, 1);
  1207. if (!maybel) {
  1208. return stack::push(L, false);
  1209. }
  1210. auto mayber = stack::unqualified_check_get<T>(L, 2);
  1211. if (!mayber) {
  1212. return stack::push(L, false);
  1213. }
  1214. decltype(auto) l = *maybel;
  1215. decltype(auto) r = *mayber;
  1216. if constexpr (std::is_same_v<no_comp, Op>) {
  1217. std::equal_to<> op;
  1218. return stack::push(L, op(detail::ptr(l), detail::ptr(r)));
  1219. }
  1220. else {
  1221. if constexpr (std::is_same_v<std::equal_to<>, Op> // clang-format hack
  1222. || std::is_same_v<std::less_equal<>, Op> //
  1223. || std::is_same_v<std::less_equal<>, Op>) { //
  1224. if (detail::ptr(l) == detail::ptr(r)) {
  1225. return stack::push(L, true);
  1226. }
  1227. }
  1228. Op op;
  1229. return stack::push(L, op(detail::deref(l), detail::deref(r)));
  1230. }
  1231. }
  1232. }
  1233. template <typename T, typename IFx, typename Fx>
  1234. void insert_default_registrations(IFx&& ifx, Fx&& fx);
  1235. template <typename T, bool, bool>
  1236. struct get_is_primitive : is_lua_primitive<T> { };
  1237. template <typename T>
  1238. struct get_is_primitive<T, true, false>
  1239. : meta::neg<std::is_reference<decltype(sol_lua_get(types<T>(), nullptr, -1, std::declval<stack::record&>()))>> { };
  1240. template <typename T>
  1241. struct get_is_primitive<T, false, true>
  1242. : meta::neg<std::is_reference<decltype(sol_lua_get(types<meta::unqualified_t<T>>(), nullptr, -1, std::declval<stack::record&>()))>> { };
  1243. template <typename T>
  1244. struct get_is_primitive<T, true, true> : get_is_primitive<T, true, false> { };
  1245. } // namespace detail
  1246. template <typename T>
  1247. struct is_proxy_primitive
  1248. : detail::get_is_primitive<T, meta::meta_detail::is_adl_sol_lua_get_v<T>, meta::meta_detail::is_adl_sol_lua_get_v<meta::unqualified_t<T>>> { };
  1249. } // namespace sol
  1250. #endif // SOL_STACK_CORE_HPP