瀏覽代碼

Add rmlui_static_cast to assert validity of down casts, see #514

Employ it around the library for extra debug checks (only with rtti enabled).
Michael Ragazzon 2 年之前
父節點
當前提交
70d0d5ecc9

+ 16 - 0
Include/RmlUi/Core/Traits.h

@@ -30,6 +30,7 @@
 #define RMLUI_CORE_TRAITS_H
 
 #include "../Config/Config.h"
+#include "Debug.h"
 #include "Header.h"
 #include <type_traits>
 
@@ -136,6 +137,13 @@ Derived rmlui_dynamic_cast(Base base_instance)
 		return nullptr;
 }
 
+template <class Derived, class Base>
+Derived rmlui_static_cast(Base base_instance)
+{
+	static_assert(std::is_pointer<Derived>::value && std::is_pointer<Base>::value, "rmlui_static_cast can only cast pointer types");
+	return static_cast<Derived>(base_instance);
+}
+
 template <class T>
 const char* rmlui_type_name(const T& /*var*/)
 {
@@ -162,6 +170,14 @@ Derived rmlui_dynamic_cast(Base base_instance)
 	return dynamic_cast<Derived>(base_instance);
 }
 
+template <class Derived, class Base>
+Derived rmlui_static_cast(Base base_instance)
+{
+	static_assert(std::is_pointer<Derived>::value && std::is_pointer<Base>::value, "rmlui_static_cast can only cast pointer types");
+	RMLUI_ASSERT(dynamic_cast<Derived>(base_instance));
+	return static_cast<Derived>(base_instance);
+}
+
 template <class T>
 const char* rmlui_type_name(const T& var)
 {

+ 5 - 5
Samples/basic/demo/src/main.cpp

@@ -60,7 +60,7 @@ public:
 			document->GetElementById("title")->SetInnerRML(title);
 
 			// Add sandbox default text.
-			if (auto source = static_cast<Rml::ElementFormControl*>(document->GetElementById("sandbox_rml_source")))
+			if (auto source = rmlui_dynamic_cast<Rml::ElementFormControl*>(document->GetElementById("sandbox_rml_source")))
 			{
 				auto value = source->GetValue();
 				value += "<p>Write your RML here</p>\n\n<!-- <img src=\"assets/high_scores_alien_1.tga\"/> -->";
@@ -100,7 +100,7 @@ public:
 			}
 
 			// Add sandbox style sheet text.
-			if (auto source = static_cast<Rml::ElementFormControl*>(document->GetElementById("sandbox_rcss_source")))
+			if (auto source = rmlui_dynamic_cast<Rml::ElementFormControl*>(document->GetElementById("sandbox_rcss_source")))
 			{
 				Rml::String value = "/* Write your RCSS here */\n\n/* body { color: #fea; background: #224; }\nimg { image-color: red; } */";
 				source->SetValue(value);
@@ -332,7 +332,7 @@ public:
 		}
 		else if (value == "tween_duration")
 		{
-			float value = (float)std::atof(static_cast<Rml::ElementFormControl*>(element)->GetValue().c_str());
+			float value = (float)std::atof(rmlui_static_cast<Rml::ElementFormControl*>(element)->GetValue().c_str());
 			tweening_parameters.duration = value;
 			if (auto el_duration = element->GetElementById("duration"))
 				el_duration->SetInnerRML(CreateString(20, "%2.2f", value));
@@ -381,7 +381,7 @@ public:
 		}
 		else if (value == "set_sandbox_body")
 		{
-			if (auto source = static_cast<Rml::ElementFormControl*>(element->GetElementById("sandbox_rml_source")))
+			if (auto source = rmlui_dynamic_cast<Rml::ElementFormControl*>(element->GetElementById("sandbox_rml_source")))
 			{
 				auto value = source->GetValue();
 				demo_window->SetSandboxBody(value);
@@ -389,7 +389,7 @@ public:
 		}
 		else if (value == "set_sandbox_style")
 		{
-			if (auto source = static_cast<Rml::ElementFormControl*>(element->GetElementById("sandbox_rcss_source")))
+			if (auto source = rmlui_dynamic_cast<Rml::ElementFormControl*>(element->GetElementById("sandbox_rcss_source")))
 			{
 				auto value = source->GetValue();
 				demo_window->SetSandboxStylesheet(value);

+ 1 - 1
Source/Core/Context.cpp

@@ -282,7 +282,7 @@ ElementDocument* Context::LoadDocument(Stream* stream)
 	if (!element)
 		return nullptr;
 
-	ElementDocument* document = static_cast<ElementDocument*>(element.get());
+	ElementDocument* document = rmlui_static_cast<ElementDocument*>(element.get());
 
 	root->AppendChild(std::move(element));
 

+ 5 - 11
Source/Core/DataViewDefault.cpp

@@ -391,18 +391,12 @@ bool DataViewText::Update(DataModel& model)
 	{
 		if (Element* element = GetElement())
 		{
-			RMLUI_ASSERTMSG(rmlui_dynamic_cast<ElementText*>(element),
-				"Somehow the element type was changed from ElementText since construction of the view. Should not be possible?");
+			String new_text = BuildText();
+			String text;
+			if (SystemInterface* system_interface = GetSystemInterface())
+				system_interface->TranslateString(text, new_text);
 
-			if (ElementText* text_element = static_cast<ElementText*>(element))
-			{
-				String new_text = BuildText();
-
-				String text;
-				if (SystemInterface* system_interface = GetSystemInterface())
-					system_interface->TranslateString(text, new_text);
-				text_element->SetText(text);
-			}
+			rmlui_static_cast<ElementText*>(element)->SetText(text);
 		}
 		else
 		{

+ 1 - 1
Source/Core/ElementDocument.cpp

@@ -221,7 +221,7 @@ void ElementDocument::ReloadStyleSheet()
 		return;
 	}
 
-	SetStyleSheetContainer(static_cast<ElementDocument*>(temp_doc.get())->style_sheet_container);
+	SetStyleSheetContainer(rmlui_static_cast<ElementDocument*>(temp_doc.get())->style_sheet_container);
 }
 
 void ElementDocument::DirtyMediaQueries()

+ 1 - 1
Source/Core/ElementInstancer.cpp

@@ -71,7 +71,7 @@ ElementPtr ElementInstancerText::InstanceElement(Element* /*parent*/, const Stri
 
 void ElementInstancerText::ReleaseElement(Element* element)
 {
-	pool_text_default.DestroyAndDeallocate(static_cast<ElementText*>(element));
+	pool_text_default.DestroyAndDeallocate(rmlui_static_cast<ElementText*>(element));
 }
 
 } // namespace Rml

+ 1 - 1
Source/Core/Layout/BlockContainer.cpp

@@ -460,7 +460,7 @@ InlineContainer* BlockContainer::GetOpenInlineContainer()
 const InlineContainer* BlockContainer::GetOpenInlineContainer() const
 {
 	if (!child_boxes.empty() && child_boxes.back()->GetType() == Type::InlineContainer)
-		return static_cast<InlineContainer*>(child_boxes.back().get());
+		return rmlui_static_cast<InlineContainer*>(child_boxes.back().get());
 	return nullptr;
 }
 

+ 1 - 3
Source/Core/Layout/InlineLevelBox.cpp

@@ -227,8 +227,6 @@ String InlineLevelBox_Text::DebugDumpNameValue() const
 
 ElementText* InlineLevelBox_Text::GetTextElement()
 {
-	RMLUI_ASSERT(rmlui_dynamic_cast<ElementText*>(GetElement()));
-
-	return static_cast<ElementText*>(GetElement());
+	return rmlui_static_cast<ElementText*>(GetElement());
 }
 } // namespace Rml

+ 2 - 2
Source/Core/Layout/LineBox.cpp

@@ -92,7 +92,7 @@ bool LineBox::AddBox(InlineLevelBox* box, InlineLayoutMode layout_mode, LayoutOv
 	case FragmentType::InlineBox:
 	{
 		RMLUI_ASSERT(constructor.layout_width < 0.f);
-		RMLUI_ASSERT(rmlui_dynamic_cast<InlineBox*>(box));
+		RMLUI_ASSERT(rmlui_static_cast<InlineBox*>(box));
 
 		open_fragments_leaf = fragment_index;
 		open_spacing_left += box->GetSpacingLeft();
@@ -389,7 +389,7 @@ InlineBox* LineBox::GetOpenInlineBox()
 	if (open_fragments_leaf == RootFragmentIndex)
 		return nullptr;
 
-	return static_cast<InlineBox*>(fragments[open_fragments_leaf].box);
+	return rmlui_static_cast<InlineBox*>(fragments[open_fragments_leaf].box);
 }
 
 bool LineBox::CanCollapseLine() const