mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-08 17:48:46 -10:00
242 lines
5.2 KiB
C++
242 lines
5.2 KiB
C++
|
|
#ifndef LUAVALUE_H
|
|
#define LUAVALUE_H
|
|
#pragma once
|
|
|
|
#include "LuaConvert.h"
|
|
#include "LuaReference.h"
|
|
#include "LuaException.h"
|
|
|
|
#include "LuaHeaders.h"
|
|
|
|
#include <memory>
|
|
|
|
#include <cstdint>
|
|
#include <csetjmp>
|
|
|
|
namespace luacpp {
|
|
/**
|
|
* @brief The values of a LuaValue
|
|
*/
|
|
enum class ValueType {
|
|
NONE,
|
|
NIL,
|
|
BOOLEAN,
|
|
LIGHTUSERDATA,
|
|
STRING,
|
|
NUMBER,
|
|
TABLE,
|
|
FUNCTION,
|
|
USERDATA,
|
|
THREAD
|
|
};
|
|
|
|
/**
|
|
* @brief Represents a Lua-value
|
|
*
|
|
* This class holds a reference to a lua value and provides type checking to ensure that the value is still the same.
|
|
*/
|
|
class LuaValue {
|
|
public:
|
|
/**
|
|
* @brief Creates a LuaValue.
|
|
* This is done by pushing the value onto the lua stack and creating a reference to it.
|
|
*
|
|
* @param state The lua state
|
|
* @param value The value to be referenced
|
|
* @return luacpp::LuaValue A new LuaValue instance which references the specified value
|
|
*/
|
|
template<class ValueType>
|
|
static LuaValue createValue(lua_State* state, const ValueType& value) {
|
|
LuaValue retVal(state);
|
|
|
|
convert::pushValue(state, value);
|
|
|
|
retVal.setReference(UniqueLuaReference::create(state));
|
|
|
|
// Remove the value again
|
|
lua_pop(state, 1);
|
|
|
|
return retVal;
|
|
}
|
|
|
|
static LuaValue createNil(lua_State* L);
|
|
|
|
/**
|
|
* @brief Default constructor, creates an invalid LuaValue
|
|
*/
|
|
LuaValue() : _luaState(nullptr), _luaType(ValueType::NONE) {}
|
|
|
|
/**
|
|
* @brief Initializes the lua value
|
|
*
|
|
* The instance does not point to a lua-value after the constructor has finished. To reference
|
|
* a value use #setReference(LuaReferencePtr)
|
|
*
|
|
* @param state The lua state
|
|
*/
|
|
LuaValue(lua_State* state);
|
|
|
|
/**
|
|
* @brief Copy-constructor
|
|
* @param other The other LuaValue.
|
|
*/
|
|
LuaValue(const LuaValue& other);
|
|
|
|
/**
|
|
* @brief Releases the reference
|
|
*/
|
|
virtual ~LuaValue();
|
|
|
|
/**
|
|
* @brief Sets a new LuaReference.
|
|
*
|
|
* @param ref The new lua reference.
|
|
*/
|
|
virtual void setReference(const LuaReference& ref);
|
|
|
|
/**
|
|
* @brief Gets the LuaReference.
|
|
*
|
|
* This reference is used to reference the actual lua value.
|
|
*
|
|
* @return The LuaReference instance.
|
|
*/
|
|
virtual const LuaReference getReference() const;
|
|
|
|
/**
|
|
* @brief Gets the lua type of this value.
|
|
* @return One of the LUA_T* defines.
|
|
*/
|
|
virtual ValueType getValueType() const;
|
|
|
|
/**
|
|
* @brief Checks if the value is of the specified type.
|
|
*
|
|
* @return bool @c true when it is, @c false if it isn't.
|
|
*/
|
|
inline bool is(ValueType check) const { return _luaType == check; }
|
|
|
|
/**
|
|
* @brief Sets a new value, possible changing the type
|
|
*
|
|
* @param value The new value
|
|
*/
|
|
template<class Type>
|
|
void setValue(const Type& value) {
|
|
// Push the new value
|
|
convert::pushValue(_luaState, value);
|
|
|
|
// And create a reference for it
|
|
setReference(UniqueLuaReference::create(_luaState));
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the value or throws an exception
|
|
*
|
|
* @return Type The value
|
|
*
|
|
* @exception LuaException Thrown when the conversion failed.
|
|
*/
|
|
template<class Type>
|
|
Type getValue() const {
|
|
_reference->pushValue();
|
|
|
|
Type target;
|
|
if (!convert::popValue(_luaState, target)) {
|
|
lua_pop(_luaState, 1);
|
|
throw LuaException("Failed to pop value");
|
|
} else {
|
|
return target;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Specifies if the lua value is valid.
|
|
*
|
|
* @return bool @c true if it can be used and have an underlying reference, @c false otherwise.
|
|
*/
|
|
bool isValid() const;
|
|
|
|
/**
|
|
* @brief Pushes this lua value onto the stack.
|
|
*/
|
|
virtual bool pushValue() const;
|
|
|
|
lua_State* getLuaState() const;
|
|
protected:
|
|
lua_State* _luaState; //!< The lua state of this value.
|
|
|
|
LuaReference _reference;
|
|
|
|
ValueType _luaType;
|
|
};
|
|
|
|
/**
|
|
* @brief Checks for equality of the lua values.
|
|
* @param lhs The left value
|
|
* @param rhs The right lua value.
|
|
* @return `true` when the value are equal as specified by the lua "==" operator.
|
|
*/
|
|
template<typename Type>
|
|
bool operator==(const LuaValue& lhs, const Type& rhs) {
|
|
lhs.pushValue();
|
|
convert::pushValue(lhs.getLuaState(), rhs);
|
|
|
|
bool result = lua_equal(lhs.getLuaState(), -2, -1) != 0;
|
|
|
|
lua_pop(lhs.getLuaState(), 2);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @brief Checks if the other value is bigger than this value.
|
|
* @param lhs The left lua value.
|
|
* @param rhs The right lua value.
|
|
* @return `true` when the second value is bigger than this value as specified
|
|
* by lua.
|
|
*/
|
|
template<typename Type>
|
|
bool operator<(const LuaValue& lhs, const Type& rhs) {
|
|
lhs.pushValue();
|
|
convert::pushValue(lhs.getLuaState(), rhs);
|
|
|
|
bool result = lua_lessthan(lhs.getLuaState(), -2, -1) != 0;
|
|
|
|
lua_pop(lhs.getLuaState(), 2);
|
|
|
|
return result;
|
|
}
|
|
|
|
template<typename Type>
|
|
bool operator!=(const LuaValue& lhs, const Type& rhs) {
|
|
return !(lhs == rhs);
|
|
}
|
|
|
|
template<typename Type>
|
|
bool operator>(const LuaValue& lhs, const Type& rhs) {
|
|
return !(lhs <= rhs);
|
|
}
|
|
|
|
template<typename Type>
|
|
bool operator<=(const LuaValue& lhs, const Type& rhs) {
|
|
return (lhs == rhs) || (lhs < rhs);
|
|
}
|
|
|
|
template<typename Type>
|
|
bool operator>=(const LuaValue& lhs, const Type& rhs) {
|
|
return !(lhs < rhs);
|
|
}
|
|
|
|
namespace convert {
|
|
|
|
void pushValue(lua_State* luaState, const LuaValue& value);
|
|
|
|
bool popValue(lua_State* luaState, LuaValue& target, int stackposition = -1, bool remove = true);
|
|
|
|
}
|
|
}
|
|
|
|
#endif
|