state_view.hpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874
  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_STATE_VIEW_HPP
  19. #define SOL_STATE_VIEW_HPP
  20. #include <sol/error.hpp>
  21. #include <sol/table.hpp>
  22. #include <sol/environment.hpp>
  23. #include <sol/load_result.hpp>
  24. #include <sol/state_handling.hpp>
  25. #include <memory>
  26. #include <cstddef>
  27. namespace sol {
  28. class state_view {
  29. private:
  30. lua_State* L;
  31. table reg;
  32. global_table global;
  33. optional<object> is_loaded_package(const std::string& key) {
  34. auto loaded = reg.traverse_get<optional<object>>("_LOADED", key);
  35. bool is53mod = loaded && !(loaded->is<bool>() && !loaded->as<bool>());
  36. if (is53mod)
  37. return loaded;
  38. #if SOL_LUA_VERSION_I_ <= 501
  39. auto loaded51 = global.traverse_get<optional<object>>("package", "loaded", key);
  40. bool is51mod = loaded51 && !(loaded51->is<bool>() && !loaded51->as<bool>());
  41. if (is51mod)
  42. return loaded51;
  43. #endif
  44. return nullopt;
  45. }
  46. template <typename T>
  47. void ensure_package(const std::string& key, T&& sr) {
  48. #if SOL_LUA_VERSION_I_ <= 501
  49. auto pkg = global["package"];
  50. if (!pkg.valid()) {
  51. pkg = create_table_with("loaded", create_table_with(key, sr));
  52. }
  53. else {
  54. auto ld = pkg["loaded"];
  55. if (!ld.valid()) {
  56. ld = create_table_with(key, sr);
  57. }
  58. else {
  59. ld[key] = sr;
  60. }
  61. }
  62. #endif
  63. auto loaded = reg["_LOADED"];
  64. if (!loaded.valid()) {
  65. loaded = create_table_with(key, sr);
  66. }
  67. else {
  68. loaded[key] = sr;
  69. }
  70. }
  71. template <typename Fx>
  72. object require_core(const std::string& key, Fx&& action, bool create_global = true) {
  73. optional<object> loaded = is_loaded_package(key);
  74. if (loaded && loaded->valid())
  75. return std::move(*loaded);
  76. int before = lua_gettop(L);
  77. action();
  78. int after = lua_gettop(L);
  79. if (before == after) {
  80. // I mean, you were supposed to return
  81. // something, ANYTHING, from your requires script. I guess I'll just
  82. // but some trash in here, it's on you after that?
  83. ensure_package(key, static_cast<void*>(L));
  84. return object(L, lua_nil);
  85. }
  86. stack_reference sr(L, -1);
  87. if (create_global)
  88. set(key, sr);
  89. ensure_package(key, sr);
  90. return stack::pop<object>(L);
  91. }
  92. public:
  93. using iterator = typename global_table::iterator;
  94. using const_iterator = typename global_table::const_iterator;
  95. state_view(lua_State* Ls) : L(Ls), reg(Ls, LUA_REGISTRYINDEX), global(Ls, global_tag) {
  96. }
  97. state_view(this_state Ls) : state_view(Ls.L) {
  98. }
  99. lua_State* lua_state() const {
  100. return L;
  101. }
  102. template <typename... Args>
  103. void open_libraries(Args&&... args) {
  104. static_assert(meta::all_same<lib, meta::unqualified_t<Args>...>::value, "all types must be libraries");
  105. if constexpr (sizeof...(args) == 0) {
  106. luaL_openlibs(L);
  107. return;
  108. }
  109. else {
  110. lib libraries[1 + sizeof...(args)] = { lib::count, std::forward<Args>(args)... };
  111. for (auto&& library : libraries) {
  112. switch (library) {
  113. #if SOL_LUA_VERSION_I_ <= 501 && SOL_IS_ON(SOL_USE_LUAJIT)
  114. case lib::coroutine:
  115. #endif // luajit opens coroutine base stuff
  116. case lib::base:
  117. luaL_requiref(L, "base", luaopen_base, 1);
  118. lua_pop(L, 1);
  119. break;
  120. case lib::package:
  121. luaL_requiref(L, "package", luaopen_package, 1);
  122. lua_pop(L, 1);
  123. break;
  124. #if SOL_IS_OFF(SOL_USE_LUAJIT)
  125. case lib::coroutine:
  126. #if SOL_LUA_VERSION_I_ > 501
  127. luaL_requiref(L, "coroutine", luaopen_coroutine, 1);
  128. lua_pop(L, 1);
  129. #endif // Lua 5.2+ only
  130. break;
  131. #endif // Not LuaJIT - comes builtin
  132. case lib::string:
  133. luaL_requiref(L, "string", luaopen_string, 1);
  134. lua_pop(L, 1);
  135. break;
  136. case lib::table:
  137. luaL_requiref(L, "table", luaopen_table, 1);
  138. lua_pop(L, 1);
  139. break;
  140. case lib::math:
  141. luaL_requiref(L, "math", luaopen_math, 1);
  142. lua_pop(L, 1);
  143. break;
  144. case lib::bit32:
  145. #if SOL_IS_ON(SOL_USE_LUAJIT)
  146. luaL_requiref(L, "bit32", luaopen_bit, 1);
  147. lua_pop(L, 1);
  148. #elif SOL_IS_ON(SOL_LUA_BIT32_LIB)
  149. luaL_requiref(L, "bit32", luaopen_bit32, 1);
  150. lua_pop(L, 1);
  151. #else
  152. #endif
  153. break;
  154. case lib::io:
  155. luaL_requiref(L, "io", luaopen_io, 1);
  156. lua_pop(L, 1);
  157. break;
  158. case lib::os:
  159. luaL_requiref(L, "os", luaopen_os, 1);
  160. lua_pop(L, 1);
  161. break;
  162. case lib::debug:
  163. luaL_requiref(L, "debug", luaopen_debug, 1);
  164. lua_pop(L, 1);
  165. break;
  166. case lib::utf8:
  167. #if SOL_LUA_VERSION_I_ > 502 && SOL_IS_OFF(SOL_USE_LUAJIT)
  168. luaL_requiref(L, "utf8", luaopen_utf8, 1);
  169. lua_pop(L, 1);
  170. #endif // Lua 5.3+ only
  171. break;
  172. case lib::ffi:
  173. #if SOL_IS_ON(SOL_USE_LUAJIT) && SOL_IS_OFF(SOL_LUAJIT_FFI_DISABLED)
  174. luaL_requiref(L, "ffi", luaopen_ffi, 1);
  175. lua_pop(L, 1);
  176. #endif // LuaJIT only
  177. break;
  178. case lib::jit:
  179. #if SOL_IS_ON(SOL_USE_LUAJIT)
  180. luaL_requiref(L, "jit", luaopen_jit, 0);
  181. lua_pop(L, 1);
  182. #endif // LuaJIT Only
  183. break;
  184. case lib::count:
  185. default:
  186. break;
  187. }
  188. }
  189. }
  190. }
  191. object require(const std::string& key, lua_CFunction open_function, bool create_global = true) {
  192. luaL_requiref(L, key.c_str(), open_function, create_global ? 1 : 0);
  193. return stack::pop<object>(L);
  194. }
  195. object require_script(const std::string& key, const string_view& code, bool create_global = true,
  196. const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  197. auto action = [this, &code, &chunkname, &mode]() { stack::script(L, code, chunkname, mode); };
  198. return require_core(key, action, create_global);
  199. }
  200. object require_file(const std::string& key, const std::string& filename, bool create_global = true, load_mode mode = load_mode::any) {
  201. auto action = [this, &filename, &mode]() { stack::script_file(L, filename, mode); };
  202. return require_core(key, action, create_global);
  203. }
  204. void clear_package_loaders() {
  205. optional<table> maybe_package = this->global["package"];
  206. if (!maybe_package) {
  207. // package lib wasn't opened
  208. // open package lib
  209. return;
  210. }
  211. table& package = *maybe_package;
  212. // yay for version differences...
  213. // one day Lua 5.1 will die a peaceful death
  214. // and its old bones will find blissful rest
  215. auto loaders_proxy = package
  216. #if SOL_LUA_VERSION_I_ < 502
  217. ["loaders"]
  218. #else
  219. ["searchers"]
  220. #endif
  221. ;
  222. if (!loaders_proxy.valid()) {
  223. // nothing to clear
  224. return;
  225. }
  226. // we need to create the table for loaders
  227. // table does not exist, so create and move forward
  228. loaders_proxy = new_table(1, 0);
  229. }
  230. template <typename Fx>
  231. void add_package_loader(Fx&& fx, bool clear_all_package_loaders = false) {
  232. optional<table> maybe_package = this->global["package"];
  233. if (!maybe_package) {
  234. // package lib wasn't opened
  235. // open package lib
  236. return;
  237. }
  238. table& package = *maybe_package;
  239. // yay for version differences...
  240. // one day Lua 5.1 will die a peaceful death
  241. // and its old bones will find blissful rest
  242. auto loaders_proxy = package
  243. #if SOL_LUA_VERSION_I_ < 502
  244. ["loaders"]
  245. #else
  246. ["searchers"]
  247. #endif
  248. ;
  249. bool make_new_table = clear_all_package_loaders || !loaders_proxy.valid();
  250. if (make_new_table) {
  251. // we need to create the table for loaders
  252. // table does not exist, so create and move forward
  253. loaders_proxy = new_table(1, 0);
  254. }
  255. optional<table> maybe_loaders = loaders_proxy;
  256. if (!maybe_loaders) {
  257. // loaders/searches
  258. // thing exists in package, but it
  259. // ain't a table or a table-alike...!
  260. return;
  261. }
  262. table loaders = loaders_proxy;
  263. loaders.add(std::forward<Fx>(fx));
  264. }
  265. template <typename E>
  266. protected_function_result do_reader(lua_Reader reader, void* data, const basic_environment<E>& env,
  267. const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  268. detail::typical_chunk_name_t basechunkname = {};
  269. const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname);
  270. load_status x = static_cast<load_status>(lua_load(L, reader, data, chunknametarget, to_string(mode).c_str()));
  271. if (x != load_status::ok) {
  272. return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x));
  273. }
  274. stack_aligned_protected_function pf(L, -1);
  275. set_environment(env, pf);
  276. return pf();
  277. }
  278. protected_function_result do_reader(
  279. lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  280. detail::typical_chunk_name_t basechunkname = {};
  281. const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname);
  282. load_status x = static_cast<load_status>(lua_load(L, reader, data, chunknametarget, to_string(mode).c_str()));
  283. if (x != load_status::ok) {
  284. return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x));
  285. }
  286. stack_aligned_protected_function pf(L, -1);
  287. return pf();
  288. }
  289. template <typename E>
  290. protected_function_result do_string(const string_view& code, const basic_environment<E>& env,
  291. const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  292. detail::typical_chunk_name_t basechunkname = {};
  293. const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
  294. load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()));
  295. if (x != load_status::ok) {
  296. return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x));
  297. }
  298. stack_aligned_protected_function pf(L, -1);
  299. set_environment(env, pf);
  300. return pf();
  301. }
  302. protected_function_result do_string(
  303. const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  304. detail::typical_chunk_name_t basechunkname = {};
  305. const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
  306. load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()));
  307. if (x != load_status::ok) {
  308. return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x));
  309. }
  310. stack_aligned_protected_function pf(L, -1);
  311. return pf();
  312. }
  313. template <typename E>
  314. protected_function_result do_file(const std::string& filename, const basic_environment<E>& env, load_mode mode = load_mode::any) {
  315. load_status x = static_cast<load_status>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str()));
  316. if (x != load_status::ok) {
  317. return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x));
  318. }
  319. stack_aligned_protected_function pf(L, -1);
  320. set_environment(env, pf);
  321. return pf();
  322. }
  323. protected_function_result do_file(const std::string& filename, load_mode mode = load_mode::any) {
  324. load_status x = static_cast<load_status>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str()));
  325. if (x != load_status::ok) {
  326. return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x));
  327. }
  328. stack_aligned_protected_function pf(L, -1);
  329. return pf();
  330. }
  331. template <typename Fx,
  332. meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>,
  333. meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler>
  334. protected_function_result safe_script(
  335. lua_Reader reader, void* data, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  336. protected_function_result pfr = do_reader(reader, data, chunkname, mode);
  337. if (!pfr.valid()) {
  338. return on_error(L, std::move(pfr));
  339. }
  340. return pfr;
  341. }
  342. protected_function_result safe_script(
  343. lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  344. return safe_script(reader, data, script_default_on_error, chunkname, mode);
  345. }
  346. template <typename Fx,
  347. meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>,
  348. meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler>
  349. protected_function_result safe_script(
  350. const string_view& code, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  351. protected_function_result pfr = do_string(code, chunkname, mode);
  352. if (!pfr.valid()) {
  353. return on_error(L, std::move(pfr));
  354. }
  355. return pfr;
  356. }
  357. template <typename Fx, typename E>
  358. protected_function_result safe_script(const string_view& code, const basic_environment<E>& env, Fx&& on_error,
  359. const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  360. protected_function_result pfr = do_string(code, env, chunkname, mode);
  361. if (!pfr.valid()) {
  362. return on_error(L, std::move(pfr));
  363. }
  364. return pfr;
  365. }
  366. template <typename E>
  367. protected_function_result safe_script(const string_view& code, const basic_environment<E>& env,
  368. const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  369. return safe_script(code, env, script_default_on_error, chunkname, mode);
  370. }
  371. protected_function_result safe_script(
  372. const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  373. return safe_script(code, script_default_on_error, chunkname, mode);
  374. }
  375. template <typename Fx,
  376. meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>,
  377. meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler>
  378. protected_function_result safe_script_file(const std::string& filename, Fx&& on_error, load_mode mode = load_mode::any) {
  379. protected_function_result pfr = do_file(filename, mode);
  380. if (!pfr.valid()) {
  381. return on_error(L, std::move(pfr));
  382. }
  383. return pfr;
  384. }
  385. template <typename Fx, typename E>
  386. protected_function_result safe_script_file(
  387. const std::string& filename, const basic_environment<E>& env, Fx&& on_error, load_mode mode = load_mode::any) {
  388. protected_function_result pfr = do_file(filename, env, mode);
  389. if (!pfr.valid()) {
  390. return on_error(L, std::move(pfr));
  391. }
  392. return pfr;
  393. }
  394. template <typename E>
  395. protected_function_result safe_script_file(const std::string& filename, const basic_environment<E>& env, load_mode mode = load_mode::any) {
  396. return safe_script_file(filename, env, script_default_on_error, mode);
  397. }
  398. protected_function_result safe_script_file(const std::string& filename, load_mode mode = load_mode::any) {
  399. return safe_script_file(filename, script_default_on_error, mode);
  400. }
  401. template <typename E>
  402. unsafe_function_result unsafe_script(lua_Reader reader, void* data, const basic_environment<E>& env,
  403. const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  404. detail::typical_chunk_name_t basechunkname = {};
  405. const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname);
  406. int index = lua_gettop(L);
  407. if (lua_load(L, reader, data, chunknametarget, to_string(mode).c_str())) {
  408. lua_error(L);
  409. }
  410. set_environment(env, stack_reference(L, raw_index(index + 1)));
  411. if (lua_pcall(L, 0, LUA_MULTRET, 0)) {
  412. lua_error(L);
  413. }
  414. int postindex = lua_gettop(L);
  415. int returns = postindex - index;
  416. return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
  417. }
  418. unsafe_function_result unsafe_script(
  419. lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  420. int index = lua_gettop(L);
  421. stack::script(L, reader, data, chunkname, mode);
  422. int postindex = lua_gettop(L);
  423. int returns = postindex - index;
  424. return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
  425. }
  426. template <typename E>
  427. unsafe_function_result unsafe_script(const string_view& code, const basic_environment<E>& env,
  428. const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  429. detail::typical_chunk_name_t basechunkname = {};
  430. const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
  431. int index = lua_gettop(L);
  432. if (luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str())) {
  433. lua_error(L);
  434. }
  435. set_environment(env, stack_reference(L, raw_index(index + 1)));
  436. if (lua_pcall(L, 0, LUA_MULTRET, 0)) {
  437. lua_error(L);
  438. }
  439. int postindex = lua_gettop(L);
  440. int returns = postindex - index;
  441. return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
  442. }
  443. unsafe_function_result unsafe_script(
  444. const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  445. int index = lua_gettop(L);
  446. stack::script(L, code, chunkname, mode);
  447. int postindex = lua_gettop(L);
  448. int returns = postindex - index;
  449. return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
  450. }
  451. template <typename E>
  452. unsafe_function_result unsafe_script_file(const std::string& filename, const basic_environment<E>& env, load_mode mode = load_mode::any) {
  453. int index = lua_gettop(L);
  454. if (luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())) {
  455. lua_error(L);
  456. }
  457. set_environment(env, stack_reference(L, raw_index(index + 1)));
  458. if (lua_pcall(L, 0, LUA_MULTRET, 0)) {
  459. lua_error(L);
  460. }
  461. int postindex = lua_gettop(L);
  462. int returns = postindex - index;
  463. return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
  464. }
  465. unsafe_function_result unsafe_script_file(const std::string& filename, load_mode mode = load_mode::any) {
  466. int index = lua_gettop(L);
  467. stack::script_file(L, filename, mode);
  468. int postindex = lua_gettop(L);
  469. int returns = postindex - index;
  470. return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
  471. }
  472. template <typename Fx,
  473. meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>,
  474. meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler>
  475. protected_function_result script(
  476. const string_view& code, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  477. return safe_script(code, std::forward<Fx>(on_error), chunkname, mode);
  478. }
  479. template <typename Fx,
  480. meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>,
  481. meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler>
  482. protected_function_result script_file(const std::string& filename, Fx&& on_error, load_mode mode = load_mode::any) {
  483. return safe_script_file(filename, std::forward<Fx>(on_error), mode);
  484. }
  485. template <typename Fx, typename E>
  486. protected_function_result script(const string_view& code, const basic_environment<E>& env, Fx&& on_error,
  487. const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  488. return safe_script(code, env, std::forward<Fx>(on_error), chunkname, mode);
  489. }
  490. template <typename Fx, typename E>
  491. protected_function_result script_file(const std::string& filename, const basic_environment<E>& env, Fx&& on_error, load_mode mode = load_mode::any) {
  492. return safe_script_file(filename, env, std::forward<Fx>(on_error), mode);
  493. }
  494. protected_function_result script(
  495. const string_view& code, const environment& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  496. return safe_script(code, env, script_default_on_error, chunkname, mode);
  497. }
  498. protected_function_result script_file(const std::string& filename, const environment& env, load_mode mode = load_mode::any) {
  499. return safe_script_file(filename, env, script_default_on_error, mode);
  500. }
  501. #if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS)
  502. protected_function_result script(
  503. lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  504. return safe_script(reader, data, chunkname, mode);
  505. }
  506. protected_function_result script(
  507. const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  508. return safe_script(code, chunkname, mode);
  509. }
  510. protected_function_result script_file(const std::string& filename, load_mode mode = load_mode::any) {
  511. return safe_script_file(filename, mode);
  512. }
  513. #else
  514. unsafe_function_result script(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  515. return unsafe_script(code, chunkname, mode);
  516. }
  517. unsafe_function_result script_file(const std::string& filename, load_mode mode = load_mode::any) {
  518. return unsafe_script_file(filename, mode);
  519. }
  520. #endif
  521. load_result load(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  522. detail::typical_chunk_name_t basechunkname = {};
  523. const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
  524. load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()));
  525. return load_result(L, absolute_index(L, -1), 1, 1, x);
  526. }
  527. load_result load_buffer(const char* buff, size_t size, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  528. return load(string_view(buff, size), chunkname, mode);
  529. }
  530. load_result load_buffer(
  531. const std::byte* buff, size_t size, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  532. return load(string_view(reinterpret_cast<const char*>(buff), size), chunkname, mode);
  533. }
  534. load_result load_file(const std::string& filename, load_mode mode = load_mode::any) {
  535. load_status x = static_cast<load_status>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str()));
  536. return load_result(L, absolute_index(L, -1), 1, 1, x);
  537. }
  538. load_result load(lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
  539. detail::typical_chunk_name_t basechunkname = {};
  540. const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname);
  541. load_status x = static_cast<load_status>(lua_load(L, reader, data, chunknametarget, to_string(mode).c_str()));
  542. return load_result(L, absolute_index(L, -1), 1, 1, x);
  543. }
  544. iterator begin() const {
  545. return global.begin();
  546. }
  547. iterator end() const {
  548. return global.end();
  549. }
  550. const_iterator cbegin() const {
  551. return global.cbegin();
  552. }
  553. const_iterator cend() const {
  554. return global.cend();
  555. }
  556. global_table globals() const {
  557. // if we return a reference
  558. // we'll be screwed a bit
  559. return global;
  560. }
  561. global_table& globals() {
  562. return global;
  563. }
  564. table registry() const {
  565. return reg;
  566. }
  567. std::size_t memory_used() const {
  568. return total_memory_used(lua_state());
  569. }
  570. int stack_top() const {
  571. return stack::top(L);
  572. }
  573. int stack_clear() {
  574. int s = stack_top();
  575. lua_pop(L, s);
  576. return s;
  577. }
  578. bool supports_gc_mode(gc_mode mode) const noexcept {
  579. #if SOL_LUA_VERSION_I_ >= 504
  580. // supports all modes
  581. (void)mode;
  582. return true;
  583. #endif
  584. return mode == gc_mode::default_value;
  585. }
  586. bool is_gc_on() const {
  587. #if SOL_LUA_VERSION_I_ >= 502
  588. return lua_gc(lua_state(), LUA_GCISRUNNING, 0) == 1;
  589. #else
  590. // You cannot turn it off in Lua 5.1
  591. return true;
  592. #endif
  593. }
  594. void collect_garbage() {
  595. lua_gc(lua_state(), LUA_GCCOLLECT, 0);
  596. }
  597. void collect_gc() {
  598. collect_garbage();
  599. }
  600. bool step_gc(int step_size_kilobytes) {
  601. // THOUGHT: std::chrono-alikes to map "kilobyte size" here...?
  602. // Make it harder to give MB or KB to a B parameter...?
  603. // Probably overkill for now.
  604. #if SOL_LUA_VERSION_I_ >= 504
  605. // The manual implies that this function is almost always successful...
  606. // is it?? It could depend on the GC mode...
  607. return lua_gc(lua_state(), LUA_GCSTEP, step_size_kilobytes) != 0;
  608. #else
  609. return lua_gc(lua_state(), LUA_GCSTEP, step_size_kilobytes) == 1;
  610. #endif
  611. }
  612. void restart_gc() {
  613. lua_gc(lua_state(), LUA_GCRESTART, 0);
  614. }
  615. void stop_gc() {
  616. lua_gc(lua_state(), LUA_GCSTOP, 0);
  617. }
  618. // Returns the old GC mode. Check support using the supports_gc_mode function.
  619. gc_mode change_gc_mode_incremental(int pause, int step_multiplier, int step_byte_size) {
  620. // "What the fuck does any of this mean??"
  621. // http://www.lua.org/manual/5.4/manual.html#2.5.1
  622. // THOUGHT: std::chrono-alikes to map "byte size" here...?
  623. // Make it harder to give MB or KB to a B parameter...?
  624. // Probably overkill for now.
  625. #if SOL_LUA_VERSION_I_ >= 504
  626. int old_mode = lua_gc(lua_state(), LUA_GCINC, pause, step_multiplier, step_byte_size);
  627. if (old_mode == LUA_GCGEN) {
  628. return gc_mode::generational;
  629. }
  630. else if (old_mode == LUA_GCINC) {
  631. return gc_mode::incremental;
  632. }
  633. #else
  634. lua_gc(lua_state(), LUA_GCSETPAUSE, pause);
  635. lua_gc(lua_state(), LUA_GCSETSTEPMUL, step_multiplier);
  636. (void)step_byte_size; // means nothing in older versions
  637. #endif
  638. return gc_mode::default_value;
  639. }
  640. // Returns the old GC mode. Check support using the supports_gc_mode function.
  641. gc_mode change_gc_mode_generational(int minor_multiplier, int major_multiplier) {
  642. #if SOL_LUA_VERSION_I_ >= 504
  643. // "What does this shit mean?"
  644. // http://www.lua.org/manual/5.4/manual.html#2.5.2
  645. int old_mode = lua_gc(lua_state(), LUA_GCGEN, minor_multiplier, major_multiplier);
  646. if (old_mode == LUA_GCGEN) {
  647. return gc_mode::generational;
  648. }
  649. else if (old_mode == LUA_GCINC) {
  650. return gc_mode::incremental;
  651. }
  652. #else
  653. (void)minor_multiplier;
  654. (void)major_multiplier;
  655. #endif
  656. return gc_mode::default_value;
  657. }
  658. operator lua_State*() const {
  659. return lua_state();
  660. }
  661. void set_panic(lua_CFunction panic) {
  662. lua_atpanic(lua_state(), panic);
  663. }
  664. void set_exception_handler(exception_handler_function handler) {
  665. set_default_exception_handler(lua_state(), handler);
  666. }
  667. template <typename... Args, typename... Keys>
  668. decltype(auto) get(Keys&&... keys) const {
  669. return global.get<Args...>(std::forward<Keys>(keys)...);
  670. }
  671. template <typename T, typename Key>
  672. decltype(auto) get_or(Key&& key, T&& otherwise) const {
  673. return global.get_or(std::forward<Key>(key), std::forward<T>(otherwise));
  674. }
  675. template <typename T, typename Key, typename D>
  676. decltype(auto) get_or(Key&& key, D&& otherwise) const {
  677. return global.get_or<T>(std::forward<Key>(key), std::forward<D>(otherwise));
  678. }
  679. template <typename... Args>
  680. state_view& set(Args&&... args) {
  681. global.set(std::forward<Args>(args)...);
  682. return *this;
  683. }
  684. template <typename T, typename... Keys>
  685. decltype(auto) traverse_get(Keys&&... keys) const {
  686. return global.traverse_get<T>(std::forward<Keys>(keys)...);
  687. }
  688. template <typename... Args>
  689. state_view& traverse_set(Args&&... args) {
  690. global.traverse_set(std::forward<Args>(args)...);
  691. return *this;
  692. }
  693. template <typename Class, typename... Args>
  694. usertype<Class> new_usertype(Args&&... args) {
  695. return global.new_usertype<Class>(std::forward<Args>(args)...);
  696. }
  697. template <bool read_only = true, typename... Args>
  698. state_view& new_enum(const string_view& name, Args&&... args) {
  699. global.new_enum<read_only>(name, std::forward<Args>(args)...);
  700. return *this;
  701. }
  702. template <typename T, bool read_only = true>
  703. state_view& new_enum(const string_view& name, std::initializer_list<std::pair<string_view, T>> items) {
  704. global.new_enum<T, read_only>(name, std::move(items));
  705. return *this;
  706. }
  707. template <typename Fx>
  708. void for_each(Fx&& fx) {
  709. global.for_each(std::forward<Fx>(fx));
  710. }
  711. template <typename T>
  712. table_proxy<global_table&, detail::proxy_key_t<T>> operator[](T&& key) {
  713. return global[std::forward<T>(key)];
  714. }
  715. template <typename T>
  716. table_proxy<const global_table&, detail::proxy_key_t<T>> operator[](T&& key) const {
  717. return global[std::forward<T>(key)];
  718. }
  719. template <typename Sig, typename... Args, typename Key>
  720. state_view& set_function(Key&& key, Args&&... args) {
  721. global.set_function<Sig>(std::forward<Key>(key), std::forward<Args>(args)...);
  722. return *this;
  723. }
  724. template <typename... Args, typename Key>
  725. state_view& set_function(Key&& key, Args&&... args) {
  726. global.set_function(std::forward<Key>(key), std::forward<Args>(args)...);
  727. return *this;
  728. }
  729. template <typename Name>
  730. table create_table(Name&& name, int narr = 0, int nrec = 0) {
  731. return global.create(std::forward<Name>(name), narr, nrec);
  732. }
  733. template <typename Name, typename Key, typename Value, typename... Args>
  734. table create_table(Name&& name, int narr, int nrec, Key&& key, Value&& value, Args&&... args) {
  735. return global.create(std::forward<Name>(name), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
  736. }
  737. template <typename Name, typename... Args>
  738. table create_named_table(Name&& name, Args&&... args) {
  739. table x = global.create_with(std::forward<Args>(args)...);
  740. global.set(std::forward<Name>(name), x);
  741. return x;
  742. }
  743. table create_table(int narr = 0, int nrec = 0) {
  744. return create_table(lua_state(), narr, nrec);
  745. }
  746. template <typename Key, typename Value, typename... Args>
  747. table create_table(int narr, int nrec, Key&& key, Value&& value, Args&&... args) {
  748. return create_table(lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
  749. }
  750. template <typename... Args>
  751. table create_table_with(Args&&... args) {
  752. return create_table_with(lua_state(), std::forward<Args>(args)...);
  753. }
  754. static inline table create_table(lua_State* L, int narr = 0, int nrec = 0) {
  755. return global_table::create(L, narr, nrec);
  756. }
  757. template <typename Key, typename Value, typename... Args>
  758. static inline table create_table(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) {
  759. return global_table::create(L, narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
  760. }
  761. template <typename... Args>
  762. static inline table create_table_with(lua_State* L, Args&&... args) {
  763. return global_table::create_with(L, std::forward<Args>(args)...);
  764. }
  765. };
  766. } // namespace sol
  767. #endif // SOL_STATE_VIEW_HPP