Explorar o código

Make variants and properties movable

Michael Ragazzon %!s(int64=6) %!d(string=hai) anos
pai
achega
ce02e7c1ec

+ 0 - 2
Include/RmlUi/Core/Property.h

@@ -99,8 +99,6 @@ public:
 	template<typename EnumType, typename = typename std::enable_if< std::is_enum<EnumType>::value, EnumType >::type>
 	Property(EnumType value) : value(static_cast<int>(value)), unit(KEYWORD), specificity(-1) {}
 
-	~Property();	
-
 	/// Get the value of the property as a string.
 	String ToString() const;
 

+ 0 - 1
Include/RmlUi/Core/PropertyDictionary.h

@@ -47,7 +47,6 @@ class RMLUICORE_API PropertyDictionary
 {
 public:
 	PropertyDictionary();
-	~PropertyDictionary();
 
 	/// Sets a property on the dictionary. Any existing property with a similar name will be overwritten.
 	/// @param[in] name The name of the property to add.

+ 37 - 28
Include/RmlUi/Core/Variant.h

@@ -49,17 +49,6 @@ namespace Core {
 class RMLUICORE_API Variant
 {
 public:
-	Variant();
-	/// Templatised constructors don't work for the copy constructor, so we have to define it
-	/// explicitly.
-	Variant(const Variant&);
-	/// Constructs a variant with internal data.
-	/// @param[in] t Data of a supported type to set on the variant.
-	template< typename T >
-	Variant(const T& t);
-
-	~Variant();
-
 	/// Type of data stored in the variant.
 	enum Type
 	{
@@ -67,7 +56,7 @@ public:
 		BYTE = 'b',
 		CHAR = 'c',
 		FLOAT = 'f',
-		INT = 'i', 
+		INT = 'i',
 		STRING = 's',
 		WORD = 'w',
 		VECTOR2 = '2',
@@ -80,15 +69,32 @@ public:
 		TRANSITIONLIST = 'T',
 		ANIMATIONLIST = 'A',
 		DECORATORLIST = 'D',
-		VOIDPTR = '*',			
+		VOIDPTR = '*',
 	};
 
-	/// Clears the data structure stored by the variant.
+	Variant();
+	Variant(const Variant&);
+	Variant(Variant&&);
+	Variant& operator=(const Variant& copy);
+	Variant& operator=(Variant&& other);
+	~Variant();
+
+	// Construct by variant type
+	template< typename T >
+	Variant(const T& t);
+	template< typename T >
+	Variant(T&& t);
+
+	// Assign by variant type
+	template<typename T>
+	Variant& operator=(const T& t);
+	template<typename T>
+	Variant& operator=(T&& t);
+
 	void Clear();
 
-	/// Gets the current internal representation type.
-	/// @return The type of data stored in the variant internally.
 	inline Type GetType() const;
+
 	/// Templatised data accessor. TypeConverters will be used to attempt to convert from the
 	/// internal representation to the requested representation.
 	/// @param[in] default_value The value returned if the conversion failed.
@@ -103,14 +109,10 @@ public:
 	template< typename T >
 	bool GetInto(T& value) const;
 
-	/// Copy another variant.
-	/// @param[in] copy Variant to copy.
-	Variant& operator=(const Variant& copy);
-
-	/// Clear and set a new value to this variant.
-	/// @param[in] t New value to set.
-	template<typename T>
-	Variant& operator=(const T& t);
+	/// Returns a reference to the variants underlying type.
+	/// @warning: Undefined behavior if T does not represent the underlying type of the variant.
+	template< typename T>
+	const T& GetReference() const;
 
 	bool operator==(const Variant& other) const;
 	bool operator!=(const Variant& other) const { return !(*this == other); }
@@ -120,6 +122,7 @@ private:
 	/// Copy another variant's data to this variant.
 	/// @warning Does not clear existing data.
 	void Set(const Variant& copy);
+	void Set(Variant&& other);
 
 	void Set(const byte value);
 	void Set(const char value);
@@ -128,17 +131,23 @@ private:
 	void Set(const word value);
 	void Set(const char* value);
 	void Set(void* value);
-	void Set(const String& value);
 	void Set(const Vector2f& value);
 	void Set(const Vector3f& value);
 	void Set(const Vector4f& value);
+	void Set(const Colourf& value);
+	void Set(const Colourb& value);
+	void Set(ScriptInterface* value);
+
+	void Set(const String& value);
+	void Set(String&& value);
 	void Set(const TransformRef& value);
+	void Set(TransformRef&& value);
 	void Set(const TransitionList& value);
+	void Set(TransitionList&& value);
 	void Set(const AnimationList& value);
+	void Set(AnimationList&& value);
 	void Set(const DecoratorList& value);
-	void Set(const Colourf& value);
-	void Set(const Colourb& value);
-	void Set(ScriptInterface* value);
+	void Set(DecoratorList&& value);
 	
 	static constexpr size_t LOCAL_DATA_SIZE = sizeof(TransitionList);
 

+ 22 - 0
Include/RmlUi/Core/Variant.inl

@@ -41,6 +41,13 @@ Variant::Variant(const T& t) : type(NONE)
 	Set(t);
 }
 
+// Constructs a variant by moving data
+template< typename T >
+Variant::Variant(T&& t) : type(NONE)
+{
+	Set(std::move(t));
+}
+
 // Clear and set new value
 template< typename T >
 Variant& Variant::operator=(const T& t)
@@ -50,6 +57,15 @@ Variant& Variant::operator=(const T& t)
 	return *this;
 }
 
+// Clear and set new value
+template< typename T >
+Variant& Variant::operator=(T&& t)
+{
+	Clear();
+	Set(std::move(t));
+	return *this;
+}
+
 // Templatised data accessor.
 template< typename T >
 bool Variant::GetInto(T& value) const
@@ -139,5 +155,11 @@ T Variant::Get(T default_value) const
 	return default_value;
 }
 
+template<typename T>
+inline const T& Variant::GetReference() const
+{
+	return *(T*)data;
+}
+
 }
 }

+ 3 - 2
Source/Controls/InputTypeRange.cpp

@@ -67,10 +67,11 @@ bool InputTypeRange::OnAttributeChange(const Core::ElementAttributes& changed_at
 	bool dirty_layout = false;
 
 	// Check if maxlength has been defined.
-	auto it_orientation = changed_attributes.find("orientation");
+	static const Core::String str_orientation = "orientation";
+	auto it_orientation = changed_attributes.find(str_orientation);
 	if (it_orientation != changed_attributes.end())
 	{
-		widget->SetOrientation(it_orientation->second.Get<Rml::Core::String>("horizontal") == "horizontal" ? WidgetSliderInput::HORIZONTAL : WidgetSliderInput::VERTICAL);
+		widget->SetOrientation(it_orientation->second.Get<Rml::Core::String>(str_orientation) == str_orientation ? WidgetSliderInput::HORIZONTAL : WidgetSliderInput::VERTICAL);
 		dirty_layout = true;
 	}
 

+ 6 - 6
Source/Core/ElementAnimation.cpp

@@ -118,8 +118,8 @@ static Property InterpolateProperties(const Property & p0, const Property& p1, f
 	{
 		using namespace Rml::Core::Transforms;
 
-		auto t0 = p0.value.Get<TransformRef>();
-		auto t1 = p1.value.Get<TransformRef>();
+		auto& t0 = p0.value.GetReference<TransformRef>();
+		auto& t1 = p1.value.GetReference<TransformRef>();
 
 		const auto& prim0 = t0->GetPrimitives();
 		const auto& prim1 = t1->GetPrimitives();
@@ -321,8 +321,8 @@ static bool PrepareTransforms(std::vector<AnimationKey>& keys, Element& element,
 		if(prop0.unit != Property::TRANSFORM || prop1.unit != Property::TRANSFORM)
 			return false;
 
-		auto t0 = prop0.value.Get<TransformRef>();
-		auto t1 = prop1.value.Get<TransformRef>();
+		auto& t0 = prop0.value.GetReference<TransformRef>();
+		auto& t1 = prop1.value.GetReference<TransformRef>();
 
 		auto result = PrepareTransformPair(*t0, *t1, element);
 
@@ -373,7 +373,7 @@ bool ElementAnimation::InternalAddKey(float time, const Property& property, Twee
 
 	if (key.property.unit == Property::TRANSFORM)
 	{
-		if (!key.property.value.Get<TransformRef>())
+		if (!key.property.value.GetReference<TransformRef>())
 			key.property.value = std::make_shared<Transform>();
 	}
 
@@ -399,7 +399,7 @@ bool ElementAnimation::AddKey(float target_time, const Property & in_property, E
 	if (property.unit == Property::TRANSFORM)
 	{
 		bool must_decompose = false;
-		Transform& transform = *property.value.Get<TransformRef>();
+		Transform& transform = *property.value.GetReference<TransformRef>();
 
 		for (auto& primitive : transform.GetPrimitives())
 		{

+ 0 - 4
Source/Core/Property.cpp

@@ -39,10 +39,6 @@ Property::Property() : unit(UNKNOWN), specificity(-1)
 	parser_index = -1;
 }
 
-Property::~Property()
-{
-}
-
 String Property::ToString() const
 {
 	if (definition == NULL)

+ 0 - 4
Source/Core/PropertyDictionary.cpp

@@ -36,10 +36,6 @@ PropertyDictionary::PropertyDictionary()
 {
 }
 
-PropertyDictionary::~PropertyDictionary()
-{
-}
-
 // Sets a property on the dictionary. Any existing property with a similar name will be overwritten.
 void PropertyDictionary::SetProperty(PropertyId id, const Property& property)
 {

+ 140 - 32
Source/Core/Variant.cpp

@@ -45,11 +45,16 @@ Variant::Variant() : type(NONE)
 	static_assert(sizeof(DecoratorList) <= LOCAL_DATA_SIZE, "Local data too small for DecoratorList");
 }
 
-Variant::Variant( const Variant& copy ) : type(NONE)
+Variant::Variant(const Variant& copy) : type(NONE)
 {
 	Set(copy);
 }
 
+Variant::Variant(Variant&& other) : type(NONE)
+{
+	Set(std::move(other));
+}
+
 Variant::~Variant() 
 {
 	Clear();
@@ -133,9 +138,42 @@ void Variant::Set(const Variant& copy)
 
 	default:
 		memcpy(data, copy.data, LOCAL_DATA_SIZE);
+		type = copy.type;
+		break;
+	}
+	RMLUI_ASSERT(type == copy.type);
+}
+
+void Variant::Set(Variant&& other)
+{
+	switch (other.type)
+	{
+	case STRING:
+		Set(std::move(*(String*)other.data));
+		break;
+
+	case TRANSFORMREF:
+		Set(std::move(*(TransformRef*)other.data));
+		break;
+
+	case TRANSITIONLIST:
+		Set(std::move(*(TransitionList*)other.data));
+		break;
+
+	case ANIMATIONLIST:
+		Set(std::move(*(AnimationList*)other.data));
+		break;
+
+	case DECORATORLIST:
+		Set(std::move(*(DecoratorList*)other.data));
+		break;
+
+	default:
+		memcpy(data, other.data, LOCAL_DATA_SIZE);
+		type = other.type;
 		break;
 	}
-	type = copy.type;
+	RMLUI_ASSERT(type == other.type);
 }
 
 void Variant::Set(const byte value)
@@ -161,20 +199,6 @@ void Variant::Set(const int value)
 	type = INT;
 	SET_VARIANT(int);
 }
-
-void Variant::Set(const String& value) 
-{
-	if (type == STRING)
-	{
-		(*(String*)data) = value;
-	}
-	else
-	{
-		type = STRING;
-		new(data) String(value);
-	}
-}
-
 void Variant::Set(const word value)
 {
 	type = WORD;
@@ -210,6 +234,51 @@ void Variant::Set(const Vector4f& value)
 	SET_VARIANT(Vector4f);
 }
 
+void Variant::Set(const Colourf& value)
+{
+	type = COLOURF;
+	SET_VARIANT(Colourf);
+}
+
+void Variant::Set(const Colourb& value)
+{
+	type = COLOURB;
+	SET_VARIANT(Colourb);
+}
+
+void Variant::Set(ScriptInterface* value)
+{
+	type = SCRIPTINTERFACE;
+	memcpy(data, &value, sizeof(ScriptInterface*));
+}
+
+
+void Variant::Set(const String& value)
+{
+	if (type == STRING)
+	{
+		(*(String*)data) = value;
+	}
+	else
+	{
+		type = STRING;
+		new(data) String(value);
+	}
+}
+void Variant::Set(String&& value)
+{
+	if (type == STRING)
+	{
+		(*(String*)data) = std::move(value);
+	}
+	else
+	{
+		type = STRING;
+		new(data) String(std::move(value));
+	}
+}
+
+
 void Variant::Set(const TransformRef& value)
 {
 	if (type == TRANSFORMREF)
@@ -222,6 +291,18 @@ void Variant::Set(const TransformRef& value)
 		new(data) TransformRef(value);
 	}
 }
+void Variant::Set(TransformRef&& value)
+{
+	if (type == TRANSFORMREF)
+	{
+		(*(TransformRef*)data) = std::move(value);
+	}
+	else
+	{
+		type = TRANSFORMREF;
+		new(data) TransformRef(std::move(value));
+	}
+}
 
 void Variant::Set(const TransitionList& value)
 {
@@ -235,6 +316,19 @@ void Variant::Set(const TransitionList& value)
 		new(data) TransitionList(value);
 	}
 }
+void Variant::Set(TransitionList&& value)
+{
+	if (type == TRANSITIONLIST)
+	{
+		(*(TransitionList*)data) = std::move(value);
+	}
+	else
+	{
+		type = TRANSITIONLIST;
+		new(data) TransitionList(std::move(value));
+	}
+}
+
 void Variant::Set(const AnimationList& value)
 {
 	if (type == ANIMATIONLIST)
@@ -247,6 +341,18 @@ void Variant::Set(const AnimationList& value)
 		new(data) AnimationList(value);
 	}
 }
+void Variant::Set(AnimationList&& value)
+{
+	if (type == ANIMATIONLIST)
+	{
+		(*(AnimationList*)data) = std::move(value);
+	}
+	else
+	{
+		type = ANIMATIONLIST;
+		new(data) AnimationList(std::move(value));
+	}
+}
 
 void Variant::Set(const DecoratorList& value)
 {
@@ -260,23 +366,17 @@ void Variant::Set(const DecoratorList& value)
 		new(data) DecoratorList(value);
 	}
 }
-
-void Variant::Set(const Colourf& value)
+void Variant::Set(DecoratorList&& value)
 {
-	type = COLOURF;
-	SET_VARIANT(Colourf);
-}
-
-void Variant::Set(const Colourb& value)
-{
-	type = COLOURB;
-	SET_VARIANT(Colourb);
-}
-
-void Variant::Set(ScriptInterface* value) 
-{
-	type = SCRIPTINTERFACE;
-	memcpy(data, &value, sizeof(ScriptInterface*));
+	if (type == DECORATORLIST)
+	{
+		(*(DecoratorList*)data) = std::move(value);
+	}
+	else
+	{
+		type = DECORATORLIST;
+		new(data) DecoratorList(std::move(value));
+	}
 }
 
 Variant& Variant::operator=(const Variant& copy)
@@ -287,6 +387,14 @@ Variant& Variant::operator=(const Variant& copy)
 	return *this;
 }
 
+Variant& Variant::operator=(Variant&& other)
+{
+	if (other.type != type)
+		Clear();
+	Set(std::move(other));
+	return *this;
+}
+
 #define DEFAULT_VARIANT_COMPARE(TYPE) static_cast<TYPE>(*(TYPE*)data) == static_cast<TYPE>(*(TYPE*)other.data)
 
 bool Variant::operator==(const Variant & other) const