mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 08:47:17 +01:00
209 lines
6.8 KiB
C++
209 lines
6.8 KiB
C++
|
// ------------------------------------------------------------------------------------------------
|
||
|
#include "Library/Worker/Parameter.hpp"
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
namespace SqMod {
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
Parameter::Parameter(CCStr str)
|
||
|
: Parameter()
|
||
|
{
|
||
|
// Make sure there's a string
|
||
|
if (str)
|
||
|
{
|
||
|
mSize = static_cast< uint32_t >(std::strlen(str));
|
||
|
mString = new SQChar[mSize+1];
|
||
|
std::strcpy(mString, str);
|
||
|
}
|
||
|
// Even an empty string should still be marked as a string
|
||
|
mType = T_STRING;
|
||
|
}
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
Parameter::Parameter(CCStr str, size_t len)
|
||
|
: Parameter()
|
||
|
{
|
||
|
// Make sure there's a string
|
||
|
if (str && len)
|
||
|
{
|
||
|
mSize = ConvTo< uint32_t >::From(len);
|
||
|
mString = new SQChar[mSize+1];
|
||
|
std::strncpy(mString, str, mSize);
|
||
|
mString[mSize] = '\0'; // Null terminator
|
||
|
}
|
||
|
// Even an empty string should still be marked as a string
|
||
|
mType = T_STRING;
|
||
|
}
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
Parameter::Parameter(ArrayType && v)
|
||
|
: mType(T_ARRAY), mSize(static_cast< uint32_t >(v.size()))
|
||
|
, mArray(new ArrayType(std::forward< ArrayType >(v)))
|
||
|
{
|
||
|
}
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
Parameter::Parameter(const ArrayType & v)
|
||
|
: mType(T_ARRAY), mSize(static_cast< uint32_t >(v.size()))
|
||
|
, mArray(new ArrayType(v))
|
||
|
{
|
||
|
}
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
Parameter::Parameter(TableType && v)
|
||
|
: mType(T_ARRAY), mSize(static_cast< uint32_t >(v.size()))
|
||
|
, mTable(new TableType(std::forward< TableType >(v)))
|
||
|
{
|
||
|
}
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
Parameter::Parameter(const TableType & v)
|
||
|
: mType(T_ARRAY), mSize(static_cast< uint32_t >(v.size()))
|
||
|
, mTable(new TableType(v))
|
||
|
{
|
||
|
}
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
Parameter::Parameter(const Parameter & o)
|
||
|
: mType(o.mType), mSize(o.mSize), mData(o.mData)
|
||
|
{
|
||
|
// Identify the type to be copied
|
||
|
switch (mType)
|
||
|
{
|
||
|
// Fundamental types can be copied bit-wise (which we did)
|
||
|
case T_NULL:
|
||
|
case T_INT:
|
||
|
case T_BOOL:
|
||
|
case T_FLOAT: break;
|
||
|
case T_STRING:
|
||
|
if (mSize)
|
||
|
{
|
||
|
mString = new SQChar[mSize];
|
||
|
std::strncpy(mString, o.mString, mSize);
|
||
|
mString[mSize] = '\0'; // Null terminator
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mString = nullptr; // Empty string?
|
||
|
}
|
||
|
break;
|
||
|
case T_ARRAY:
|
||
|
mArray = o.mArray ? new ArrayType(*o.mArray) : nullptr;
|
||
|
break;
|
||
|
case T_TABLE:
|
||
|
mTable = o.mTable ? new TableType(*o.mTable) : nullptr;
|
||
|
break;
|
||
|
// How did we get here?
|
||
|
default: break;
|
||
|
}
|
||
|
}
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
Parameter::Parameter(Parameter && o)
|
||
|
: mType(o.mType), mSize(o.mSize), mData(o.mData)
|
||
|
{
|
||
|
o.Discard(); // Take ownership
|
||
|
}
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
bool Parameter::operator == (const Parameter & o) const noexcept
|
||
|
{
|
||
|
// If they're not the same type then there's no point in comparing
|
||
|
if (mType != o.mType)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
// Identify which type to compare
|
||
|
switch (mType)
|
||
|
{
|
||
|
// Null is same regardless
|
||
|
case T_NULL: return true;
|
||
|
// Boolean is stored as integer
|
||
|
case T_INT:
|
||
|
case T_BOOL: return (mInt == o.mInt);
|
||
|
// Take into account precision errors
|
||
|
case T_FLOAT: return EpsEq(mFloat, o.mFloat);
|
||
|
case T_STRING:
|
||
|
// Only perform a comparison if there's actually a string to compare
|
||
|
if (mSize && mSize == o.mSize)
|
||
|
{
|
||
|
return std::strncmp(mString, o.mString, mSize) == 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return false; // If they're not the same size then they can't be the same
|
||
|
}
|
||
|
// For table or arrays we only test if they're the same rather then each value individually
|
||
|
case T_ARRAY: return (mArray == o.mArray);
|
||
|
case T_TABLE: return (mTable == o.mTable);
|
||
|
// How did we get here?
|
||
|
default: return false;
|
||
|
}
|
||
|
}
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
void Parameter::Assign(const Parameter & o)
|
||
|
{
|
||
|
// Avoid self assignment
|
||
|
if (this == &o) return;
|
||
|
/* We could probably optimize this by reusing current container memory.
|
||
|
* But chances are we would complicate code for the simpler case.
|
||
|
* And the simpler case is likely to be the more common scenario.
|
||
|
*/
|
||
|
// Discard current information
|
||
|
Clear();
|
||
|
// The size and type are copied bit-wise
|
||
|
mType = o.mType;
|
||
|
mSize = o.mSize;
|
||
|
// Identify the type to be copied
|
||
|
switch (mType)
|
||
|
{
|
||
|
// Fundamental types can be copied bit-wise
|
||
|
case T_NULL:
|
||
|
case T_INT:
|
||
|
case T_BOOL:
|
||
|
case T_FLOAT:
|
||
|
mData = o.mData;
|
||
|
break;
|
||
|
// Strings require memory to be allocated
|
||
|
case T_STRING:
|
||
|
if (mSize)
|
||
|
{
|
||
|
mString = new SQChar[mSize];
|
||
|
std::strncpy(mString, o.mString, mSize);
|
||
|
mString[mSize] = '\0'; // Null terminator
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mString = nullptr; // Empty string?
|
||
|
}
|
||
|
break;
|
||
|
case T_ARRAY:
|
||
|
mArray = o.mArray ? new ArrayType(*o.mArray) : nullptr;
|
||
|
break;
|
||
|
case T_TABLE:
|
||
|
mTable = o.mTable ? new TableType(*o.mTable) : nullptr;
|
||
|
break;
|
||
|
// How did we get here?
|
||
|
default: break;
|
||
|
}
|
||
|
}
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
void Parameter::Assign(Parameter && o)
|
||
|
{
|
||
|
// Avoid self assignment
|
||
|
if (this == &o) return;
|
||
|
// Discard current information
|
||
|
Clear();
|
||
|
// We don't care about the type since we take ownership
|
||
|
mType = o.mType;
|
||
|
mSize = o.mSize;
|
||
|
mData = o.mData;
|
||
|
// Take ownership
|
||
|
o.Discard();
|
||
|
}
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
void Parameter::Clear()
|
||
|
{
|
||
|
switch (mType)
|
||
|
{
|
||
|
case T_STRING: delete[] mString; break;
|
||
|
case T_ARRAY: delete mArray; break;
|
||
|
case T_TABLE: delete mTable; break;
|
||
|
default: break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} // Namespace:: SqMod
|