From d56eab0420ac132f2ec52e101731c64ac7ed8700 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Mon, 16 Dec 2019 09:59:49 +0800 Subject: [PATCH] CObjectNumber for Lua interop needs to deal with both double and sint64 types, cannot have separate CObjectInteger type --- .../client/src/r2/dmc/com_lua_module.cpp | 2 +- code/ryzom/common/src/game_share/object.cpp | 267 +++++++----------- code/ryzom/common/src/game_share/object.h | 82 ++---- 3 files changed, 136 insertions(+), 215 deletions(-) diff --git a/code/ryzom/client/src/r2/dmc/com_lua_module.cpp b/code/ryzom/client/src/r2/dmc/com_lua_module.cpp index 7a3fb94fc..18ecbe011 100644 --- a/code/ryzom/client/src/r2/dmc/com_lua_module.cpp +++ b/code/ryzom/client/src/r2/dmc/com_lua_module.cpp @@ -1245,7 +1245,7 @@ CObject* CComLuaModule::getObjectFromLua(lua_State* state, sint idx) { sint64 value = lua_tointeger(state, -1); lua_pop(state, 1); - return new CObjectInteger(value); + return new CObjectNumber(value); } else #endif diff --git a/code/ryzom/common/src/game_share/object.cpp b/code/ryzom/common/src/game_share/object.cpp index 97794b812..c8e238107 100644 --- a/code/ryzom/common/src/game_share/object.cpp +++ b/code/ryzom/common/src/game_share/object.cpp @@ -175,12 +175,6 @@ void CObject::inPlaceCopy(const CObjectNumber &src) copyMismatchMsg(src); } -void CObject::inPlaceCopy(const CObjectInteger &src) -{ - //H_AUTO(R2_CObject_inPlaceCopy) - copyMismatchMsg(src); -} - void CObject::inPlaceCopy(const CObjectTable &src) { //H_AUTO(R2_CObject_inPlaceCopy) @@ -764,7 +758,15 @@ void CObjectRefId::doSerialize(std::string& out, CSerializeContext& /* context //----------------------- CObjectNumber ---------------------------------------- -CObjectNumber::CObjectNumber(double value) : CObject(), _Value(value){} +CObjectNumber::CObjectNumber(double value) : CObject(), m_IsInteger(false) +{ + m_Value.Integer = value; +} + +CObjectNumber::CObjectNumber(sint64 value) : CObject(), m_IsInteger(true) +{ + m_Value.Integer = value; +} const char *CObjectNumber::getTypeAsString() const { @@ -787,185 +789,137 @@ void CObjectNumber::inPlaceCopyTo(CObject &dest) const void CObjectNumber::inPlaceCopy(const CObjectNumber &src) { //H_AUTO(R2_CObjectNumber_inPlaceCopy) - _Value = src._Value; + m_IsInteger = src.m_IsInteger; + m_Value.Integer = src.m_Value.Integer; setGhost(src.getGhost()); } -std::string CObjectNumber::doToString() const { return NLMISC::toString("%lf", _Value);} +std::string CObjectNumber::doToString() const { return m_IsInteger ? NLMISC::toString(m_Value.Integer) : NLMISC::toString("%lf", m_Value.Number);} void CObjectNumber::doSerialize(std::string& out, CSerializeContext& /* context */) const { //H_AUTO(R2_CObjectNumber_doSerialize) nlassert(!getGhost()); - //out.precision(15); - std::string value = NLMISC::toString(double(sint64(_Value * 1000.0 + (_Value>=0.0?0.5:-0.5)))/1000.0); - // search for first not 0 value from the end - std::string::size_type pos = value.find_last_not_of('0'); - if (pos != std::string::npos) + if (m_IsInteger) + { + out += NLMISC::toString(m_Value.Integer); + } + else { - // don't remove character at pos if it's another digit - if (value[pos] != '.') ++pos; - value.erase(pos); + //out.precision(15); + double num = getNumberValue(); + // TODO: WTF is this for?! + std::string value = NLMISC::toString(double(sint64(num * 1000.0 + (num>=0.0?0.5:-0.5)))/1000.0); + // search for first not 0 value from the end + std::string::size_type pos = value.find_last_not_of('0'); + if (pos != std::string::npos) + { + // don't remove character at pos if it's another digit + if (value[pos] != '.') ++pos; + value.erase(pos); + } + out += value; } - out += value; } -bool CObjectNumber::set(const std::string& key, double value) +bool CObjectNumber::set(const std::string& key, sint64 value) { //H_AUTO(R2_CObjectNumber_set) BOMB_IF(!key.empty(), "Try to set an element of a table on an object that is not a table", return false); - _Value = value; + m_IsInteger = true; + m_Value.Integer = value; return true; } +bool CObjectNumber::set(const std::string& key, double value) +{ + //H_AUTO(R2_CObjectNumber_set) + + BOMB_IF(!key.empty(), "Try to set an element of a table on an object that is not a table", return false); + + m_IsInteger = false; + m_Value.Number = value; + return true; +} bool CObjectNumber::set(const std::string& key, const std::string & value) { //H_AUTO(R2_CObjectNumber_set) //XXX BOMB_IF(!key.empty(), "Try to set an element of a table on an object that is not a table", return false); - NLMISC::fromString(value, _Value); - return true; + double num; + sint64 i; + if (NLMISC::fromString(value, num)) + { + m_IsInteger = false; + m_Value.Number = num; + } + if (NLMISC::fromString(value, i)) + { + m_IsInteger = true; + m_Value.Number = i; + } + return false; } - -double CObjectNumber::doToNumber() const { return _Value; } - CObject* CObjectNumber::clone() const { //H_AUTO(R2_CObjectNumber_clone) - CObjectNumber *result = new CObjectNumber(_Value); + CObjectNumber *result = m_IsInteger + ? new CObjectNumber(m_Value.Integer) + : new CObjectNumber(m_Value.Number); result->setGhost(getGhost()); return result; } -bool CObjectNumber::doIsNumber() const { return true;} +bool CObjectNumber::doIsNumber() const { return !m_IsInteger || (sint64)getNumberValue() == m_Value.Integer;} + +double CObjectNumber::doToNumber() const { return getNumberValue(); } +bool CObjectNumber::doIsInteger() const { return m_IsInteger || (double)getIntegerValue() == m_Value.Number;} +sint64 CObjectNumber::doToInteger() const { return getIntegerValue(); } bool CObjectNumber::setObject(const std::string& /* key */, CObject* value) { //H_AUTO(R2_CObjectNumber_setObject) - BOMB_IF(!value->isNumber(), NLMISC::toString("Try to set an element of a type '%s' with a value of type '%s' on an object that is not a number", this->getTypeAsString(), value->getTypeAsString()), return false); + BOMB_IF(!value->isNumber() && !value->isInteger(), NLMISC::toString("Try to set an element of a type '%s' with a value of type '%s' on an object that is not a number", this->getTypeAsString(), value->getTypeAsString()), return false); - _Value = value->toNumber(); + if (value->isInteger()) + { + m_IsInteger = true; + m_Value.Integer = value->toInteger(); + } + else + { + m_IsInteger = false; + m_Value.Number = value->toNumber(); + } setGhost(value->getGhost()); return true; } - - bool CObjectNumber::equal(const CObject* other) const { - //H_AUTO(R2_CObjectNumber_equal) - if (!other || !other->isNumber()) return false; + if (!other) return false; + if (isInteger()) + { + if (!other->isInteger()) return false; + return (getIntegerValue() == other->toInteger()); + } + + if (!other->isNumber()) return false; + double value = getNumberValue(); double otherValue = other->toNumber(); - if (_Value == otherValue) return true; + if (value == otherValue) return true; // if difference between 2 values less than epsilon, we consider they are equals - return fabs(_Value - otherValue) <= std::numeric_limits::epsilon(); + return fabs(value - otherValue) <= std::numeric_limits::epsilon(); } - -//----------------------- CObjectInteger ---------------------------------------- - - -CObjectInteger::CObjectInteger(sint64 value) : CObject(), _Value(value){} - -const char *CObjectInteger::getTypeAsString() const -{ - return "Integer"; -} - -void CObjectInteger::visitInternal(IObjectVisitor &visitor) -{ - //H_AUTO(R2_CObjectInteger_visit) - visitor.visit(*this); -} - - -void CObjectInteger::inPlaceCopyTo(CObject &dest) const -{ - //H_AUTO(R2_CObjectInteger_inPlaceCopyTo) - dest.inPlaceCopy(*this); -} - -void CObjectInteger::inPlaceCopy(const CObjectInteger &src) -{ - //H_AUTO(R2_CObjectInteger_inPlaceCopy) - _Value = src._Value; - setGhost(src.getGhost()); -} - - -std::string CObjectInteger::doToString() const { return NLMISC::toString(_Value); } - -void CObjectInteger::doSerialize(std::string& out, CSerializeContext& /* context */) const -{ - //H_AUTO(R2_CObjectInteger_doSerialize) - nlassert(!getGhost()); - out += NLMISC::toString(_Value); -} - -bool CObjectInteger::set(const std::string& key, sint64 value) -{ - //H_AUTO(R2_CObjectInteger_set) - - BOMB_IF(!key.empty(), "Try to set an element of a table on an object that is not a table", return false); - - _Value = value; - return true; -} - - -bool CObjectInteger::set(const std::string& key, const std::string & value) -{ - //H_AUTO(R2_CObjectInteger_set) - //XXX - BOMB_IF(!key.empty(), "Try to set an element of a table on an object that is not a table", return false); - NLMISC::fromString(value, _Value); - return true; -} - - -sint64 CObjectInteger::doToInteger() const { return _Value; } - -CObject* CObjectInteger::clone() const -{ - //H_AUTO(R2_CObjectInteger_clone) - CObjectInteger *result = new CObjectInteger(_Value); - result->setGhost(getGhost()); - return result; -} - -bool CObjectInteger::doIsInteger() const { return true;} - - - -bool CObjectInteger::setObject(const std::string& /* key */, CObject* value) -{ - //H_AUTO(R2_CObjectInteger_setObject) - BOMB_IF(!value->isInteger(), NLMISC::toString("Try to set an element of a type '%s' with a value of type '%s' on an object that is not an integer", this->getTypeAsString(), value->getTypeAsString()), return false); - - _Value = value->toInteger(); - setGhost(value->getGhost()); - return true; -} - - - -bool CObjectInteger::equal(const CObject* other) const -{ - //H_AUTO(R2_CObjectInteger_equal) - if (!other || !other->isInteger()) return false; - sint64 otherValue = other->toInteger(); - return _Value == otherValue; -} - - //----------------------- CObjectTable ---------------------------------------- @@ -1686,7 +1640,7 @@ CObject* CObjectFactory::newBasic(const std::string & type) } else if (type == "Number") { - return new CObjectNumber(0); + return new CObjectNumber((sint64)0); } else if (type == "Table") { @@ -1976,15 +1930,10 @@ void CObjectNumber::dump(const std::string prefix, uint depth) const { //H_AUTO(R2_CObjectNumber_dump) std::string result(depth * 4, ' '); - result += NLMISC::toString("%sNumber, ptr = 0x%p, value = %lf, ghost = %s", prefix.c_str(), this, _Value, _Ghost ? "true" : "false"); - nlwarning(result.c_str()); -} - -void CObjectInteger::dump(const std::string prefix, uint depth) const -{ - //H_AUTO(R2_CObjectInteger_dump) - std::string result(depth * 4, ' '); - result += NLMISC::toString("%sInteger, ptr = 0x%p, value = %" NL_I64 "d, ghost = %s", prefix.c_str(), this, _Value, _Ghost ? "true" : "false"); + if (m_IsInteger) + result += NLMISC::toString("%sNumber, ptr = 0x%p, isNumber, value = %lf, ghost = %s", prefix.c_str(), this, m_Value.Integer, _Ghost ? "true" : "false"); + else + result += NLMISC::toString("%sNumber, ptr = 0x%p, isInteger, value = %lf, ghost = %s", prefix.c_str(), this, m_Value.Number, _Ghost ? "true" : "false"); nlwarning(result.c_str()); } @@ -3330,13 +3279,13 @@ void CObjectSerializerImpl::serialImpl(NLMISC::IStream& stream, CObject*& data, { double value; stream.serial(value); - data = serializer->Factory ? serializer->Factory->newBasic("Number") : new CObjectNumber(0); + data = serializer->Factory ? serializer->Factory->newBasic("Number") : new CObjectNumber((sint64)0); ((CObjectNumber *) data)->set("", value); return; } case ObjectNumberZero: { - data = serializer->Factory ? serializer->Factory->newBasic("Number") : new CObjectNumber(0); + data = serializer->Factory ? serializer->Factory->newBasic("Number") : new CObjectNumber((sint64)0); ((CObjectNumber *) data)->set("", 0.0); return; } @@ -3344,8 +3293,8 @@ void CObjectSerializerImpl::serialImpl(NLMISC::IStream& stream, CObject*& data, { sint32 value; stream.serial(value); - data = serializer->Factory ? serializer->Factory->newBasic("Number") : new CObjectNumber(0); - ((CObjectNumber *) data)->set("", value); + data = serializer->Factory ? serializer->Factory->newBasic("Number") : new CObjectNumber((sint64)0); + ((CObjectNumber *) data)->set("", (sint64)value); return; } @@ -3353,8 +3302,8 @@ void CObjectSerializerImpl::serialImpl(NLMISC::IStream& stream, CObject*& data, { uint32 value; stream.serial(value); - data = serializer->Factory ? serializer->Factory->newBasic("Number") : new CObjectNumber(0); - ((CObjectNumber *) data)->set("", value); + data = serializer->Factory ? serializer->Factory->newBasic("Number") : new CObjectNumber((sint64)0); + ((CObjectNumber *) data)->set("", (sint64)value); return; } @@ -3362,8 +3311,8 @@ void CObjectSerializerImpl::serialImpl(NLMISC::IStream& stream, CObject*& data, { sint16 value; stream.serial(value); - data = serializer->Factory ? serializer->Factory->newBasic("Number") : new CObjectNumber(0); - ((CObjectNumber *) data)->set("", value); + data = serializer->Factory ? serializer->Factory->newBasic("Number") : new CObjectNumber((sint64)0); + ((CObjectNumber *) data)->set("", (sint64)value); return; } @@ -3371,8 +3320,8 @@ void CObjectSerializerImpl::serialImpl(NLMISC::IStream& stream, CObject*& data, { uint16 value; stream.serial(value); - data = serializer->Factory ? serializer->Factory->newBasic("Number") : new CObjectNumber(0); - ((CObjectNumber *) data)->set("", value); + data = serializer->Factory ? serializer->Factory->newBasic("Number") : new CObjectNumber((sint64)0); + ((CObjectNumber *) data)->set("", (sint64)value); return; } @@ -3380,8 +3329,8 @@ void CObjectSerializerImpl::serialImpl(NLMISC::IStream& stream, CObject*& data, { sint8 value; stream.serial(value); - data = serializer->Factory ? serializer->Factory->newBasic("Number") : new CObjectNumber(0); - ((CObjectNumber *) data)->set("", value); + data = serializer->Factory ? serializer->Factory->newBasic("Number") : new CObjectNumber((sint64)0); + ((CObjectNumber *) data)->set("", (sint64)value); return; } @@ -3389,8 +3338,8 @@ void CObjectSerializerImpl::serialImpl(NLMISC::IStream& stream, CObject*& data, { uint8 value; stream.serial(value); - data = serializer->Factory ? serializer->Factory->newBasic("Number") : new CObjectNumber(0); - ((CObjectNumber *) data)->set("", value); + data = serializer->Factory ? serializer->Factory->newBasic("Number") : new CObjectNumber((sint64)0); + ((CObjectNumber *) data)->set("", (sint64)value); return; } // Do not remove this or it would be impossible to load old session @@ -3398,8 +3347,8 @@ void CObjectSerializerImpl::serialImpl(NLMISC::IStream& stream, CObject*& data, { float value; stream.serial(value); - data = serializer->Factory ? serializer->Factory->newBasic("Number") : new CObjectNumber(0); - ((CObjectNumber *) data)->set("", value); + data = serializer->Factory ? serializer->Factory->newBasic("Number") : new CObjectNumber((sint64)0); + ((CObjectNumber *) data)->set("", (double)value); return; } @@ -3407,7 +3356,7 @@ void CObjectSerializerImpl::serialImpl(NLMISC::IStream& stream, CObject*& data, { double value; stream.serial(value); - data = serializer->Factory ? serializer->Factory->newBasic("Number") : new CObjectNumber(0); + data = serializer->Factory ? serializer->Factory->newBasic("Number") : new CObjectNumber((sint64)0); ((CObjectNumber *) data)->set("", value); return; } diff --git a/code/ryzom/common/src/game_share/object.h b/code/ryzom/common/src/game_share/object.h index 7d4ab1f49..806d790aa 100644 --- a/code/ryzom/common/src/game_share/object.h +++ b/code/ryzom/common/src/game_share/object.h @@ -206,7 +206,6 @@ public: virtual void inPlaceCopyTo(CObject &dest) const = 0; virtual void inPlaceCopy(const CObjectString &src); virtual void inPlaceCopy(const CObjectNumber &src); - virtual void inPlaceCopy(const CObjectInteger &src); virtual void inPlaceCopy(const CObjectTable &src); protected: void copyMismatchMsg(const CObject &src); @@ -287,78 +286,51 @@ class CObjectNumber : public CObject public: explicit CObjectNumber(double value); + explicit CObjectNumber(sint64 value); - virtual const char *getTypeAsString() const; + virtual const char *getTypeAsString() const NL_OVERRIDE; - virtual bool set(const std::string& key, double value); - virtual bool set(const std::string& key, const std::string&value); + virtual bool set(const std::string& key, sint64 value) NL_OVERRIDE; + virtual bool set(const std::string& key, double value) NL_OVERRIDE; + virtual bool set(const std::string& key, const std::string&value) NL_OVERRIDE; - virtual bool setObject(const std::string& key, CObject* value); + virtual bool setObject(const std::string& key, CObject* value) NL_OVERRIDE; - virtual CObject* clone() const; + virtual CObject* clone() const NL_OVERRIDE; - double getValue() const { return _Value; } + double getNumberValue() const { return m_IsInteger ? m_Value.Integer : m_Value.Number; } + sint64 getIntegerValue() const { return m_IsInteger ? m_Value.Integer : m_Value.Number; } - virtual void dump(const std::string prefix = "", uint depth = 0) const; + virtual void dump(const std::string prefix = "", uint depth = 0) const NL_OVERRIDE; - virtual bool equal(const CObject* other) const; + virtual bool equal(const CObject* other) const NL_OVERRIDE; protected: - virtual void doSerialize(std::string& out, CSerializeContext& context) const; - - virtual bool doIsNumber() const; - - virtual double doToNumber() const; - - virtual std::string doToString() const; - - virtual void inPlaceCopyTo(CObject &dest) const; - virtual void inPlaceCopy(const CObjectNumber &src); + virtual void doSerialize(std::string& out, CSerializeContext& context) const NL_OVERRIDE; - virtual void visitInternal(IObjectVisitor &visitor); + virtual bool doIsNumber() const NL_OVERRIDE; -private: - double _Value; + virtual double doToNumber() const NL_OVERRIDE; -}; + virtual bool doIsInteger() const NL_OVERRIDE; -class CObjectInteger : public CObject -{ + virtual sint64 doToInteger() const NL_OVERRIDE; -public: - explicit CObjectInteger(sint64 value); + virtual std::string doToString() const NL_OVERRIDE; - virtual const char *getTypeAsString() const; + virtual void inPlaceCopyTo(CObject &dest) const NL_OVERRIDE; + virtual void inPlaceCopy(const CObjectNumber &src) NL_OVERRIDE; - virtual bool set(const std::string& key, sint64 value); - virtual bool set(const std::string& key, const std::string &value); - - virtual bool setObject(const std::string& key, CObject* value); - - virtual CObject* clone() const; - - sint64 getValue() const { return _Value; } - - virtual void dump(const std::string prefix = "", uint depth = 0) const; - - virtual bool equal(const CObject* other) const; - -protected: - virtual void doSerialize(std::string& out, CSerializeContext& context) const; - - virtual bool doIsInteger() const; - - virtual sint64 doToInteger() const; - - virtual std::string doToString() const; - - virtual void inPlaceCopyTo(CObject &dest) const; - virtual void inPlaceCopy(const CObjectInteger &src); - - virtual void visitInternal(IObjectVisitor &visitor); + virtual void visitInternal(IObjectVisitor &visitor) NL_OVERRIDE; private: - sint64 _Value; + bool m_IsInteger; + union + { + double Number; + sint64 Integer; + } m_Value; + }; class CObjectTable: public CObject