1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
|
#ifndef LUATABLE_H
#define LUATABLE_H
#pragma once
#include "LuaConvert.h"
#include "LuaValue.h"
#include <iterator>
namespace luacpp {
class LuaTable;
/**
* @brief Utility class for iterating over the contents of a lua table
*
* The elements are returned as key-value pairs of the table
*
* @warning Never manipulate the lua stack while using an instance of this class! It's ok to change the stack but it must
* be in the exact same state when you call the next method of this class.
*/
class LuaTableIterator {
lua_State* _luaState = nullptr;
int _stackTop = 0;
bool _hasElement = false;
std::pair<LuaValue, LuaValue> _currentVal;
public:
/**
* @brief Initializes the iterator with a table
* @param t The table to iterate iver
*/
explicit LuaTableIterator(const LuaTable& t);
~LuaTableIterator();
LuaTableIterator(const LuaTableIterator&) = delete;
LuaTableIterator& operator=(const LuaTableIterator&) = delete;
/**
* @brief Test if there is a valid element
* @return @c true if there is a value, @c false otherwise
*/
bool hasElement();
/**
* @brief Advances the iterator to the next element
*/
void toNextElement();
/**
* @brief Gets the key-value pair of the current element
* @return The key-value pair
*/
std::pair<LuaValue, LuaValue> getElement();
};
/**
* @brief Class to improve handling of lua tables.
*
* This class provides a high-level interface to lua tables without the need to directly call
* lua-API functions.
*
* @see LuaConvert
*/
class LuaTable: public LuaValue {
public:
/**
* @brief STL adaptor for LuaTableIterator
*
* This wraps a shared pointer to an iterator so that this class can be copied like the iterator interface expects
*/
class iterator: public std::iterator<std::input_iterator_tag, std::pair<LuaValue, LuaValue>> {
public:
explicit iterator(const LuaTable& _parent);
iterator();
bool operator==(const iterator& other);
bool operator!=(const iterator& other);
iterator& operator++();
iterator& operator++(int);
std::pair<LuaValue, LuaValue> operator*();
private:
std::shared_ptr<LuaTableIterator> _iter;
bool _atEnd = false;
};
typedef iterator iterator_type;
/**
* @brief Creates a new empty table.
*/
static LuaTable create(lua_State* state);
/**
* @brief Default constructor
*/
LuaTable();
/**
* Dereferences the stored reference to the table if it exists.
*/
~LuaTable() override;
/**
* @brief Sets the metatable.
*
* The given table will be set as the metatable of this table.
*
* @param ref The new metatable.
* @return Always `true`.
*/
bool setMetatable(const LuaTable& ref);
/**
* @brief Sets a new reference.
* This overload checks if the passed reference is a table
*
* @param ref The new reference
* @return void
*/
void setReference(const LuaReference& ref) override;
/**
* @brief Adds a value to this lua table.
*
* @param index The index value to use.
* @param value The value to set at the index.
*/
template<class IndexType, class ValueType>
void addValue(IndexType&& index, ValueType&& value) {
// Push the table onto the stack by using the reference
this->pushValue(_luaState);
// Push the index and value onto the stac by using the template functions
convert::pushValue(_luaState, std::forward<IndexType>(index));
convert::pushValue(_luaState, std::forward<ValueType>(value));
// Set the value in the table
lua_settable(_luaState, -3);
// And pop the table again
lua_pop(_luaState, 1);
}
/**
* @brief Retrieves a value from the table.
*
* @param index The index where the value is located.
* @param target The target location where the value should be stored.
* @return @c true when the value could be successfully converted, @c false otherwise
*/
template<class IndexType, class ValueType>
bool getValue(const IndexType& index, ValueType& target) const {
this->pushValue(_luaState);
convert::pushValue(_luaState, index);
lua_gettable(_luaState, -2);
bool ret = convert::popValue(_luaState, target);
if (!ret) {
lua_pop(_luaState, 1);
}
lua_pop(_luaState, 1);
return ret;
}
/**
* @brief Gets a value or throws an exception.
* This function gets the specified value from the table and returns it
* or throws an exception if that faild
*
* @param index The index of the value to retrieve
* @return luacpp::ValueType The value
*
* @exception LuaException Thrown when an error occurs while converting the value
*/
template<class ValueType, class IndexType>
// IndexType is last so the compiler can deduce it from the argument
ValueType getValue(const IndexType& index) const {
ValueType target;
if (!getValue(index, target)) {
throw LuaException("Failed to get lua value!");
} else {
return target;
}
}
/**
* @brief Gets the length of the table.
*
* Gets size of the table (the same as using the '#' operator in Lua).
*
* @return The size value.
*/
size_t getLength() const;
/**
* @brief Returns an iterator to the begin of this table
*
* This can be used with STL algorithms or with the C++11 range-base-for-loop
*
* @warning Never manipulate the lua stack while using this iterator!
*
* @return The iterator to the begin of the table
*/
iterator begin() const;
/**
* @brief Returns an iterator to the end of this table
*
* This can be used with STL algorithms or with the C++11 range-base-for-loop
*
* @return The iterator to the end of the table
*/
iterator end() const;
};
namespace convert {
bool popValue(lua_State* luaState, LuaTable& target, int stackposition = -1, bool remove = true);
}
}
#endif
|