1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-02-07 21:37:14 +01:00
SqMod/include/sqrat/sqratUtil.h
Sandu Liviu Catalin 0137dfc66f Move the plugin Squirrel utilities to the Sqrat binding utility.
Implement registration of functions and methods with string formatting support in the Sqrat binding utility.
Few minor other fixes.
2016-11-16 11:54:07 +02:00

1637 lines
62 KiB
C++

//
// SqratUtil: Squirrel Utilities
//
//
// Copyright (c) 2009 Brandon Jones
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
#if !defined(_SCRAT_UTIL_H_)
#define _SCRAT_UTIL_H_
#ifdef SQMOD_PLUGIN_API
#include <SqAPI.h>
#else
#include <squirrel.h>
#include <sqstdstring.h>
#endif // SQMOD_PLUGIN_API
#include <cassert>
#include <map>
#include <string.h>
#if defined(SCRAT_USE_CXX11_OPTIMIZATIONS)
#include <unordered_map>
#endif
namespace Sqrat {
/// @cond DEV
#if defined(SCRAT_USE_CXX11_OPTIMIZATIONS)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Define an unordered map for Sqrat to use based on whether SCRAT_USE_CXX11_OPTIMIZATIONS is defined or not
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Key, class T>
struct unordered_map {
typedef std::unordered_map<Key, T> type;
};
#else
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Define an unordered map for Sqrat to use based on whether SCRAT_USE_CXX11_OPTIMIZATIONS is defined or not
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Key, class T>
struct unordered_map {
typedef std::map<Key, T> type;
};
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Define an inline function to avoid MSVC's "conditional expression is constant" warning
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
template <typename T>
inline T _c_def(T value) { return value; }
#define SQRAT_CONST_CONDITION(value) _c_def(value)
#else
#define SQRAT_CONST_CONDITION(value) value
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Define helpers to create portable import / export macros
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if defined(SCRAT_EXPORT)
#if defined(_WIN32)
// Windows compilers need a specific keyword for export
#define SQRAT_API __declspec(dllexport)
#else
#if __GNUC__ >= 4
// GCC 4 has special keywords for showing/hiding symbols,
// the same keyword is used for both importing and exporting
#define SQRAT_API __attribute__ ((__visibility__ ("default")))
#else
// GCC < 4 has no mechanism to explicitly hide symbols, everything's exported
#define SQRAT_API
#endif
#endif
#elif defined(SCRAT_IMPORT)
#if defined(_WIN32)
// Windows compilers need a specific keyword for import
#define SQRAT_API __declspec(dllimport)
#else
#if __GNUC__ >= 4
// GCC 4 has special keywords for showing/hiding symbols,
// the same keyword is used for both importing and exporting
#define SQRAT_API __attribute__ ((__visibility__ ("default")))
#else
// GCC < 4 has no mechanism to explicitly hide symbols, everything's exported
#define SQRAT_API
#endif
#endif
#else
#define SQRAT_API
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Define macros for internal error handling
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if defined (SCRAT_NO_ERROR_CHECKING)
#define SQCATCH(vm) if (SQRAT_CONST_CONDITION(false))
#define SQCATCH_NOEXCEPT(vm) if (SQRAT_CONST_CONDITION(false))
#define SQCLEAR(vm)
#define SQRETHROW(vm)
#define SQTHROW(vm, err)
#define SQTRY()
#define SQWHAT(vm) _SC("")
#define SQWHAT_NOEXCEPT(vm) _SC("")
#elif defined (SCRAT_USE_EXCEPTIONS)
#define SQCATCH(vm) } catch (const Sqrat::Exception& e)
#define SQCATCH_NOEXCEPT(vm) if (SQRAT_CONST_CONDITION(false))
#define SQCLEAR(vm)
#ifdef _MSC_VER // avoid MSVC's "unreachable code" warning
#define SQRETHROW(vm) if (SQRAT_CONST_CONDITION(true)) throw
#define SQTHROW(vm, err) if (SQRAT_CONST_CONDITION(true)) throw Sqrat::Exception(err)
#else
#define SQRETHROW(vm) throw
#define SQTHROW(vm, err) throw Sqrat::Exception(err)
#endif
#define SQTRY() try {
#define SQWHAT(vm) e.Message().c_str()
#define SQWHAT_NOEXCEPT(vm) _SC("")
#else
#define SQCATCH(vm) if (SQRAT_CONST_CONDITION(false))
#define SQCATCH_NOEXCEPT(vm) if (Error::Occurred(vm))
#define SQCLEAR(vm) Error::Clear(vm)
#define SQRETHROW(vm)
#define SQTHROW(vm, err) Error::Throw(vm, err)
#define SQTRY()
#define SQWHAT(vm) _SC("")
#define SQWHAT_NOEXCEPT(vm) Error::Message(vm).c_str()
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Removes unused variable warnings in a way that Doxygen can understand
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
void SQUNUSED(const T&) {
}
/// @endcond
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Defines a string that is definitely compatible with the version of Squirrel being used (normally this is std::string)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef std::basic_string<SQChar> string;
/// @cond DEV
#ifdef SQUNICODE
/* from http://stackoverflow.com/questions/15333259/c-stdwstring-to-stdstring-quick-and-dirty-conversion-for-use-as-key-in,
only works for ASCII chars */
/**
* Convert a std::string into a std::wstring
*/
static std::wstring string_to_wstring(const std::string& str)
{
return std::wstring(str.begin(), str.end());
}
/**
* Convert a std::wstring into a std::string
*/
static std::string wstring_to_string(const std::wstring& wstr)
{
return std::string(wstr.begin(), wstr.end());
}
#endif // SQUNICODE
template <class T>
class SharedPtr;
template <class T>
class WeakPtr;
/// @endcond
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Helper class that defines a VM that can be used as a fallback VM in case no other one is given to a piece of code
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class DefaultVM {
private:
static HSQUIRRELVM& staticVm() {
static HSQUIRRELVM vm;
return vm;
}
public:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Gets the default VM
///
/// \return Default VM
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static HSQUIRRELVM Get() {
return staticVm();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Sets the default VM to a given VM
///
/// \param vm New default VM
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void Set(HSQUIRRELVM vm) {
staticVm() = vm;
}
};
#if !defined (SCRAT_NO_ERROR_CHECKING) && !defined (SCRAT_USE_EXCEPTIONS)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// The class that must be used to deal with errors that Sqrat has
///
/// \remarks
/// When documentation in Sqrat says, "This function MUST have its error handled if it occurred," that
/// means that after the function has been run, you must call Error::Occurred to see if the function
/// ran successfully. If the function did not run successfully, then you MUST either call Error::Clear
/// or Error::Message to clear the error buffer so new ones may occur and Sqrat does not get confused.
///
/// \remarks
/// Any error thrown inside of a bound C++ function will be thrown in the given Squirrel VM and
/// automatically handled.
///
/// \remarks
/// If compiling with SCRAT_USE_EXCEPTIONS defined, Sqrat will throw exceptions instead of using this
/// class to handle errors. This means that functions must be enclosed in try blocks that catch
/// Sqrat::Exception instead of checking for errors with Error::Occurred.
///
/// \remarks
/// If compiling with SCRAT_NO_ERROR_CHECKING defined, Sqrat will run significantly faster,
/// but it will no longer check for errors and the Error class itself will not be defined.
/// In this mode, a Squirrel script may crash the C++ application if errors occur in it.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class Error {
public:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Clears the error associated with a given VM
///
/// \param vm Target VM
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void Clear(HSQUIRRELVM vm) {
sq_pushregistrytable(vm);
sq_pushstring(vm, "__error", -1);
sq_rawdeleteslot(vm, -2, false);
sq_pop(vm, 1);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Clears the error associated with a given VM and returns the associated error message
///
/// \param vm Target VM
///
/// \return String containing a nice error message
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static string Message(HSQUIRRELVM vm) {
sq_pushregistrytable(vm);
sq_pushstring(vm, "__error", -1);
if (SQ_SUCCEEDED(sq_rawget(vm, -2))) {
string** ud;
sq_getuserdata(vm, -1, (SQUserPointer*)&ud, NULL);
sq_pop(vm, 1);
string err = **ud;
sq_pushstring(vm, "__error", -1);
sq_rawdeleteslot(vm, -2, false);
sq_pop(vm, 1);
return err;
}
sq_pushstring(vm, "__error", -1);
sq_rawdeleteslot(vm, -2, false);
sq_pop(vm, 1);
return string(_SC("an unknown error has occurred"));
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Returns whether a Sqrat error has occurred with a given VM
///
/// \param vm Target VM
///
/// \return True if an error has occurred, otherwise false
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static bool Occurred(HSQUIRRELVM vm) {
sq_pushregistrytable(vm);
sq_pushstring(vm, "__error", -1);
if (SQ_SUCCEEDED(sq_rawget(vm, -2))) {
sq_pop(vm, 2);
return true;
}
sq_pop(vm, 1);
return false;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Raises an error in a given VM with a given error message
///
/// \param vm Target VM
/// \param err A nice error message
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void Throw(HSQUIRRELVM vm, const string& err) {
sq_pushregistrytable(vm);
sq_pushstring(vm, "__error", -1);
if (SQ_FAILED(sq_rawget(vm, -2))) {
sq_pushstring(vm, "__error", -1);
string** ud = reinterpret_cast<string**>(sq_newuserdata(vm, sizeof(string*)));
*ud = new string(err);
sq_setreleasehook(vm, -1, &error_cleanup_hook);
sq_rawset(vm, -3);
sq_pop(vm, 1);
return;
}
sq_pop(vm, 2);
}
private:
Error() {}
static SQInteger error_cleanup_hook(SQUserPointer ptr, SQInteger size) {
SQUNUSED(size);
string** ud = reinterpret_cast<string**>(ptr);
delete *ud;
return 0;
}
};
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Tells Sqrat whether Squirrel error handling should be used
///
/// \remarks
/// If true, if a runtime error occurs during the execution of a call, the VM will invoke its error handler.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class ErrorHandling {
private:
static bool& errorHandling() {
static bool eh = true;
return eh;
}
public:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Returns whether Squirrel error handling is enabled
///
/// \return True if error handling is enabled, otherwise false
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static bool IsEnabled() {
return errorHandling();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Enables or disables Squirrel error handling
///
/// \param enable True to enable, false to disable
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void Enable(bool enable) {
errorHandling() = enable;
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Sqrat exception class
///
/// \remarks
/// Used only when SCRAT_USE_EXCEPTIONS is defined (see Sqrat::Error)
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class Exception {
public:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Constructs an exception
///
/// \param msg A nice error message
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Exception(const SQChar * msg) noexcept : message(msg) {}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Constructs an exception
///
/// \param msg A nice error message
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
explicit Exception(string && msg) noexcept : message(msg) {}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Constructs an exception
///
/// \param msg A nice error message
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
explicit Exception(const string& msg) noexcept : message(msg) {}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy constructor
///
/// \param ex Exception to copy
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Exception(const Exception& ex) noexcept : message(ex.message) {}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Returns a string identifying the exception
///
/// \return A nice error message
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const string& Message() const noexcept {
return message;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Returns a C string identifying the exception
///
/// \return A nice error message
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const SQChar * what() const noexcept {
return message.c_str();
}
private:
string message;
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Returns a string that has been formatted to give a nice type error message (for usage with Class::SquirrelFunc)
///
/// \param vm VM the error occurred with
/// \param idx Index on the stack of the argument that had a type error
/// \param expectedType The name of the type that the argument should have been
///
/// \return String containing a nice type error message
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline string FormatTypeError(HSQUIRRELVM vm, SQInteger idx, const string& expectedType) {
string err = _SC("wrong type (") + expectedType + _SC(" expected");
#if (SQUIRREL_VERSION_NUMBER>= 200) && (SQUIRREL_VERSION_NUMBER < 300) // Squirrel 2.x
err = err + _SC(")");
#else // Squirrel 3.x
if (SQ_SUCCEEDED(sq_typeof(vm, idx))) {
const SQChar* actualType;
sq_tostring(vm, -1);
sq_getstring(vm, -1, &actualType);
sq_pop(vm, 2);
err = err + _SC(", got ") + actualType + _SC(")");
} else {
err = err + _SC(", got unknown)");
}
#endif
return err;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Returns the last error that occurred with a Squirrel VM (not associated with Sqrat errors)
///
/// \param vm Target VM
///
/// \return String containing a nice error message
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline string LastErrorString(HSQUIRRELVM vm) {
const SQChar* sqErr;
SQInteger size;
sq_getlasterror(vm);
if (sq_gettype(vm, -1) == OT_NULL) {
sq_pop(vm, 1);
return string();
}
sq_tostring(vm, -1);
sq_getstringandsize(vm, -1, &sqErr, &size);
sq_pop(vm, 2);
return string(sqErr, size);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// A smart pointer that retains shared ownership of an object through a pointer (see std::shared_ptr)
///
/// \tparam T Type of pointer
///
/// \remarks
/// SharedPtr exists to automatically delete an object when all references to it are destroyed.
///
/// \remarks
/// std::shared_ptr was not used because it is a C++11 feature.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <class T>
class SharedPtr
{
template <class U>
friend class SharedPtr;
template <class U>
friend class WeakPtr;
private:
T* m_Ptr;
unsigned int* m_RefCount;
unsigned int* m_RefCountRefCount;
public:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Constructs a new SharedPtr
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SharedPtr() :
m_Ptr (NULL),
m_RefCount (NULL),
m_RefCountRefCount(NULL)
{
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Constructs a new SharedPtr from an object allocated with the new operator
///
/// \param ptr Should be the return value from a call to the new operator
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SharedPtr(T* ptr) :
m_Ptr (NULL),
m_RefCount (NULL),
m_RefCountRefCount(NULL)
{
Init(ptr);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Constructs a new SharedPtr from an object allocated with the new operator
///
/// \param ptr Should be the return value from a call to the new operator
///
/// \tparam U Type of pointer (usually doesnt need to be defined explicitly)
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <class U>
SharedPtr(U* ptr) :
m_Ptr (NULL),
m_RefCount (NULL),
m_RefCountRefCount(NULL)
{
Init(ptr);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy constructor
///
/// \param copy SharedPtr to copy
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SharedPtr(const SharedPtr<T>& copy)
{
if (copy.Get() != NULL)
{
m_Ptr = copy.Get();
m_RefCount = copy.m_RefCount;
m_RefCountRefCount = copy.m_RefCountRefCount;
*m_RefCount += 1;
*m_RefCountRefCount += 1;
}
else
{
m_Ptr = NULL;
m_RefCount = NULL;
m_RefCountRefCount = NULL;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy constructor
///
/// \param copy SharedPtr to copy
///
/// \tparam U Type of copy (usually doesnt need to be defined explicitly)
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <class U>
SharedPtr(const SharedPtr<U>& copy)
{
if (copy.Get() != NULL)
{
m_Ptr = static_cast<T*>(copy.Get());
m_RefCount = copy.m_RefCount;
m_RefCountRefCount = copy.m_RefCountRefCount;
*m_RefCount += 1;
*m_RefCountRefCount += 1;
}
else
{
m_Ptr = NULL;
m_RefCount = NULL;
m_RefCountRefCount = NULL;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Move constructor
///
/// \param other SharedPtr to move
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SharedPtr(SharedPtr<T>&& other)
: m_Ptr(other.m_Ptr)
, m_RefCount(other.m_RefCount)
, m_RefCountRefCount(other.m_RefCountRefCount)
{
other.m_Ptr = NULL;
other.m_RefCount = NULL;
other.m_RefCountRefCount = NULL;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Move constructor
///
/// \param other SharedPtr to move
///
/// \tparam U Type of pointer (usually doesnt need to be defined explicitly)
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <class U>
SharedPtr(SharedPtr<U>&& other)
: m_Ptr(static_cast<T*>(other.m_Ptr))
, m_RefCount(other.m_RefCount)
, m_RefCountRefCount(other.m_RefCountRefCount)
{
other.m_Ptr = NULL;
other.m_RefCount = NULL;
other.m_RefCountRefCount = NULL;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy constructor
///
/// \param copy WeakPtr to copy
///
/// \tparam U Type of copy (usually doesnt need to be defined explicitly)
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <class U>
SharedPtr(const WeakPtr<U>& copy)
{
if (copy.m_Ptr != NULL)
{
m_Ptr = static_cast<T*>(copy.m_Ptr);
m_RefCount = copy.m_RefCount;
m_RefCountRefCount = copy.m_RefCountRefCount;
*m_RefCount += 1;
*m_RefCountRefCount += 1;
}
else
{
m_Ptr = NULL;
m_RefCount = NULL;
m_RefCountRefCount = NULL;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Destructs the owned object if no more SharedPtr link to it
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
~SharedPtr()
{
Reset();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Assigns the SharedPtr
///
/// \param copy SharedPtr to copy
///
/// \return The SharedPtr itself
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SharedPtr<T>& operator=(const SharedPtr<T>& copy)
{
if (this != &copy)
{
Reset();
if (copy.Get() != NULL)
{
m_Ptr = copy.Get();
m_RefCount = copy.m_RefCount;
m_RefCountRefCount = copy.m_RefCountRefCount;
*m_RefCount += 1;
*m_RefCountRefCount += 1;
}
}
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Assigns the SharedPtr
///
/// \param copy SharedPtr to copy
///
/// \tparam U Type of copy (usually doesnt need to be defined explicitly)
///
/// \return The SharedPtr itself
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <class U>
SharedPtr<T>& operator=(const SharedPtr<U>& copy)
{
Reset();
if (copy.Get() != NULL)
{
m_Ptr = static_cast<T*>(copy.Get());
m_RefCount = copy.m_RefCount;
m_RefCountRefCount = copy.m_RefCountRefCount;
*m_RefCount += 1;
*m_RefCountRefCount += 1;
}
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Assigns the SharedPtr
///
/// \param other SharedPtr to move
///
/// \return The SharedPtr itself
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SharedPtr<T>& operator=(SharedPtr<T>&& other)
{
if (m_Ptr != other.m_Ptr)
{
Reset();
m_Ptr = other.m_Ptr;
m_RefCount = other.m_RefCount;
m_RefCountRefCount = other.m_RefCountRefCount;
other.m_Ptr = NULL;
other.m_RefCount = NULL;
other.m_RefCountRefCount = NULL;
}
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Assigns the SharedPtr
///
/// \param other SharedPtr to move
///
/// \tparam U Type of pointer (usually doesnt need to be defined explicitly)
///
/// \return The SharedPtr itself
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <class U>
SharedPtr<T>& operator=(SharedPtr<U>&& other)
{
if (m_Ptr != static_cast<T*>(other.m_Ptr))
{
Reset();
m_Ptr = static_cast<T*>(other.m_Ptr);
m_RefCount = other.m_RefCount;
m_RefCountRefCount = other.m_RefCountRefCount;
other.m_Ptr = NULL;
other.m_RefCount = NULL;
other.m_RefCountRefCount = NULL;
}
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Sets up a new object to be managed by the SharedPtr
///
/// \param ptr Should be the return value from a call to the new operator
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Init(T* ptr)
{
Reset();
m_Ptr = ptr;
m_RefCount = new unsigned int;
*m_RefCount = 1;
m_RefCountRefCount = new unsigned int;
*m_RefCountRefCount = 1;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Sets up a new object to be managed by the SharedPtr
///
/// \param ptr Should be the return value from a call to the new operator
///
/// \tparam U Type of copy (usually doesnt need to be defined explicitly)
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <class U>
void Init(U* ptr)
{
Reset();
m_Ptr = static_cast<T*>(ptr);
m_RefCount = new unsigned int;
*m_RefCount = 1;
m_RefCountRefCount = new unsigned int;
*m_RefCountRefCount = 1;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Clears the owned object for this SharedPtr and deletes it if no more SharedPtr link to it
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Reset()
{
if (m_Ptr != NULL)
{
*m_RefCount -= 1;
*m_RefCountRefCount -= 1;
if (*m_RefCount == 0)
{
delete m_Ptr;
}
if (*m_RefCountRefCount == 0)
{
delete m_RefCount;
delete m_RefCountRefCount;
}
m_Ptr = NULL;
m_RefCount = NULL;
m_RefCountRefCount = NULL;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Checks if there is an associated managed object
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
operator bool () const
{
return m_Ptr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Checks if there is NOT an associated managed object
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool operator!() const
{
return !m_Ptr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Compares with another SharedPtr
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename U>
bool operator ==(const SharedPtr<U>& right) const
{
return m_Ptr == right.m_Ptr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Compares with another SharedPtr
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool operator ==(const SharedPtr<T>& right) const
{
return m_Ptr == right.m_Ptr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Compares with another pointer
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename U>
bool friend operator ==(const SharedPtr<T>& left, const U* right)
{
return left.m_Ptr == right;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Compares with another pointer
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool friend operator ==(const SharedPtr<T>& left, const T* right)
{
return left.m_Ptr == right;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Compares with another pointer
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename U>
bool friend operator ==(const U* left, const SharedPtr<T>& right)
{
return left == right.m_Ptr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Compares with another pointer
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool friend operator ==(const T* left, const SharedPtr<T>& right)
{
return left == right.m_Ptr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Compares with another SharedPtr
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename U>
bool operator !=(const SharedPtr<U>& right) const
{
return m_Ptr != right.m_Ptr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Compares with another SharedPtr
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool operator !=(const SharedPtr<T>& right) const
{
return m_Ptr != right.m_Ptr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Compares with another pointer
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename U>
bool friend operator !=(const SharedPtr<T>& left, const U* right)
{
return left.m_Ptr != right;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Compares with another pointer
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool friend operator !=(const SharedPtr<T>& left, const T* right)
{
return left.m_Ptr != right;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Compares with another pointer
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename U>
bool friend operator !=(const U* left, const SharedPtr<T>& right)
{
return left != right.m_Ptr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Compares with another pointer
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool friend operator !=(const T* left, const SharedPtr<T>& right)
{
return left != right.m_Ptr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Dereferences pointer to the managed object
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
T& operator*() const
{
assert(m_Ptr != NULL); // fails when dereferencing a null SharedPtr
return *m_Ptr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Dereferences pointer to the managed object
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
T* operator->() const
{
assert(m_Ptr != NULL); // fails when dereferencing a null SharedPtr
return m_Ptr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Gets the underlying pointer
///
/// \return Pointer to the managed object
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
T* Get() const
{
return m_Ptr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Gets the number of references to the underlying pointer
///
/// \return Number of references
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
unsigned int Count() const
{
return m_RefCount ? *m_RefCount : 0;
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// A smart pointer that retains a non-owning ("weak") reference to an object that is managed by SharedPtr (see std::weak_ptr)
///
/// \tparam T Type of pointer
///
/// \remarks
/// WeakPtr exists for when an object that may be deleted at any time needs to be accessed if it exists.
///
/// \remarks
/// std::weak_ptr was not used because it is a C++11 feature.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <class T>
class WeakPtr
{
template <class U>
friend class SharedPtr;
private:
T* m_Ptr;
unsigned int* m_RefCount;
unsigned int* m_RefCountRefCount;
public:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Constructs a new WeakPtr
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
WeakPtr() :
m_Ptr (NULL),
m_RefCount (NULL),
m_RefCountRefCount(NULL)
{
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy constructor
///
/// \param copy WeakPtr to copy
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
WeakPtr(const WeakPtr<T>& copy)
{
if (copy.m_Ptr != NULL)
{
m_Ptr = copy.m_Ptr;
m_RefCount = copy.m_RefCount;
m_RefCountRefCount = copy.m_RefCountRefCount;
*m_RefCountRefCount += 1;
}
else
{
m_Ptr = NULL;
m_RefCount = NULL;
m_RefCountRefCount = NULL;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy constructor
///
/// \param copy WeakPtr to copy
///
/// \tparam U Type of copy (usually doesnt need to be defined explicitly)
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <class U>
WeakPtr(const WeakPtr<U>& copy)
{
if (copy.m_Ptr != NULL)
{
m_Ptr = static_cast<T*>(copy.m_Ptr);
m_RefCount = copy.m_RefCount;
m_RefCountRefCount = copy.m_RefCountRefCount;
*m_RefCountRefCount += 1;
}
else
{
m_Ptr = NULL;
m_RefCount = NULL;
m_RefCountRefCount = NULL;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Move constructor
///
/// \param other WeakPtr to move
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
WeakPtr(WeakPtr<T>&& other)
: m_Ptr(other.m_Ptr)
, m_RefCount(other.m_RefCount)
, m_RefCountRefCount(other.m_RefCountRefCount)
{
other.m_Ptr = NULL;
other.m_RefCount = NULL;
other.m_RefCountRefCount = NULL;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Move constructor
///
/// \param other WeakPtr to move
///
/// \tparam U Type of pointer (usually doesnt need to be defined explicitly)
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <class U>
WeakPtr(WeakPtr<U>&& other)
: m_Ptr(static_cast<T*>(other.m_Ptr))
, m_RefCount(other.m_RefCount)
, m_RefCountRefCount(other.m_RefCountRefCount)
{
other.m_Ptr = NULL;
other.m_RefCount = NULL;
other.m_RefCountRefCount = NULL;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy constructor
///
/// \param copy SharedPtr to copy
///
/// \tparam U Type of copy (usually doesnt need to be defined explicitly)
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <class U>
WeakPtr(const SharedPtr<U>& copy)
{
if (copy.Get() != NULL)
{
m_Ptr = static_cast<T*>(copy.Get());
m_RefCount = copy.m_RefCount;
m_RefCountRefCount = copy.m_RefCountRefCount;
*m_RefCountRefCount += 1;
}
else
{
m_Ptr = NULL;
m_RefCount = NULL;
m_RefCountRefCount = NULL;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Destructs the WeakPtr but has no influence on the object that was managed
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
~WeakPtr()
{
Reset();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Assigns the WeakPtr
///
/// \param copy WeakPtr to copy
///
/// \return The WeakPtr itself
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
WeakPtr<T>& operator=(const WeakPtr<T>& copy)
{
if (this != &copy)
{
Reset();
if (copy.m_Ptr != NULL)
{
m_Ptr = copy.m_Ptr;
m_RefCount = copy.m_RefCount;
m_RefCountRefCount = copy.m_RefCountRefCount;
*m_RefCountRefCount += 1;
}
}
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Assigns the WeakPtr
///
/// \param copy WeakPtr to copy
///
/// \tparam U Type of copy (usually doesnt need to be defined explicitly)
///
/// \return The WeakPtr itself
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <class U>
WeakPtr<T>& operator=(const WeakPtr<U>& copy)
{
Reset();
if (copy.m_Ptr != NULL)
{
m_Ptr = static_cast<T*>(copy.m_Ptr);
m_RefCount = copy.m_RefCount;
m_RefCountRefCount = copy.m_RefCountRefCount;
*m_RefCountRefCount += 1;
}
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Assigns the WeakPtr
///
/// \param other WeakPtr to move
///
/// \return The WeakPtr itself
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
WeakPtr<T>& operator=(WeakPtr<T>&& other)
{
if (m_Ptr != other.m_Ptr)
{
Reset();
m_Ptr = other.m_Ptr;
m_RefCount = other.m_RefCount;
m_RefCountRefCount = other.m_RefCountRefCount;
other.m_Ptr = NULL;
other.m_RefCount = NULL;
other.m_RefCountRefCount = NULL;
}
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Assigns the WeakPtr
///
/// \param other WeakPtr to move
///
/// \tparam U Type of pointer (usually doesnt need to be defined explicitly)
///
/// \return The WeakPtr itself
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <class U>
WeakPtr<T>& operator=(WeakPtr<U>&& other)
{
if (m_Ptr != static_cast<T*>(other.m_Ptr))
{
Reset();
m_Ptr = static_cast<T*>(other.m_Ptr);
m_RefCount = other.m_RefCount;
m_RefCountRefCount = other.m_RefCountRefCount;
other.m_Ptr = NULL;
other.m_RefCount = NULL;
other.m_RefCountRefCount = NULL;
}
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Assigns the WeakPtr
///
/// \param copy SharedPtr to copy
///
/// \tparam U Type of copy (usually doesnt need to be defined explicitly)
///
/// \return The WeakPtr itself
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <class U>
WeakPtr<T>& operator=(const SharedPtr<U>& copy)
{
Reset();
if (copy.Get() != NULL)
{
m_Ptr = static_cast<T*>(copy.Get());
m_RefCount = copy.m_RefCount;
m_RefCountRefCount = copy.m_RefCountRefCount;
*m_RefCountRefCount += 1;
}
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Checks whether the managed object exists
///
/// \return True if the managed object does not exist, false otherwise
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool Expired() const
{
return (m_Ptr == NULL || *m_RefCount == 0);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Creates a new SharedPtr that shares ownership of the managed object
///
/// \return A SharedPtr which shares ownership of the managed object
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SharedPtr<T> Lock() const
{
SharedPtr<T> other;
if (m_Ptr != NULL)
{
other.m_Ptr = m_Ptr;
other.m_RefCount = m_RefCount;
other.m_RefCountRefCount = m_RefCountRefCount;
*m_RefCount += 1;
*m_RefCountRefCount += 1;
}
return other;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Clears the associated object for this WeakPtr
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Reset()
{
if (m_Ptr != NULL)
{
*m_RefCountRefCount -= 1;
if (*m_RefCountRefCount == 0)
{
delete m_RefCount;
delete m_RefCountRefCount;
}
m_Ptr = NULL;
m_RefCount = NULL;
m_RefCountRefCount = NULL;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Gets the number of weak references to the underlying pointer
///
/// \return Number of references
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
unsigned int Count() const
{
return m_RefCountRefCount ? *m_RefCountRefCount : 0;
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Implements RAII to restore the VM stack to it's initial size on function exit.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct StackGuard
{
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Default constructor.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackGuard()
: m_VM(DefaultVM::Get()), m_Top(sq_gettop(m_VM))
{
/* ... */
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Base constructor.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackGuard(HSQUIRRELVM vm)
: m_VM(vm), m_Top(sq_gettop(vm))
{
/* ... */
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy constructor. (disabled)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackGuard(const StackGuard &) = delete;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Move constructor. (disabled)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackGuard(StackGuard &&) = delete;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Destructor.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
~StackGuard()
{
sq_pop(m_VM, sq_gettop(m_VM) - m_Top);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy assignment operator. (disabled)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackGuard & operator = (const StackGuard &) = delete;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Move assignment operator. (disabled)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackGuard & operator = (StackGuard &&) = delete;
private:
HSQUIRRELVM m_VM; ///< The VM where the stack should be restored.
SQInteger m_Top; ///< The top of the stack when this instance was created.
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Helper structure for retrieving a value from the stack as a string or a formatted string.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct StackStrF
{
const SQChar * mPtr; ///< Pointer to the C string that was retrieved.
SQInteger mLen; ///< The string length if it could be retrieved.
SQRESULT mRes; ///< The result of the retrieval attempts.
HSQOBJECT mObj; ///< Strong reference to the string object.
HSQUIRRELVM mVM; ///< The associated virtual machine.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Base constructor.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackStrF(HSQUIRRELVM vm, SQInteger idx, bool fmt = true)
: mPtr(nullptr)
, mLen(-1)
, mRes(SQ_OK)
, mObj()
, mVM(vm)
{
const SQInteger top = sq_gettop(vm);
// Reset the converted value object
sq_resetobject(&mObj);
// Was the string or value specified?
if (top <= (idx - 1))
{
mRes = sq_throwerror(vm, "Missing string or value");
}
// Do we have enough values to call the format function and are we allowed to?
else if ((top - 1) > idx && fmt)
{
// Pointer to the generated string
SQChar * str = nullptr;
// Attempt to generate the specified string format
mRes = sqstd_format(vm, idx, &mLen, &str);
// Did the format succeeded but ended up with a null string pointer?
if (SQ_SUCCEEDED(mRes) && !str)
{
mRes = sq_throwerror(vm, "Unable to generate the string");
}
else
{
mPtr = const_cast< const SQChar * >(str);
}
}
// Is the value on the stack an actual string?
else if (sq_gettype(vm, idx) == OT_STRING)
{
// Obtain a reference to the string object
mRes = sq_getstackobj(vm, idx, &mObj);
// Could we retrieve the object from the stack?
if (SQ_SUCCEEDED(mRes))
{
// Keep a strong reference to the object
sq_addref(vm, &mObj);
// Attempt to retrieve the string value from the stack
mRes = sq_getstringandsize(vm, idx, &mPtr, &mLen);
}
// Did the retrieval succeeded but ended up with a null string pointer?
if (SQ_SUCCEEDED(mRes) && !mPtr)
{
mRes = sq_throwerror(vm, "Unable to retrieve the string");
}
}
// We have to try and convert it to string
else
{
// Attempt to convert the value from the stack to a string
mRes = sq_tostring(vm, idx);
// Could we convert the specified value to string?
if (SQ_SUCCEEDED(mRes))
{
// Obtain a reference to the resulted object
mRes = sq_getstackobj(vm, -1, &mObj);
// Could we retrieve the object from the stack?
if (SQ_SUCCEEDED(mRes))
{
// Keep a strong reference to the object
sq_addref(vm, &mObj);
// Attempt to obtain the string pointer
mRes = sq_getstringandsize(vm, -1, &mPtr, &mLen);
}
}
// Pop a value from the stack regardless of the result
sq_pop(vm, 1);
// Did the retrieval succeeded but ended up with a null string pointer?
if (SQ_SUCCEEDED(mRes) && !mPtr)
{
mRes = sq_throwerror(vm, "Unable to retrieve the value");
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy constructor. (disabled)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackStrF(const StackStrF & o) = delete;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy constructor.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackStrF(StackStrF && o)
: mPtr(o.mPtr)
, mLen(o.mLen)
, mRes(o.mRes)
, mObj(o.mObj)
, mVM(o.mVM)
{
o.mPtr = nullptr;
o.mLen = 0;
o.mRes = SQ_OK;
o.mVM = nullptr;
sq_resetobject(&o.mObj);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Destructor.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
~StackStrF()
{
if (mVM && !sq_isnull(mObj))
{
sq_release(mVM, &mObj);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy constructor. (disabled)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackStrF & operator = (const StackStrF & o) = delete;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Move constructor. (disabled)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackStrF & operator = (StackStrF && o) = delete;
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @cond DEV
/// Used internally to get and manipulate the underlying type of variables - retrieved from cppreference.com
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> struct remove_const {typedef T type;};
template<class T> struct remove_const<const T> {typedef T type;};
template<class T> struct remove_volatile {typedef T type;};
template<class T> struct remove_volatile<volatile T> {typedef T type;};
template<class T> struct remove_cv {typedef typename remove_volatile<typename remove_const<T>::type>::type type;};
template<class T> struct is_pointer_helper {static const bool value = false;};
template<class T> struct is_pointer_helper<T*> {static const bool value = true;};
template<class T> struct is_pointer_helper<SharedPtr<T> > {static const bool value = true;};
template<class T> struct is_pointer_helper<WeakPtr<T> > {static const bool value = true;};
template<class T> struct is_pointer : is_pointer_helper<typename remove_cv<T>::type> {};
template<class T> struct is_reference {static const bool value = false;};
template<class T> struct is_reference<T&> {static const bool value = true;};
/// @endcond
}
#endif