?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download

  1. // https://github.com/vinniefalco/LuaBridge
  2. // Copyright 2019, Dmitry Tarakanov
  3. // Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
  4. // Copyright 2007, Nathan Reed
  5. // SPDX-License-Identifier: MIT
  6.  
  7. #pragma once
  8.  
  9. #include <LuaBridge/detail/LuaHelpers.h>
  10. #include <LuaBridge/detail/Userdata.h>
  11.  
  12. #include <string>
  13. #ifdef LUABRIDGE_CXX17
  14. #include <string_view>
  15. #endif
  16.  
  17. namespace luabridge {
  18.  
  19. /// Lua stack traits for C++ types.
  20. ///
  21. /// @tparam T A C++ type.
  22. ///
  23. template<class T>
  24. struct Stack;
  25.  
  26. template<>
  27. struct Stack<void>
  28. {
  29.     static void push(lua_State*) {}
  30. };
  31.  
  32. //------------------------------------------------------------------------------
  33. /**
  34.     Receive the lua_State* as an argument.
  35. */
  36. template<>
  37. struct Stack<lua_State*>
  38. {
  39.     static lua_State* get(lua_State* L, int) { return L; }
  40. };
  41.  
  42. //------------------------------------------------------------------------------
  43. /**
  44.     Stack specialization for a lua_CFunction.
  45. */
  46. template<>
  47. struct Stack<lua_CFunction>
  48. {
  49.     static void push(lua_State* L, lua_CFunction f) { lua_pushcfunction(L, f); }
  50.  
  51.     static lua_CFunction get(lua_State* L, int index) { return lua_tocfunction(L, index); }
  52.  
  53.     static bool isInstance(lua_State* L, int index) { return lua_iscfunction(L, index); }
  54. };
  55.  
  56. //------------------------------------------------------------------------------
  57. /**
  58.     Stack specialization for `int`.
  59. */
  60. template<>
  61. struct Stack<int>
  62. {
  63.     static void push(lua_State* L, int value)
  64.     {
  65.         lua_pushinteger(L, static_cast<lua_Integer>(value));
  66.     }
  67.  
  68.     static int get(lua_State* L, int index)
  69.     {
  70.         return static_cast<int>(luaL_checkinteger(L, index));
  71.     }
  72.  
  73.     static bool isInstance(lua_State* L, int index)
  74.     {
  75.         if (lua_type(L, index) != LUA_TNUMBER)
  76.         {
  77.             return false;
  78.         }
  79.  
  80. #if LUA_VERSION_NUM <= 501
  81.         return true;
  82. #else
  83.         int isNumber;
  84.         lua_tointegerx(L, index, &isNumber);
  85.         return isNumber;
  86. #endif
  87.     }
  88. };
  89.  
  90. //------------------------------------------------------------------------------
  91. /**
  92.     Stack specialization for `unsigned int`.
  93. */
  94. template<>
  95. struct Stack<unsigned int>
  96. {
  97.     static void push(lua_State* L, unsigned int value)
  98.     {
  99.         lua_pushinteger(L, static_cast<lua_Integer>(value));
  100.     }
  101.  
  102.     static unsigned int get(lua_State* L, int index)
  103.     {
  104.         return static_cast<unsigned int>(luaL_checkinteger(L, index));
  105.     }
  106.  
  107.     static bool isInstance(lua_State* L, int index) { return Stack<int>::isInstance(L, index); }
  108. };
  109.  
  110. //------------------------------------------------------------------------------
  111. /**
  112.     Stack specialization for `unsigned char`.
  113. */
  114. template<>
  115. struct Stack<unsigned char>
  116. {
  117.     static void push(lua_State* L, unsigned char value)
  118.     {
  119.         lua_pushinteger(L, static_cast<lua_Integer>(value));
  120.     }
  121.  
  122.     static unsigned char get(lua_State* L, int index)
  123.     {
  124.         return static_cast<unsigned char>(luaL_checkinteger(L, index));
  125.     }
  126.  
  127.     static bool isInstance(lua_State* L, int index) { return Stack<int>::isInstance(L, index); }
  128. };
  129.  
  130. //------------------------------------------------------------------------------
  131. /**
  132.     Stack specialization for `short`.
  133. */
  134. template<>
  135. struct Stack<short>
  136. {
  137.     static void push(lua_State* L, short value)
  138.     {
  139.         lua_pushinteger(L, static_cast<lua_Integer>(value));
  140.     }
  141.  
  142.     static short get(lua_State* L, int index)
  143.     {
  144.         return static_cast<short>(luaL_checkinteger(L, index));
  145.     }
  146.  
  147.     static bool isInstance(lua_State* L, int index) { return Stack<int>::isInstance(L, index); }
  148. };
  149.  
  150. //------------------------------------------------------------------------------
  151. /**
  152.     Stack specialization for `unsigned short`.
  153. */
  154. template<>
  155. struct Stack<unsigned short>
  156. {
  157.     static void push(lua_State* L, unsigned short value)
  158.     {
  159.         lua_pushinteger(L, static_cast<lua_Integer>(value));
  160.     }
  161.  
  162.     static unsigned short get(lua_State* L, int index)
  163.     {
  164.         return static_cast<unsigned short>(luaL_checkinteger(L, index));
  165.     }
  166.  
  167.     static bool isInstance(lua_State* L, int index) { return Stack<int>::isInstance(L, index); }
  168. };
  169.  
  170. //------------------------------------------------------------------------------
  171. /**
  172.     Stack specialization for `long`.
  173. */
  174. template<>
  175. struct Stack<long>
  176. {
  177.     static void push(lua_State* L, long value)
  178.     {
  179.         lua_pushinteger(L, static_cast<lua_Integer>(value));
  180.     }
  181.  
  182.     static long get(lua_State* L, int index)
  183.     {
  184.         return static_cast<long>(luaL_checkinteger(L, index));
  185.     }
  186.  
  187.     static bool isInstance(lua_State* L, int index) { return Stack<int>::isInstance(L, index); }
  188. };
  189.  
  190. //------------------------------------------------------------------------------
  191. /**
  192.     Stack specialization for `unsigned long`.
  193. */
  194. template<>
  195. struct Stack<unsigned long>
  196. {
  197.     static void push(lua_State* L, unsigned long value)
  198.     {
  199.         lua_pushinteger(L, static_cast<lua_Integer>(value));
  200.     }
  201.  
  202.     static unsigned long get(lua_State* L, int index)
  203.     {
  204.         return static_cast<unsigned long>(luaL_checkinteger(L, index));
  205.     }
  206.  
  207.     static bool isInstance(lua_State* L, int index) { return Stack<int>::isInstance(L, index); }
  208. };
  209.  
  210. //------------------------------------------------------------------------------
  211. /**
  212.  * Stack specialization for `long long`.
  213.  */
  214. template<>
  215. struct Stack<long long>
  216. {
  217.     static void push(lua_State* L, long long value)
  218.     {
  219.         lua_pushinteger(L, static_cast<lua_Integer>(value));
  220.     }
  221.  
  222.     static long long get(lua_State* L, int index)
  223.     {
  224.         return static_cast<long long>(luaL_checkinteger(L, index));
  225.     }
  226.  
  227.     static bool isInstance(lua_State* L, int index) { return Stack<int>::isInstance(L, index); }
  228. };
  229.  
  230. //------------------------------------------------------------------------------
  231. /**
  232.  * Stack specialization for `unsigned long long`.
  233.  */
  234. template<>
  235. struct Stack<unsigned long long>
  236. {
  237.     static void push(lua_State* L, unsigned long long value)
  238.     {
  239.         lua_pushinteger(L, static_cast<lua_Integer>(value));
  240.     }
  241.     static unsigned long long get(lua_State* L, int index)
  242.     {
  243.         return static_cast<unsigned long long>(luaL_checkinteger(L, index));
  244.     }
  245.  
  246.     static bool isInstance(lua_State* L, int index) { return Stack<int>::isInstance(L, index); }
  247. };
  248.  
  249. //------------------------------------------------------------------------------
  250. /**
  251.     Stack specialization for `float`.
  252. */
  253. template<>
  254. struct Stack<float>
  255. {
  256.     static void push(lua_State* L, float value)
  257.     {
  258.         lua_pushnumber(L, static_cast<lua_Number>(value));
  259.     }
  260.  
  261.     static float get(lua_State* L, int index)
  262.     {
  263.         return static_cast<float>(luaL_checknumber(L, index));
  264.     }
  265.  
  266.     static bool isInstance(lua_State* L, int index) { return lua_type(L, index) == LUA_TNUMBER; }
  267. };
  268.  
  269. //------------------------------------------------------------------------------
  270. /**
  271.     Stack specialization for `double`.
  272. */
  273. template<>
  274. struct Stack<double>
  275. {
  276.     static void push(lua_State* L, double value)
  277.     {
  278.         lua_pushnumber(L, static_cast<lua_Number>(value));
  279.     }
  280.  
  281.     static double get(lua_State* L, int index)
  282.     {
  283.         return static_cast<double>(luaL_checknumber(L, index));
  284.     }
  285.  
  286.     static bool isInstance(lua_State* L, int index) { return lua_type(L, index) == LUA_TNUMBER; }
  287. };
  288.  
  289. //------------------------------------------------------------------------------
  290. /**
  291.     Stack specialization for `bool`.
  292. */
  293. template<>
  294. struct Stack<bool>
  295. {
  296.     static void push(lua_State* L, bool value) { lua_pushboolean(L, value ? 1 : 0); }
  297.  
  298.     static bool get(lua_State* L, int index) { return lua_toboolean(L, index) ? true : false; }
  299.  
  300.     static bool isInstance(lua_State* L, int index) { return lua_isboolean(L, index); }
  301. };
  302.  
  303. //------------------------------------------------------------------------------
  304. /**
  305.     Stack specialization for `char`.
  306. */
  307. template<>
  308. struct Stack<char>
  309. {
  310.     static void push(lua_State* L, char value) { lua_pushlstring(L, &value, 1); }
  311.  
  312.     static char get(lua_State* L, int index) { return luaL_checkstring(L, index)[0]; }
  313.  
  314.     static bool isInstance(lua_State* L, int index) { return lua_type(L, index) == LUA_TSTRING; }
  315. };
  316.  
  317. //------------------------------------------------------------------------------
  318. /**
  319.     Stack specialization for `const char*`.
  320. */
  321. template<>
  322. struct Stack<char const*>
  323. {
  324.     static void push(lua_State* L, char const* str)
  325.     {
  326.         if (str != 0)
  327.             lua_pushstring(L, str);
  328.         else
  329.             lua_pushnil(L);
  330.     }
  331.  
  332.     static char const* get(lua_State* L, int index)
  333.     {
  334.         return lua_isnil(L, index) ? 0 : luaL_checkstring(L, index);
  335.     }
  336.  
  337.     static bool isInstance(lua_State* L, int index)
  338.     {
  339.         return lua_isnil(L, index) || lua_type(L, index) == LUA_TSTRING;
  340.     }
  341. };
  342.  
  343. //------------------------------------------------------------------------------
  344. /**
  345.     Stack specialization for `std::string`.
  346. */
  347. template<>
  348. struct Stack<std::string>
  349. {
  350.     static void push(lua_State* L, std::string const& str)
  351.     {
  352.         lua_pushlstring(L, str.data(), str.size());
  353.     }
  354.  
  355.     static std::string get(lua_State* L, int index)
  356.     {
  357.         size_t len;
  358.         if (lua_type(L, index) == LUA_TSTRING)
  359.         {
  360.             const char* str = lua_tolstring(L, index, &len);
  361.             return std::string(str, len);
  362.         }
  363.  
  364.         // Lua reference manual:
  365.         // If the value is a number, then lua_tolstring also changes the actual value in the stack
  366.         // to a string. (This change confuses lua_next when lua_tolstring is applied to keys during
  367.         // a table traversal.)
  368.         lua_pushvalue(L, index);
  369.         const char* str = lua_tolstring(L, -1, &len);
  370.         std::string string(str, len);
  371.         lua_pop(L, 1); // Pop the temporary string
  372.         return string;
  373.     }
  374.  
  375.     static bool isInstance(lua_State* L, int index) { return lua_type(L, index) == LUA_TSTRING; }
  376. };
  377.  
  378. #ifdef LUABRIDGE_CXX17
  379.  
  380. //------------------------------------------------------------------------------
  381. /**
  382.     Stack specialization for `std::string`.
  383. */
  384. template<>
  385. struct Stack<std::string_view>
  386. {
  387.     static void push(lua_State* L, std::string_view str)
  388.     {
  389.         lua_pushlstring(L, str.data(), str.size());
  390.     }
  391.  
  392.     static std::string_view get(lua_State* L, int index)
  393.     {
  394.         size_t len;
  395.         if (lua_type(L, index) == LUA_TSTRING)
  396.         {
  397.             const char* str = lua_tolstring(L, index, &len);
  398.             return std::string_view(str, len);
  399.         }
  400.  
  401.         return {};
  402.     }
  403.  
  404.     static bool isInstance(lua_State* L, int index) { return lua_type(L, index) == LUA_TSTRING; }
  405. };
  406.  
  407. #endif // LUABRIDGE_CXX17
  408.  
  409. namespace detail {
  410.  
  411. template<class T>
  412. struct StackOpSelector<T&, false>
  413. {
  414.     typedef T ReturnType;
  415.  
  416.     static void push(lua_State* L, T& value) { Stack<T>::push(L, value); }
  417.  
  418.     static ReturnType get(lua_State* L, int index) { return Stack<T>::get(L, index); }
  419.  
  420.     static bool isInstance(lua_State* L, int index) { return Stack<T>::isInstance(L, index); }
  421. };
  422.  
  423. template<class T>
  424. struct StackOpSelector<const T&, false>
  425. {
  426.     typedef T ReturnType;
  427.  
  428.     static void push(lua_State* L, const T& value) { Stack<T>::push(L, value); }
  429.  
  430.     static ReturnType get(lua_State* L, int index) { return Stack<T>::get(L, index); }
  431.  
  432.     static bool isInstance(lua_State* L, int index) { return Stack<T>::isInstance(L, index); }
  433. };
  434.  
  435. template<class T>
  436. struct StackOpSelector<T*, false>
  437. {
  438.     typedef T ReturnType;
  439.  
  440.     static void push(lua_State* L, T* value) { Stack<T>::push(L, *value); }
  441.  
  442.     static ReturnType get(lua_State* L, int index) { return Stack<T>::get(L, index); }
  443.  
  444.     static bool isInstance(lua_State* L, int index) { return Stack<T>::isInstance(L, index); }
  445. };
  446.  
  447. template<class T>
  448. struct StackOpSelector<const T*, false>
  449. {
  450.     typedef T ReturnType;
  451.  
  452.     static void push(lua_State* L, const T* value) { Stack<T>::push(L, *value); }
  453.  
  454.     static ReturnType get(lua_State* L, int index) { return Stack<T>::get(L, index); }
  455.  
  456.     static bool isInstance(lua_State* L, int index) { return Stack<T>::isInstance(L, index); }
  457. };
  458.  
  459. } // namespace detail
  460.  
  461. template<class T>
  462. struct Stack<T&>
  463. {
  464.     typedef detail::StackOpSelector<T&, detail::IsUserdata<T>::value> Helper;
  465.     typedef typename Helper::ReturnType ReturnType;
  466.  
  467.     static void push(lua_State* L, T& value) { Helper::push(L, value); }
  468.  
  469.     static ReturnType get(lua_State* L, int index) { return Helper::get(L, index); }
  470. };
  471.  
  472. template<class T>
  473. struct Stack<const T&>
  474. {
  475.     typedef detail::StackOpSelector<const T&, detail::IsUserdata<T>::value> Helper;
  476.     typedef typename Helper::ReturnType ReturnType;
  477.  
  478.     static void push(lua_State* L, const T& value) { Helper::push(L, value); }
  479.  
  480.     static ReturnType get(lua_State* L, int index) { return Helper::get(L, index); }
  481. };
  482.  
  483. template<class T>
  484. struct Stack<T*>
  485. {
  486.     typedef detail::StackOpSelector<T*, detail::IsUserdata<T>::value> Helper;
  487.     typedef typename Helper::ReturnType ReturnType;
  488.  
  489.     static void push(lua_State* L, T* value) { Helper::push(L, value); }
  490.  
  491.     static ReturnType get(lua_State* L, int index) { return Helper::get(L, index); }
  492. };
  493.  
  494. template<class T>
  495. struct Stack<const T*>
  496. {
  497.     typedef detail::StackOpSelector<const T*, detail::IsUserdata<T>::value> Helper;
  498.     typedef typename Helper::ReturnType ReturnType;
  499.  
  500.     static void push(lua_State* L, const T* value) { Helper::push(L, value); }
  501.  
  502.     static ReturnType get(lua_State* L, int index) { return Helper::get(L, index); }
  503. };
  504.  
  505. //------------------------------------------------------------------------------
  506. /**
  507.  * Push an object onto the Lua stack.
  508.  */
  509. template<class T>
  510. void push(lua_State* L, T t)
  511. {
  512.     Stack<T>::push(L, t);
  513. }
  514.  
  515. //------------------------------------------------------------------------------
  516. /**
  517.  * Get an object from the Lua stack.
  518.  */
  519. template<class T>
  520. T get(lua_State* L, int index)
  521. {
  522.     return Stack<T>::get(L, index);
  523. }
  524.  
  525. //------------------------------------------------------------------------------
  526. /**
  527.  * Check whether an object on the Lua stack is of type T.
  528.  */
  529. template<class T>
  530. bool isInstance(lua_State* L, int index)
  531. {
  532.     return Stack<T>::isInstance(L, index);
  533. }
  534.  
  535. } // namespace luabridge
  536.