Files
fs2open.github.com/code/scripting/lua/LuaTable.h
T
asarium ad1ede7b74 Add new options system
This is a system for storing arbitrary data in the config file and then
easily retrieving it later on. This has full Lua support for exposing
the available options in a custom UI and changing the values of the
options. This ported some of the existing command line options over to
the new system which is opt-in for the moment by using a mod_table flag.
2019-03-02 14:02:21 +01:00

241 lines
5.7 KiB
C++

#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();
/**
* @brief Copy-constructor
* @param other The other table.
*/
LuaTable(const LuaTable& other);
/**
* 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();
// 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) {
this->pushValue();
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) {
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();
/**
* @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();
/**
* @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();
};
namespace convert {
bool popValue(lua_State* luaState, LuaTable& target, int stackposition = -1, bool remove = true);
}
}
#endif