// ------------------------------------------------------------------------------------------------ #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