Skip to content

Commit

Permalink
Merge pull request #10 from peacalm/dev
Browse files Browse the repository at this point in the history
add param exists
  • Loading branch information
peacalm committed Apr 23, 2023
2 parents a015a4c + c8bef41 commit 5df9e71
Showing 1 changed file with 85 additions and 46 deletions.
131 changes: 85 additions & 46 deletions include/peacalm/lua_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -317,14 +317,14 @@ class lua_wrapper {
// clang-format on

// clang-format off
int isfunction(int idx) { return lua_isfunction(L_, idx); }
int istable(int idx) { return lua_istable(L_, idx); }
int islightuserdata(int idx) { return lua_islightuserdata(L_, idx); }
int isnil(int idx) { return lua_isnil(L_, idx); }
int isboolean(int idx) { return lua_isboolean(L_, idx); }
int isthread(int idx) { return lua_isthread(L_, idx); }
int isnone(int idx) { return lua_isnone(L_, idx); }
int isnoneornil(int idx) { return lua_isnoneornil(L_, idx); }
bool isfunction(int idx = -1) { return lua_isfunction(L_, idx); }
bool istable(int idx = -1) { return lua_istable(L_, idx); }
bool islightuserdata(int idx = -1) { return lua_islightuserdata(L_, idx); }
bool isnil(int idx = -1) { return lua_isnil(L_, idx); }
bool isboolean(int idx = -1) { return lua_isboolean(L_, idx); }
bool isthread(int idx = -1) { return lua_isthread(L_, idx); }
bool isnone(int idx = -1) { return lua_isnone(L_, idx); }
bool isnoneornil(int idx = -1) { return lua_isnoneornil(L_, idx); }
// clang-format on

int getglobal(const char* name) { return lua_getglobal(L_, name); }
Expand Down Expand Up @@ -372,6 +372,8 @@ class lua_wrapper {
* @param [in] enable_log Whether print a log when exception occurs
* @param [out] failed Will be set whether the convertion is failed if this
* pointer is not nullptr
* @param [out] exists Set whether the value at given index exists. Regard
* none and nil as not exists.
*
* @{
*/
Expand All @@ -380,7 +382,9 @@ class lua_wrapper {
type to_##typename(int idx = -1, \
type def = default, \
bool enable_log = true, \
bool* failed = nullptr) { \
bool* failed = nullptr, \
bool* exists = nullptr) { \
if (exists) *exists = !isnoneornil(idx); \
/* check integer before number to avoid precision lost. */ \
if (lua_isinteger(L_, idx)) { \
if (failed) *failed = false; \
Expand Down Expand Up @@ -421,7 +425,9 @@ class lua_wrapper {
const char* to_c_str(int idx = -1,
const char* def = "",
bool enable_log = true,
bool* failed = nullptr) {
bool* failed = nullptr,
bool* exists = nullptr) {
if (exists) *exists = !isnoneornil(idx);
if (lua_isstring(L_, idx)) { // include number
if (failed) *failed = false;
return lua_tostring(L_, idx);
Expand All @@ -438,8 +444,9 @@ class lua_wrapper {
std::string to_string(int idx = -1,
const std::string& def = "",
bool enable_log = true,
bool* failed = nullptr) {
return std::string{to_c_str(idx, def.c_str(), enable_log, failed)};
bool* failed = nullptr,
bool* exists = nullptr) {
return std::string{to_c_str(idx, def.c_str(), enable_log, failed, exists)};
}

/** @}*/
Expand All @@ -455,6 +462,8 @@ class lua_wrapper {
* @param [out] failed Will be set whether the operation is failed if this
* pointer is not nullptr. If T is a container type, it regards the operation
* as failed if any element converts failed
* @param [out] exists Set whether the value at given index exists. Regard
* none and nil as not exists.
* @return Return the value on given index in type T if conversion succeeded,
* otherwise return initial value of T(i.e. by statement `T{}`) if T is a
* simple type, e.g. bool, int, double, std::string, etc. If T is a container
Expand All @@ -475,15 +484,22 @@ class lua_wrapper {
std::is_same<T, unsigned long long>::value ||
std::is_same<T, double>::value || std::is_same<T, std::string>::value,
T>
to(int idx = -1, bool enable_log = true, bool* failed = nullptr);
to(int idx = -1,
bool enable_log = true,
bool* failed = nullptr,
bool* exists = nullptr);

// to std::vector
template <typename T>
std::enable_if_t<std::is_same<T,
std::vector<typename T::value_type,
typename T::allocator_type>>::value,
T>
to(int idx = -1, bool enable_log = true, bool* failed = nullptr) {
to(int idx = -1,
bool enable_log = true,
bool* failed = nullptr,
bool* exists = nullptr) {
if (exists) *exists = !isnoneornil(-1);
T ret;
if (!lua_istable(L_, idx)) {
if (failed) *failed = true;
Expand Down Expand Up @@ -511,8 +527,11 @@ class lua_wrapper {
typename T::key_compare,
typename T::allocator_type>>::value,
T>
to(int idx = -1, bool enable_log = true, bool* failed = nullptr) {
return tom<T>(idx, enable_log, failed, "map");
to(int idx = -1,
bool enable_log = true,
bool* failed = nullptr,
bool* exists = nullptr) {
return tom<T>(idx, enable_log, failed, exists, "map");
}

// To std::unordered_map
Expand All @@ -525,16 +544,21 @@ class lua_wrapper {
typename T::key_equal,
typename T::allocator_type>>::value,
T>
to(int idx = -1, bool enable_log = true, bool* failed = nullptr) {
return tom<T>(idx, enable_log, failed, "unordered_map");
to(int idx = -1,
bool enable_log = true,
bool* failed = nullptr,
bool* exists = nullptr) {
return tom<T>(idx, enable_log, failed, exists, "unordered_map");
}

// Implementation of to map or to unordered_map
template <typename T>
T tom(int idx = -1,
bool enable_log = true,
bool* failed = nullptr,
bool* exists = nullptr,
const char* tname = "map") {
if (exists) *exists = !isnoneornil(-1);
T ret;
if (!lua_istable(L_, idx)) {
if (failed) *failed = true;
Expand Down Expand Up @@ -617,25 +641,29 @@ class lua_wrapper {
* @param [out] failed Will be set whether the operation is failed if this
* pointer is not nullptr. If T is a container type, it regards the operation
* as failed if any element converts failed
* @param [out] exists Set whether the variable exists. Regard none and nil as
* not exists.
*
* @{
*/

#define DEFINE_GLOBAL_GET(typename, type, default) \
type get_##typename(const char* name, \
const type& def = default, \
bool enable_log = true, \
bool* failed = nullptr) { \
lua_getglobal(L_, name); \
type ret = to_##typename(-1, def, enable_log, failed); \
pop(); \
return ret; \
} \
type get_##typename(const std::string& name, \
const type& def = default, \
bool enable_log = true, \
bool* failed = nullptr) { \
return get_##typename(name.c_str(), def, enable_log, failed); \
#define DEFINE_GLOBAL_GET(typename, type, default) \
type get_##typename(const char* name, \
const type& def = default, \
bool enable_log = true, \
bool* failed = nullptr, \
bool* exists = nullptr) { \
lua_getglobal(L_, name); \
type ret = to_##typename(-1, def, enable_log, failed, exists); \
pop(); \
return ret; \
} \
type get_##typename(const std::string& name, \
const type& def = default, \
bool enable_log = true, \
bool* failed = nullptr, \
bool* exists = nullptr) { \
return get_##typename(name.c_str(), def, enable_log, failed, exists); \
}

DEFINE_GLOBAL_GET(int, int, 0)
Expand All @@ -654,15 +682,17 @@ class lua_wrapper {
const char* get_c_str(const char* name,
const char* def = "",
bool enable_log = true,
bool* failed = nullptr) {
bool* failed = nullptr,
bool* exists = nullptr) {
lua_getglobal(L_, name);
return to_c_str(-1, def, enable_log, failed);
return to_c_str(-1, def, enable_log, failed, exists);
}
const char* get_c_str(const std::string& name,
const char* def = "",
bool enable_log = true,
bool* failed = nullptr) {
return get_c_str(name.c_str(), def, enable_log, failed);
bool* failed = nullptr,
bool* exists = nullptr) {
return get_c_str(name.c_str(), def, enable_log, failed, exists);
}

/** @}*/
Expand All @@ -678,20 +708,26 @@ class lua_wrapper {
* @param [out] failed Will be set whether the operation is failed if this
* pointer is not nullptr. If T is a container type, it regards the operation
* as failed if any element converts failed
* @param [out] exists Set whether the variable exists. Regard none and nil as
* not exists.
* @return The variable's value in type T
*/
template <typename T>
T get(const char* name, bool enable_log = true, bool* failed = nullptr) {
T get(const char* name,
bool enable_log = true,
bool* failed = nullptr,
bool* exists = nullptr) {
getglobal(name);
auto ret = to<T>(-1, enable_log, failed);
auto ret = to<T>(-1, enable_log, failed, exists);
pop();
return ret;
}
template <typename T>
T get(const std::string& name,
bool enable_log = true,
bool* failed = nullptr) {
return get<T>(name.c_str(), enable_log, failed);
bool* failed = nullptr,
bool* exists = nullptr) {
return get<T>(name.c_str(), enable_log, failed, exists);
}

//////////////////////// evaluate expression /////////////////////////////////
Expand Down Expand Up @@ -842,10 +878,11 @@ class lua_wrapper {
}
};

#define DEFINE_TO_SPECIALIZATIOIN(typename, type, default) \
template <> \
type lua_wrapper::to<type>(int idx, bool enable_log, bool* failed) { \
return to_##typename(idx, default, enable_log, failed); \
#define DEFINE_TO_SPECIALIZATIOIN(typename, type, default) \
template <> \
type lua_wrapper::to<type>( \
int idx, bool enable_log, bool* failed, bool* exists) { \
return to_##typename(idx, default, enable_log, failed, exists); \
}

DEFINE_TO_SPECIALIZATIOIN(bool, bool, false)
Expand All @@ -864,7 +901,9 @@ DEFINE_TO_SPECIALIZATIOIN(double, double, false)
template <>
std::string lua_wrapper::to<std::string>(int idx,
bool enable_log,
bool* failed) {
bool* failed,
bool* exists) {
if (exists) *exists = !isnoneornil(idx);
if (lua_isstring(L_, idx)) {
lua_pushvalue(L_, idx); // make a copy, so, it's safe
std::string ret = lua_tostring(L_, -1);
Expand Down

0 comments on commit 5df9e71

Please sign in to comment.