From 70d0d5ecc9c1fc7f4397a4b24836acb40dd69188 Mon Sep 17 00:00:00 2001 From: Michael Ragazzon Date: Fri, 22 Sep 2023 18:17:21 +0200 Subject: [PATCH] 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). --- Include/RmlUi/Core/Traits.h | 16 ++++++++++++++++ Samples/basic/demo/src/main.cpp | 10 +++++----- Source/Core/Context.cpp | 2 +- Source/Core/DataViewDefault.cpp | 16 +++++----------- Source/Core/ElementDocument.cpp | 2 +- Source/Core/ElementInstancer.cpp | 2 +- Source/Core/Layout/BlockContainer.cpp | 2 +- Source/Core/Layout/InlineLevelBox.cpp | 4 +--- Source/Core/Layout/LineBox.cpp | 4 ++-- 9 files changed, 33 insertions(+), 25 deletions(-) diff --git a/Include/RmlUi/Core/Traits.h b/Include/RmlUi/Core/Traits.h index 2558a7daf..b3deefb68 100644 --- a/Include/RmlUi/Core/Traits.h +++ b/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 @@ -136,6 +137,13 @@ Derived rmlui_dynamic_cast(Base base_instance) return nullptr; } +template +Derived rmlui_static_cast(Base base_instance) +{ + static_assert(std::is_pointer::value && std::is_pointer::value, "rmlui_static_cast can only cast pointer types"); + return static_cast(base_instance); +} + template const char* rmlui_type_name(const T& /*var*/) { @@ -162,6 +170,14 @@ Derived rmlui_dynamic_cast(Base base_instance) return dynamic_cast(base_instance); } +template +Derived rmlui_static_cast(Base base_instance) +{ + static_assert(std::is_pointer::value && std::is_pointer::value, "rmlui_static_cast can only cast pointer types"); + RMLUI_ASSERT(dynamic_cast(base_instance)); + return static_cast(base_instance); +} + template const char* rmlui_type_name(const T& var) { diff --git a/Samples/basic/demo/src/main.cpp b/Samples/basic/demo/src/main.cpp index 79ccf6ce7..fb6491838 100644 --- a/Samples/basic/demo/src/main.cpp +++ b/Samples/basic/demo/src/main.cpp @@ -60,7 +60,7 @@ class DemoWindow : public Rml::EventListener { document->GetElementById("title")->SetInnerRML(title); // Add sandbox default text. - if (auto source = static_cast(document->GetElementById("sandbox_rml_source"))) + if (auto source = rmlui_dynamic_cast(document->GetElementById("sandbox_rml_source"))) { auto value = source->GetValue(); value += "

Write your RML here

\n\n"; @@ -100,7 +100,7 @@ class DemoWindow : public Rml::EventListener { } // Add sandbox style sheet text. - if (auto source = static_cast(document->GetElementById("sandbox_rcss_source"))) + if (auto source = rmlui_dynamic_cast(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 @@ class DemoEventListener : public Rml::EventListener { } else if (value == "tween_duration") { - float value = (float)std::atof(static_cast(element)->GetValue().c_str()); + float value = (float)std::atof(rmlui_static_cast(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 @@ class DemoEventListener : public Rml::EventListener { } else if (value == "set_sandbox_body") { - if (auto source = static_cast(element->GetElementById("sandbox_rml_source"))) + if (auto source = rmlui_dynamic_cast(element->GetElementById("sandbox_rml_source"))) { auto value = source->GetValue(); demo_window->SetSandboxBody(value); @@ -389,7 +389,7 @@ class DemoEventListener : public Rml::EventListener { } else if (value == "set_sandbox_style") { - if (auto source = static_cast(element->GetElementById("sandbox_rcss_source"))) + if (auto source = rmlui_dynamic_cast(element->GetElementById("sandbox_rcss_source"))) { auto value = source->GetValue(); demo_window->SetSandboxStylesheet(value); diff --git a/Source/Core/Context.cpp b/Source/Core/Context.cpp index f86d79a73..04005883c 100644 --- a/Source/Core/Context.cpp +++ b/Source/Core/Context.cpp @@ -282,7 +282,7 @@ ElementDocument* Context::LoadDocument(Stream* stream) if (!element) return nullptr; - ElementDocument* document = static_cast(element.get()); + ElementDocument* document = rmlui_static_cast(element.get()); root->AppendChild(std::move(element)); diff --git a/Source/Core/DataViewDefault.cpp b/Source/Core/DataViewDefault.cpp index d04123683..4c67271fb 100644 --- a/Source/Core/DataViewDefault.cpp +++ b/Source/Core/DataViewDefault.cpp @@ -391,18 +391,12 @@ bool DataViewText::Update(DataModel& model) { if (Element* element = GetElement()) { - RMLUI_ASSERTMSG(rmlui_dynamic_cast(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(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(element)->SetText(text); } else { diff --git a/Source/Core/ElementDocument.cpp b/Source/Core/ElementDocument.cpp index 04ccf8f6b..076445fab 100644 --- a/Source/Core/ElementDocument.cpp +++ b/Source/Core/ElementDocument.cpp @@ -221,7 +221,7 @@ void ElementDocument::ReloadStyleSheet() return; } - SetStyleSheetContainer(static_cast(temp_doc.get())->style_sheet_container); + SetStyleSheetContainer(rmlui_static_cast(temp_doc.get())->style_sheet_container); } void ElementDocument::DirtyMediaQueries() diff --git a/Source/Core/ElementInstancer.cpp b/Source/Core/ElementInstancer.cpp index 30d65aa35..46fda3961 100644 --- a/Source/Core/ElementInstancer.cpp +++ b/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(element)); + pool_text_default.DestroyAndDeallocate(rmlui_static_cast(element)); } } // namespace Rml diff --git a/Source/Core/Layout/BlockContainer.cpp b/Source/Core/Layout/BlockContainer.cpp index bbbfce5dc..fc4e13e05 100644 --- a/Source/Core/Layout/BlockContainer.cpp +++ b/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(child_boxes.back().get()); + return rmlui_static_cast(child_boxes.back().get()); return nullptr; } diff --git a/Source/Core/Layout/InlineLevelBox.cpp b/Source/Core/Layout/InlineLevelBox.cpp index 18f3b441d..449c83101 100644 --- a/Source/Core/Layout/InlineLevelBox.cpp +++ b/Source/Core/Layout/InlineLevelBox.cpp @@ -227,8 +227,6 @@ String InlineLevelBox_Text::DebugDumpNameValue() const ElementText* InlineLevelBox_Text::GetTextElement() { - RMLUI_ASSERT(rmlui_dynamic_cast(GetElement())); - - return static_cast(GetElement()); + return rmlui_static_cast(GetElement()); } } // namespace Rml diff --git a/Source/Core/Layout/LineBox.cpp b/Source/Core/Layout/LineBox.cpp index ca28ce416..acc21d59b 100644 --- a/Source/Core/Layout/LineBox.cpp +++ b/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(box)); + RMLUI_ASSERT(rmlui_static_cast(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(fragments[open_fragments_leaf].box); + return rmlui_static_cast(fragments[open_fragments_leaf].box); } bool LineBox::CanCollapseLine() const