diff --git a/source/graphics/ShaderManager.cpp b/source/graphics/ShaderManager.cpp index fce3296c93..bd823ffc7b 100644 --- a/source/graphics/ShaderManager.cpp +++ b/source/graphics/ShaderManager.cpp @@ -132,7 +132,7 @@ bool CShaderManager::NewProgram(const char* name, const CShaderDefines& baseDefi XMLWriter_File shaderFile; shaderFile.SetPrettyPrint(false); shaderFile.XMB(XeroFile); - bool ok = CXeromyces::ValidateEncoded("shader", wstring_from_utf8(name), shaderFile.GetOutput()); + bool ok = CXeromyces::ValidateEncoded("shader", name, shaderFile.GetOutput()); if (!ok) return false; } diff --git a/source/graphics/tests/test_MeshManager.h b/source/graphics/tests/test_MeshManager.h index cb00f96f8e..06ecf0171b 100644 --- a/source/graphics/tests/test_MeshManager.h +++ b/source/graphics/tests/test_MeshManager.h @@ -229,7 +229,7 @@ public: RelaxNGValidator v; TS_ASSERT(v.LoadGrammar("")); - TS_ASSERT(v.Validate(L"doc", L"2.0")); + TS_ASSERT(v.Validate("doc", "2.0")); copyFile(srcDAE, testDAE); copyFile(srcSkeletonDefs, testSkeletonDefs); @@ -237,7 +237,7 @@ public: TS_ASSERT(modeldef); if (modeldef) TS_ASSERT_PATH_EQUALS(modeldef->GetName(), testBase); - TS_ASSERT(v.Validate(L"doc", L"2.0")); + TS_ASSERT(v.Validate("doc", "2.0")); } diff --git a/source/pch/simulation2/precompiled.h b/source/pch/simulation2/precompiled.h index 47806de19e..4f11431259 100644 --- a/source/pch/simulation2/precompiled.h +++ b/source/pch/simulation2/precompiled.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -23,7 +23,6 @@ // The simulation has many header files (component interfaces) which are quick to compile on their own // but bring in a lot of headers indirectly. Adding these to the precompiled header // cuts down compilation time by about half. -#include "simulation2/system/Component.h" #include "simulation2/system/Interface.h" #include "simulation2/system/InterfaceScripted.h" #include "maths/FixedVector2D.h" diff --git a/source/ps/XML/RelaxNG.cpp b/source/ps/XML/RelaxNG.cpp index a09688cef6..a8c1987572 100644 --- a/source/ps/XML/RelaxNG.cpp +++ b/source/ps/XML/RelaxNG.cpp @@ -127,14 +127,14 @@ bool RelaxNGValidator::LoadGrammarFile(const PIVFS& vfs, const VfsPath& grammarP return LoadGrammar(file.DecodeUTF8()); } -bool RelaxNGValidator::Validate(const std::wstring& filename, const std::wstring& document) const +bool RelaxNGValidator::Validate(const std::string& filename, const std::string& document) const { - std::string docutf8 = "" + utf8_from_wstring(document); + std::string docutf8 = "" + document; return ValidateEncoded(filename, docutf8); } -bool RelaxNGValidator::ValidateEncoded(const std::wstring& filename, const std::string& document) const +bool RelaxNGValidator::ValidateEncoded(const std::string& filename, const std::string& document) const { TIMER_ACCRUE(xml_validation); @@ -144,10 +144,10 @@ bool RelaxNGValidator::ValidateEncoded(const std::wstring& filename, const std:: return false; } - xmlDocPtr doc = xmlReadMemory(document.c_str(), (int)document.size(), utf8_from_wstring(filename).c_str(), NULL, XML_PARSE_NONET); + xmlDocPtr doc = xmlReadMemory(document.c_str(), (int)document.size(), filename.c_str(), NULL, XML_PARSE_NONET); if (doc == NULL) { - LOGERROR("RelaxNGValidator: Failed to parse document '%s'", utf8_from_wstring(filename).c_str()); + LOGERROR("RelaxNGValidator: Failed to parse document '%s'", filename.c_str()); return false; } diff --git a/source/ps/XML/RelaxNG.h b/source/ps/XML/RelaxNG.h index 0bc80748f0..a794c1e163 100644 --- a/source/ps/XML/RelaxNG.h +++ b/source/ps/XML/RelaxNG.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -40,9 +40,9 @@ public: MD5 GetGrammarHash() const { return m_Hash; } - bool Validate(const std::wstring& filename, const std::wstring& document) const; + bool Validate(const std::string& filename, const std::string& document) const; - bool ValidateEncoded(const std::wstring& filename, const std::string& document) const; + bool ValidateEncoded(const std::string& filename, const std::string& document) const; bool ValidateEncoded(xmlDocPtr doc) const; diff --git a/source/ps/XML/Xeromyces.cpp b/source/ps/XML/Xeromyces.cpp index b080d4766f..580feb686f 100644 --- a/source/ps/XML/Xeromyces.cpp +++ b/source/ps/XML/Xeromyces.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -92,7 +92,7 @@ bool CXeromyces::AddValidator(const PIVFS& vfs, const std::string& name, const V return true; } -bool CXeromyces::ValidateEncoded(const std::string& name, const std::wstring& filename, const std::string& document) +bool CXeromyces::ValidateEncoded(const std::string& name, const std::string& filename, const std::string& document) { std::lock_guard lock(g_ValidatorCacheLock); return GetValidator(name).ValidateEncoded(filename, document); diff --git a/source/ps/XML/Xeromyces.h b/source/ps/XML/Xeromyces.h index 4cc3f7b71e..9d81007b6e 100644 --- a/source/ps/XML/Xeromyces.h +++ b/source/ps/XML/Xeromyces.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -74,7 +74,7 @@ public: static bool AddValidator(const PIVFS& vfs, const std::string& name, const VfsPath& grammarPath); - static bool ValidateEncoded(const std::string& name, const std::wstring& filename, const std::string& document); + static bool ValidateEncoded(const std::string& name, const std::string& filename, const std::string& document); private: static RelaxNGValidator& GetValidator(const std::string& name); diff --git a/source/ps/XML/tests/test_RelaxNG.h b/source/ps/XML/tests/test_RelaxNG.h index 9d05428b5f..6fa3ba0263 100644 --- a/source/ps/XML/tests/test_RelaxNG.h +++ b/source/ps/XML/tests/test_RelaxNG.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -39,21 +39,21 @@ public: RelaxNGValidator v; TS_ASSERT(v.LoadGrammar("")); - TS_ASSERT(v.Validate(L"doc", L"")); + TS_ASSERT(v.Validate("doc", "")); { TestLogger logger; - TS_ASSERT(!v.Validate(L"doc", L"")); + TS_ASSERT(!v.Validate("doc", "")); TS_ASSERT_STR_CONTAINS(logger.GetOutput(), "Validation error: doc:1: Expecting element test, got bogus"); } { TestLogger logger; - TS_ASSERT(!v.Validate(L"doc", L"bogus")); + TS_ASSERT(!v.Validate("doc", "bogus")); TS_ASSERT_STR_CONTAINS(logger.GetOutput(), "RelaxNGValidator: Failed to parse document"); } - TS_ASSERT(v.Validate(L"doc", L"")); + TS_ASSERT(v.Validate("doc", "")); } void test_interleave() @@ -68,20 +68,20 @@ public: RelaxNGValidator v; TS_ASSERT(v.LoadGrammar("1.5")); - TS_ASSERT(v.Validate(L"doc", L"2.0")); + TS_ASSERT(v.Validate("doc", "2.0")); TestLogger logger; - TS_ASSERT(!v.Validate(L"doc", L"x")); - TS_ASSERT(!v.Validate(L"doc", L"1.0")); + TS_ASSERT(!v.Validate("doc", "x")); + TS_ASSERT(!v.Validate("doc", "1.0")); RelaxNGValidator w; TS_ASSERT(w.LoadGrammar("")); - TS_ASSERT(w.Validate(L"doc", L"2")); + TS_ASSERT(w.Validate("doc", "2")); - TS_ASSERT(!w.Validate(L"doc", L"x")); - TS_ASSERT(!w.Validate(L"doc", L"2.0")); + TS_ASSERT(!w.Validate("doc", "x")); + TS_ASSERT(!w.Validate("doc", "2.0")); } void test_broken_grammar() @@ -92,6 +92,6 @@ public: TS_ASSERT(!v.LoadGrammar("whoops")); TS_ASSERT_STR_CONTAINS(logger.GetOutput(), "RelaxNGValidator: Failed to compile schema"); - TS_ASSERT(!v.Validate(L"doc", L"")); + TS_ASSERT(!v.Validate("doc", "")); } }; diff --git a/source/rlinterface/RLInterface.cpp b/source/rlinterface/RLInterface.cpp index c4224f31b2..7e67a651d6 100644 --- a/source/rlinterface/RLInterface.cpp +++ b/source/rlinterface/RLInterface.cpp @@ -97,7 +97,7 @@ std::vector Interface::GetTemplates(const std::vector& const CParamNode* node = cmpTemplateManager->GetTemplate(templateName); if (node != nullptr) - templates.push_back(utf8_from_wstring(node->ToXML())); + templates.push_back(node->ToXMLString()); } return templates; diff --git a/source/simulation2/components/CCmpPosition.cpp b/source/simulation2/components/CCmpPosition.cpp index 794935e906..1e5f782c69 100644 --- a/source/simulation2/components/CCmpPosition.cpp +++ b/source/simulation2/components/CCmpPosition.cpp @@ -138,12 +138,12 @@ public: virtual void Init(const CParamNode& paramNode) { - std::wstring anchor = paramNode.GetChild("Anchor").ToString(); - if (anchor == L"pitch") + const std::string& anchor = paramNode.GetChild("Anchor").ToString(); + if (anchor == "pitch") m_AnchorType = PITCH; - else if (anchor == L"pitch-roll") + else if (anchor == "pitch-roll") m_AnchorType = PITCH_ROLL; - else if (anchor == L"roll") + else if (anchor == "roll") m_AnchorType = ROLL; else m_AnchorType = UPRIGHT; diff --git a/source/simulation2/components/CCmpRallyPointRenderer.cpp b/source/simulation2/components/CCmpRallyPointRenderer.cpp index 79d3474f2c..02c95c48f8 100644 --- a/source/simulation2/components/CCmpRallyPointRenderer.cpp +++ b/source/simulation2/components/CCmpRallyPointRenderer.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -89,7 +89,7 @@ void CCmpRallyPointRenderer::Init(const CParamNode& paramNode) // --------------------------------------------------------------------------------------------- // Load some XML configuration data (schema guarantees that all these nodes are valid) - m_MarkerTemplate = paramNode.GetChild("MarkerTemplate").ToString(); + m_MarkerTemplate = paramNode.GetChild("MarkerTemplate").ToWString(); const CParamNode& lineDashColor = paramNode.GetChild("LineDashColor"); m_LineDashColor = CColor( lineDashColor.GetChild("@r").ToInt()/255.f, @@ -99,11 +99,11 @@ void CCmpRallyPointRenderer::Init(const CParamNode& paramNode) ); m_LineThickness = paramNode.GetChild("LineThickness").ToFixed().ToFloat(); - m_LineTexturePath = paramNode.GetChild("LineTexture").ToString(); - m_LineTextureMaskPath = paramNode.GetChild("LineTextureMask").ToString(); - m_LineStartCapType = SOverlayTexturedLine::StrToLineCapType(paramNode.GetChild("LineStartCap").ToString()); - m_LineEndCapType = SOverlayTexturedLine::StrToLineCapType(paramNode.GetChild("LineEndCap").ToString()); - m_LinePassabilityClass = paramNode.GetChild("LinePassabilityClass").ToUTF8(); + m_LineTexturePath = paramNode.GetChild("LineTexture").ToWString(); + m_LineTextureMaskPath = paramNode.GetChild("LineTextureMask").ToWString(); + m_LineStartCapType = SOverlayTexturedLine::StrToLineCapType(paramNode.GetChild("LineStartCap").ToWString()); + m_LineEndCapType = SOverlayTexturedLine::StrToLineCapType(paramNode.GetChild("LineEndCap").ToWString()); + m_LinePassabilityClass = paramNode.GetChild("LinePassabilityClass").ToString(); // --------------------------------------------------------------------------------------------- // Load some textures diff --git a/source/simulation2/components/CCmpSelectable.cpp b/source/simulation2/components/CCmpSelectable.cpp index e30f5834aa..406106e05e 100644 --- a/source/simulation2/components/CCmpSelectable.cpp +++ b/source/simulation2/components/CCmpSelectable.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -172,15 +172,15 @@ public: { // textured quad mode (dynamic, for units) m_OverlayDescriptor.m_Type = DYNAMIC_QUAD; - m_OverlayDescriptor.m_QuadTexture = CStrIntern(TEXTUREBASEPATH + textureNode.GetChild("MainTexture").ToUTF8()); - m_OverlayDescriptor.m_QuadTextureMask = CStrIntern(TEXTUREBASEPATH + textureNode.GetChild("MainTextureMask").ToUTF8()); + m_OverlayDescriptor.m_QuadTexture = CStrIntern(TEXTUREBASEPATH + textureNode.GetChild("MainTexture").ToString()); + m_OverlayDescriptor.m_QuadTextureMask = CStrIntern(TEXTUREBASEPATH + textureNode.GetChild("MainTextureMask").ToString()); } else if (outlineNode.IsOk()) { // textured outline mode (static, for buildings) m_OverlayDescriptor.m_Type = STATIC_OUTLINE; - m_OverlayDescriptor.m_LineTexture = CStrIntern(TEXTUREBASEPATH + outlineNode.GetChild("LineTexture").ToUTF8()); - m_OverlayDescriptor.m_LineTextureMask = CStrIntern(TEXTUREBASEPATH + outlineNode.GetChild("LineTextureMask").ToUTF8()); + m_OverlayDescriptor.m_LineTexture = CStrIntern(TEXTUREBASEPATH + outlineNode.GetChild("LineTexture").ToString()); + m_OverlayDescriptor.m_LineTextureMask = CStrIntern(TEXTUREBASEPATH + outlineNode.GetChild("LineTextureMask").ToString()); m_OverlayDescriptor.m_LineThickness = outlineNode.GetChild("LineThickness").ToFloat(); } diff --git a/source/simulation2/components/CCmpTemplateManager.cpp b/source/simulation2/components/CCmpTemplateManager.cpp index 5e867af05d..205eac70fb 100644 --- a/source/simulation2/components/CCmpTemplateManager.cpp +++ b/source/simulation2/components/CCmpTemplateManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -157,7 +157,7 @@ const CParamNode* CCmpTemplateManager::GetTemplate(const std::string& templateNa // Compute validity, if it's not computed before if (m_TemplateSchemaValidity.find(templateName) == m_TemplateSchemaValidity.end()) { - m_TemplateSchemaValidity[templateName] = m_Validator.Validate(wstring_from_utf8(templateName), fileData.ToXML()); + m_TemplateSchemaValidity[templateName] = m_Validator.Validate(templateName, fileData.ToXMLString()); // Show error on the first failure to validate the template if (!m_TemplateSchemaValidity[templateName]) diff --git a/source/simulation2/components/CCmpUnitMotion.h b/source/simulation2/components/CCmpUnitMotion.h index 870195abdb..73146f528b 100644 --- a/source/simulation2/components/CCmpUnitMotion.h +++ b/source/simulation2/components/CCmpUnitMotion.h @@ -257,7 +257,7 @@ public: CmpPtr cmpPathfinder(GetSystemEntity()); if (cmpPathfinder) { - m_PassClassName = paramNode.GetChild("PassabilityClass").ToUTF8(); + m_PassClassName = paramNode.GetChild("PassabilityClass").ToString(); m_PassClass = cmpPathfinder->GetPassabilityClass(m_PassClassName); m_Clearance = cmpPathfinder->GetClearance(m_PassClass); diff --git a/source/simulation2/components/CCmpVisualActor.cpp b/source/simulation2/components/CCmpVisualActor.cpp index fcd15e6ad0..7427bb041b 100644 --- a/source/simulation2/components/CCmpVisualActor.cpp +++ b/source/simulation2/components/CCmpVisualActor.cpp @@ -203,7 +203,7 @@ public: m_IsFoundationActor = paramNode.GetChild("Foundation").IsOk() && paramNode.GetChild("FoundationActor").IsOk(); - m_BaseActorName = paramNode.GetChild(m_IsFoundationActor ? "FoundationActor" : "Actor").ToString(); + m_BaseActorName = paramNode.GetChild(m_IsFoundationActor ? "FoundationActor" : "Actor").ToWString(); ParseActorName(m_BaseActorName); m_VisibleInAtlasOnly = paramNode.GetChild("VisibleInAtlasOnly").ToBool(); diff --git a/source/simulation2/helpers/Pathfinding.cpp b/source/simulation2/helpers/Pathfinding.cpp index fcfd353c08..ec53b4fd3f 100644 --- a/source/simulation2/helpers/Pathfinding.cpp +++ b/source/simulation2/helpers/Pathfinding.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -172,12 +172,12 @@ PathfinderPassability::PathfinderPassability(pass_class_t mask, const CParamNode if (node.GetChild("Obstructions").IsOk()) { - std::wstring obstructions = node.GetChild("Obstructions").ToString(); - if (obstructions == L"none") + const std::string& obstructions = node.GetChild("Obstructions").ToString(); + if (obstructions == "none") m_Obstructions = NONE; - else if (obstructions == L"pathfinding") + else if (obstructions == "pathfinding") m_Obstructions = PATHFINDING; - else if (obstructions == L"foundation") + else if (obstructions == "foundation") m_Obstructions = FOUNDATION; else { diff --git a/source/simulation2/scripting/ScriptComponent.h b/source/simulation2/scripting/ScriptComponent.h index 646fa4845d..e5f2d036fe 100644 --- a/source/simulation2/scripting/ScriptComponent.h +++ b/source/simulation2/scripting/ScriptComponent.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -22,11 +22,6 @@ #include "ps/CLogger.h" -class CSimContext; -class CParamNode; -class ISerializer; -class IDeserializer; - class CComponentTypeScript { NONCOPYABLE(CComponentTypeScript); @@ -72,4 +67,59 @@ private: JS::PersistentRootedValue m_Instance; }; +#define REGISTER_COMPONENT_SCRIPT_WRAPPER(cname) \ + void RegisterComponentType_##cname(CComponentManager& mgr) \ + { \ + mgr.RegisterComponentTypeScriptWrapper(CCmp##cname::GetInterfaceId(), CID_##cname, CCmp##cname::Allocate, CCmp##cname::Deallocate, #cname, CCmp##cname::GetSchema()); \ + CCmp##cname::ClassInit(mgr); \ + } + + +#define DEFAULT_SCRIPT_WRAPPER(cname) \ + static void ClassInit(CComponentManager& UNUSED(componentManager)) { } \ + static IComponent* Allocate(const ScriptInterface& scriptInterface, JS::HandleValue instance) \ + { \ + return new CCmp##cname(scriptInterface, instance); \ + } \ + static void Deallocate(IComponent* cmp) \ + { \ + delete static_cast (cmp); \ + } \ + CCmp##cname(const ScriptInterface& scriptInterface, JS::HandleValue instance) : m_Script(scriptInterface, instance) { } \ + static std::string GetSchema() \ + { \ + return ""; \ + } \ + virtual void Init(const CParamNode& paramNode) \ + { \ + m_Script.Init(paramNode, GetEntityId()); \ + } \ + virtual void Deinit() \ + { \ + m_Script.Deinit(); \ + } \ + virtual void HandleMessage(const CMessage& msg, bool global) \ + { \ + m_Script.HandleMessage(msg, global); \ + } \ + virtual void Serialize(ISerializer& serialize) \ + { \ + m_Script.Serialize(serialize); \ + } \ + virtual void Deserialize(const CParamNode& paramNode, IDeserializer& deserialize) \ + { \ + m_Script.Deserialize(paramNode, deserialize, GetEntityId()); \ + } \ + virtual JS::Value GetJSInstance() const \ + { \ + return m_Script.GetInstance(); \ + } \ + virtual int GetComponentTypeId() const \ + { \ + return CID_##cname; \ + } \ + private: \ + CComponentTypeScript m_Script; \ + public: + #endif // INCLUDED_SCRIPTCOMPONENT diff --git a/source/simulation2/system/Component.h b/source/simulation2/system/Component.h index 429f4603c9..9efcdde29e 100644 --- a/source/simulation2/system/Component.h +++ b/source/simulation2/system/Component.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -34,13 +34,6 @@ CCmp##cname::ClassInit(mgr); \ } -#define REGISTER_COMPONENT_SCRIPT_WRAPPER(cname) \ - void RegisterComponentType_##cname(CComponentManager& mgr) \ - { \ - mgr.RegisterComponentTypeScriptWrapper(CCmp##cname::GetInterfaceId(), CID_##cname, CCmp##cname::Allocate, CCmp##cname::Deallocate, #cname, CCmp##cname::GetSchema()); \ - CCmp##cname::ClassInit(mgr); \ - } - #define DEFAULT_COMPONENT_ALLOCATOR(cname) \ static IComponent* Allocate(const ScriptInterface&, JS::HandleValue) { return new CCmp##cname(); } \ static void Deallocate(IComponent* cmp) { delete static_cast (cmp); } \ @@ -49,53 +42,6 @@ return CID_##cname; \ } -#define DEFAULT_SCRIPT_WRAPPER(cname) \ - static void ClassInit(CComponentManager& UNUSED(componentManager)) { } \ - static IComponent* Allocate(const ScriptInterface& scriptInterface, JS::HandleValue instance) \ - { \ - return new CCmp##cname(scriptInterface, instance); \ - } \ - static void Deallocate(IComponent* cmp) \ - { \ - delete static_cast (cmp); \ - } \ - CCmp##cname(const ScriptInterface& scriptInterface, JS::HandleValue instance) : m_Script(scriptInterface, instance) { } \ - static std::string GetSchema() \ - { \ - return ""; \ - } \ - virtual void Init(const CParamNode& paramNode) \ - { \ - m_Script.Init(paramNode, GetEntityId()); \ - } \ - virtual void Deinit() \ - { \ - m_Script.Deinit(); \ - } \ - virtual void HandleMessage(const CMessage& msg, bool global) \ - { \ - m_Script.HandleMessage(msg, global); \ - } \ - virtual void Serialize(ISerializer& serialize) \ - { \ - m_Script.Serialize(serialize); \ - } \ - virtual void Deserialize(const CParamNode& paramNode, IDeserializer& deserialize) \ - { \ - m_Script.Deserialize(paramNode, deserialize, GetEntityId()); \ - } \ - virtual JS::Value GetJSInstance() const \ - { \ - return m_Script.GetInstance(); \ - } \ - virtual int GetComponentTypeId() const \ - { \ - return CID_##cname; \ - } \ - private: \ - CComponentTypeScript m_Script; \ - public: - #define DEFAULT_MOCK_COMPONENT() \ virtual int GetComponentTypeId() const \ { \ diff --git a/source/simulation2/system/ParamNode.cpp b/source/simulation2/system/ParamNode.cpp index 586bc65713..3e8aa74a2a 100644 --- a/source/simulation2/system/ParamNode.cpp +++ b/source/simulation2/system/ParamNode.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -29,7 +29,6 @@ #include #include -#include // this isn't in string.hpp in old Boosts static CParamNode g_NullNode(false); @@ -70,7 +69,7 @@ void CParamNode::ApplyLayer(const XMBFile& xmb, const XMBElement& element, const ResetScriptVal(); std::string name = xmb.GetElementString(element.GetNodeName()); // TODO: is GetElementString inefficient? - CStrW value = element.GetText().FromUTF8(); + CStr value = element.GetText(); bool hasSetValue = false; @@ -115,11 +114,11 @@ void CParamNode::ApplyLayer(const XMBFile& xmb, const XMBElement& element, const } else if (attr.Name == at_op) { - if (std::wstring(attr.Value.begin(), attr.Value.end()) == L"add") + if (attr.Value == "add") op = ADD; - else if (std::wstring(attr.Value.begin(), attr.Value.end()) == L"mul") + else if (attr.Value == "mul") op = MUL; - else if (std::wstring(attr.Value.begin(), attr.Value.end()) == L"mul_round") + else if (attr.Value == "mul_round") op = MUL_ROUND; else LOGWARNING("Invalid op '%ls'", attr.Value); @@ -129,30 +128,30 @@ void CParamNode::ApplyLayer(const XMBFile& xmb, const XMBElement& element, const { XERO_ITER_ATTR(element, attr) { - if (attr.Name == at_datatype && std::wstring(attr.Value.begin(), attr.Value.end()) == L"tokens") + if (attr.Name == at_datatype && attr.Value == "tokens") { CParamNode& node = m_Childs[name]; // Split into tokens - std::vector oldTokens; - std::vector newTokens; + std::vector oldTokens; + std::vector newTokens; if (!replacing && !node.m_Value.empty()) // ignore the old tokens if replace="" was given boost::algorithm::split(oldTokens, node.m_Value, boost::algorithm::is_space(), boost::algorithm::token_compress_on); if (!value.empty()) boost::algorithm::split(newTokens, value, boost::algorithm::is_space(), boost::algorithm::token_compress_on); // Merge the two lists - std::vector tokens = oldTokens; + std::vector tokens = oldTokens; for (size_t i = 0; i < newTokens.size(); ++i) { - if (newTokens[i][0] == L'-') + if (newTokens[i][0] == '-') { - std::vector::iterator tokenIt = std::find(tokens.begin(), tokens.end(), newTokens[i].substr(1)); + std::vector::iterator tokenIt = std::find(tokens.begin(), tokens.end(), newTokens[i].substr(1)); if (tokenIt != tokens.end()) tokens.erase(tokenIt); else LOGWARNING("[ParamNode] Could not remove token '%s' from node '%s'%s; not present in list nor inherited (possible typo?)", - utf8_from_wstring(newTokens[i].substr(1)), name, sourceIdentifier ? (" in '" + utf8_from_wstring(sourceIdentifier) + "'").c_str() : ""); + newTokens[i].substr(1), name, sourceIdentifier ? (" in '" + utf8_from_wstring(sourceIdentifier) + "'").c_str() : ""); } else { @@ -161,7 +160,7 @@ void CParamNode::ApplyLayer(const XMBFile& xmb, const XMBElement& element, const } } - node.m_Value = boost::algorithm::join(tokens, L" "); + node.m_Value = boost::algorithm::join(tokens, " "); hasSetValue = true; break; } @@ -174,18 +173,18 @@ void CParamNode::ApplyLayer(const XMBFile& xmb, const XMBElement& element, const { // TODO: Support parsing of data types other than fixed; log warnings in other cases fixed oldval = node.ToFixed(); - fixed mod = fixed::FromString(CStrW(value)); + fixed mod = fixed::FromString(value); switch (op) { case ADD: - node.m_Value = (oldval + mod).ToString().FromUTF8(); + node.m_Value = (oldval + mod).ToString(); break; case MUL: - node.m_Value = oldval.Multiply(mod).ToString().FromUTF8(); + node.m_Value = oldval.Multiply(mod).ToString(); break; case MUL_ROUND: - node.m_Value = fixed::FromInt(oldval.Multiply(mod).ToInt_RoundToNearest()).ToString().FromUTF8(); + node.m_Value = fixed::FromInt(oldval.Multiply(mod).ToInt_RoundToNearest()).ToString(); break; default: break; @@ -226,7 +225,7 @@ void CParamNode::ApplyLayer(const XMBFile& xmb, const XMBElement& element, const continue; // Add any others std::string attrName = xmb.GetAttributeString(attr.Name); - node.m_Childs["@" + attrName].m_Value = attr.Value.FromUTF8(); + node.m_Childs["@" + attrName].m_Value = attr.Value; } } @@ -243,47 +242,39 @@ bool CParamNode::IsOk() const return m_IsOk; } -const std::wstring& CParamNode::ToString() const +const std::wstring CParamNode::ToWString() const +{ + return wstring_from_utf8(m_Value); +} + +const std::string& CParamNode::ToString() const { return m_Value; } -const std::string CParamNode::ToUTF8() const -{ - return utf8_from_wstring(m_Value); -} - const CStrIntern CParamNode::ToUTF8Intern() const { - return CStrIntern(utf8_from_wstring(m_Value)); + return CStrIntern(m_Value); } int CParamNode::ToInt() const { - int ret = 0; - std::wstringstream strm; - strm << m_Value; - strm >> ret; - return ret; + return std::strtol(m_Value.c_str(), nullptr, 10); } fixed CParamNode::ToFixed() const { - return fixed::FromString(CStrW(m_Value)); + return fixed::FromString(m_Value); } float CParamNode::ToFloat() const { - float ret = 0; - std::wstringstream strm; - strm << m_Value; - strm >> ret; - return ret; + return std::strtof(m_Value.c_str(), nullptr); } bool CParamNode::ToBool() const { - if (m_Value == L"true") + if (m_Value == "true") return true; else return false; @@ -294,40 +285,39 @@ const CParamNode::ChildrenMap& CParamNode::GetChildren() const return m_Childs; } -std::wstring CParamNode::EscapeXMLString(const std::wstring& str) +std::string CParamNode::EscapeXMLString(const std::string& str) { - std::wstring ret; + std::string ret; ret.reserve(str.size()); + // TODO: would be nice to check actual v1.0 XML codepoints, + // but our UTF8 validation routines are lacking. for (size_t i = 0; i < str.size(); ++i) { - wchar_t c = str[i]; + char c = str[i]; switch (c) { - case '<': ret += L"<"; break; - case '>': ret += L">"; break; - case '&': ret += L"&"; break; - case '"': ret += L"""; break; - case '\t': ret += L" "; break; - case '\n': ret += L" "; break; - case '\r': ret += L" "; break; + case '<': ret += "<"; break; + case '>': ret += ">"; break; + case '&': ret += "&"; break; + case '"': ret += """; break; + case '\t': ret += " "; break; + case '\n': ret += " "; break; + case '\r': ret += " "; break; default: - if ((0x20 <= c && c <= 0xD7FF) || (0xE000 <= c && c <= 0xFFFD)) - ret += c; - else - ret += 0xFFFD; + ret += c; } } return ret; } -std::wstring CParamNode::ToXML() const +std::string CParamNode::ToXMLString() const { - std::wstringstream strm; - ToXML(strm); + std::stringstream strm; + ToXMLString(strm); return strm.str(); } -void CParamNode::ToXML(std::wostream& strm) const +void CParamNode::ToXMLString(std::ostream& strm) const { strm << m_Value; @@ -338,9 +328,7 @@ void CParamNode::ToXML(std::wostream& strm) const if (it->first.length() && it->first[0] == '@') continue; - std::wstring name (it->first.begin(), it->first.end()); - - strm << L"<" << name; + strm << "<" << it->first; // Output the child's attributes first ChildrenMap::const_iterator cit = it->second.m_Childs.begin(); @@ -348,16 +336,16 @@ void CParamNode::ToXML(std::wostream& strm) const { if (cit->first.length() && cit->first[0] == '@') { - std::wstring attrname (cit->first.begin()+1, cit->first.end()); - strm << L" " << attrname << L"=\"" << EscapeXMLString(cit->second.m_Value) << L"\""; + std::string attrname (cit->first.begin()+1, cit->first.end()); + strm << " " << attrname << "=\"" << EscapeXMLString(cit->second.m_Value) << "\""; } } - strm << L">"; + strm << ">"; - it->second.ToXML(strm); + it->second.ToXMLString(strm); - strm << L""; + strm << "first << ">"; } } @@ -387,8 +375,8 @@ void CParamNode::ConstructJSVal(const ScriptRequest& rq, JS::MutableHandleValue } // Just a string - utf16string text(m_Value.begin(), m_Value.end()); - JS::RootedString str(rq.cx, JS_AtomizeAndPinUCStringN(rq.cx, reinterpret_cast(text.data()), text.length())); + JS::RootedString str(rq.cx, JS_NewStringCopyUTF8Z(rq.cx, JS::ConstUTF8CharsZ(m_Value.data(), m_Value.size()))); + str.set(JS_AtomizeAndPinJSString(rq.cx, str)); if (str) { ret.setString(str); diff --git a/source/simulation2/system/ParamNode.h b/source/simulation2/system/ParamNode.h index a9d0b8317a..3c11ac2bdb 100644 --- a/source/simulation2/system/ParamNode.h +++ b/source/simulation2/system/ParamNode.h @@ -196,14 +196,14 @@ public: bool IsOk() const; /** - * Returns the content of this node as a string + * Returns the content of this node as a wstring */ - const std::wstring& ToString() const; + const std::wstring ToWString() const; /** - * Returns the content of this node as an 8-bit string + * Returns the content of this node as an UTF8 string */ - const std::string ToUTF8() const; + const std::string& ToString() const; /** * Returns the content of this node as an internalized 8-bit string. Should only be used for @@ -234,12 +234,12 @@ public: /** * Returns the content of this node and its children as an XML string */ - std::wstring ToXML() const; + std::string ToXMLString() const; /** * Write the content of this node and its children as an XML string, to the stream */ - void ToXML(std::wostream& strm) const; + void ToXMLString(std::ostream& strm) const; /** * Returns a JS::Value representation of this node and its children. @@ -259,9 +259,12 @@ public: /** * Escapes a string so that it is well-formed XML content/attribute text. - * (Replaces "&" with "&" etc, and replaces invalid characters with U+FFFD.) + * (Replaces "&" with "&" etc) */ - static std::wstring EscapeXMLString(const std::wstring& str); + static std::string EscapeXMLString(const std::string& str); + + std::string m_Name; + u32 m_Index; private: @@ -279,7 +282,7 @@ private: void ConstructJSVal(const ScriptRequest& rq, JS::MutableHandleValue ret) const; - std::wstring m_Value; + std::string m_Value; ChildrenMap m_Childs; bool m_IsOk; diff --git a/source/simulation2/tests/test_CmpTemplateManager.h b/source/simulation2/tests/test_CmpTemplateManager.h index e705785d77..6d46a75e85 100644 --- a/source/simulation2/tests/test_CmpTemplateManager.h +++ b/source/simulation2/tests/test_CmpTemplateManager.h @@ -66,21 +66,21 @@ public: const CParamNode* basic = tempMan->LoadTemplate(ent2, "basic"); TS_ASSERT(basic != NULL); - TS_ASSERT_WSTR_EQUALS(basic->ToXML(), L"12345"); + TS_ASSERT_STR_EQUALS(basic->ToXMLString(), "12345"); const CParamNode* inherit2 = tempMan->LoadTemplate(ent2, "inherit2"); TS_ASSERT(inherit2 != NULL); - TS_ASSERT_WSTR_EQUALS(inherit2->ToXML(), L"d2e1f1g2"); + TS_ASSERT_STR_EQUALS(inherit2->ToXMLString(), "d2e1f1g2"); const CParamNode* inherit1 = tempMan->LoadTemplate(ent2, "inherit1"); TS_ASSERT(inherit1 != NULL); - TS_ASSERT_WSTR_EQUALS(inherit1->ToXML(), L"d1e1f1"); + TS_ASSERT_STR_EQUALS(inherit1->ToXMLString(), "d1e1f1"); const CParamNode* actor = tempMan->LoadTemplate(ent2, "actor|example1"); TS_ASSERT(actor != NULL); - TS_ASSERT_WSTR_EQUALS(actor->ToXML(), - L"1.0128x128/ellipse.png128x128/ellipse_mask.png" - L"example1falsefalsefalse"); + TS_ASSERT_STR_EQUALS(actor->ToXMLString(), + "1.0128x128/ellipse.png128x128/ellipse_mask.png" + "example1falsefalsefalse"); } void test_LoadTemplate_scriptcache() diff --git a/source/simulation2/tests/test_ParamNode.h b/source/simulation2/tests/test_ParamNode.h index 8cb72dc090..02c182b615 100644 --- a/source/simulation2/tests/test_ParamNode.h +++ b/source/simulation2/tests/test_ParamNode.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -41,12 +41,12 @@ public: TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, " 1 234"), PSRETURN_OK); TS_ASSERT(node.GetChild("test").IsOk()); TS_ASSERT(!node.GetChild("Test").IsOk()); - TS_ASSERT_WSTR_EQUALS(node.GetChild("test").ToString(), L""); + TS_ASSERT_STR_EQUALS(node.GetChild("test").ToString(), ""); TS_ASSERT(node.GetChild("test").GetChild("Foo").IsOk()); TS_ASSERT_EQUALS(node.GetChild("test").GetChild("Foo").ToInt(), 1); - TS_ASSERT_WSTR_EQUALS(node.GetChild("test").GetChild("Foo").ToString(), L"1"); + TS_ASSERT_STR_EQUALS(node.GetChild("test").GetChild("Foo").ToString(), "1"); TS_ASSERT_EQUALS(node.GetChild("test").GetChild("Bar").ToInt(), 24); - TS_ASSERT_WSTR_EQUALS(node.GetChild("test").GetChild("Bar").ToString(), L"24"); + TS_ASSERT_STR_EQUALS(node.GetChild("test").GetChild("Bar").ToString(), "24"); TS_ASSERT_EQUALS(node.GetChild("test").GetChild("Bar").GetChild("Baz").ToInt(), 3); TS_ASSERT(node.GetChild("test").GetChild("Qux").IsOk()); TS_ASSERT(!node.GetChild("test").GetChild("Qux").GetChild("Baz").IsOk()); @@ -58,7 +58,7 @@ public: TS_ASSERT(!nullTwo.IsOk()); TS_ASSERT(!nullThree.IsOk()); - TS_ASSERT_WSTR_EQUALS(nullOne.ToString(), L""); + TS_ASSERT_STR_EQUALS(nullOne.ToString(), ""); TS_ASSERT(nullOne.ToInt() == 0); TS_ASSERT(nullOne.ToFixed().ToDouble() == 0); } @@ -79,11 +79,11 @@ public: TS_ASSERT_EQUALS(node.GetChild("test").GetChild("w").GetChild("@a").ToInt(), 4); } - void test_ToXML() + void test_ToXMLString() { CParamNode node; TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, " 3 "), PSRETURN_OK); - TS_ASSERT_WSTR_EQUALS(node.ToXML(), L"3"); + TS_ASSERT_STR_EQUALS(node.ToXMLString(), "3"); } void test_overlay_basic() @@ -91,7 +91,7 @@ public: CParamNode node; TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, " 3 4 "), PSRETURN_OK); TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, " 7 8 "), PSRETURN_OK); - TS_ASSERT_WSTR_EQUALS(node.ToXML(), L"378"); + TS_ASSERT_STR_EQUALS(node.ToXMLString(), "378"); } void test_overlay_disable() @@ -99,7 +99,7 @@ public: CParamNode node; TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, " 1 2 "), PSRETURN_OK); TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, " "), PSRETURN_OK); - TS_ASSERT_WSTR_EQUALS(node.ToXML(), L"2"); + TS_ASSERT_STR_EQUALS(node.ToXMLString(), "2"); } void test_overlay_replace() @@ -107,7 +107,7 @@ public: CParamNode node; TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, " 2 "), PSRETURN_OK); TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, " "), PSRETURN_OK); - TS_ASSERT_WSTR_EQUALS(node.ToXML(), L""); + TS_ASSERT_STR_EQUALS(node.ToXMLString(), ""); } void test_overlay_tokens() @@ -115,24 +115,24 @@ public: CParamNode node; TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, " x ya b\nc\tdm n"), PSRETURN_OK); TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, " -y z wn o"), PSRETURN_OK); - TS_ASSERT_WSTR_EQUALS(node.ToXML(), L"x z wa b c dn o"); + TS_ASSERT_STR_EQUALS(node.ToXMLString(), "x z wa b c dn o"); } void test_overlay_remove_nonexistent_token() { // regression test; this used to cause a crash because of a failure to check whether the token being removed was present - TestLogger nolog; + TestLogger logger; CParamNode node; TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, " -nonexistenttoken X"), PSRETURN_OK); - TS_ASSERT_WSTR_EQUALS(node.ToXML(), L"X"); + TS_ASSERT_STR_EQUALS(node.ToXMLString(), "X"); } void test_overlay_remove_empty_token() { - TestLogger nolog; + TestLogger logger; CParamNode node; TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, " Y - X "), PSRETURN_OK); - TS_ASSERT_WSTR_EQUALS(node.ToXML(), L"Y X"); + TS_ASSERT_STR_EQUALS(node.ToXMLString(), "Y X"); } void test_overlay_filtered() @@ -140,12 +140,12 @@ public: CParamNode node; TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, " toberemoved "), PSRETURN_OK); TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, " "), PSRETURN_OK); - TS_ASSERT_WSTR_EQUALS(node.ToXML(), L""); + TS_ASSERT_STR_EQUALS(node.ToXMLString(), ""); CParamNode node2; TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node2, " bcde "), PSRETURN_OK); TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node2, " c2 "), PSRETURN_OK); - TS_ASSERT_WSTR_EQUALS(node2.ToXML(), L"bc2"); + TS_ASSERT_STR_EQUALS(node2.ToXMLString(), "bc2"); } void test_overlay_merge() @@ -153,7 +153,16 @@ public: CParamNode node; TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, " foobar foo "), PSRETURN_OK); TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, " testbaz willnotbeincluded textmore text "), PSRETURN_OK); - TS_ASSERT_WSTR_EQUALS(node.ToXML(), L"testbarbazmore texttextfoo"); + TS_ASSERT_STR_EQUALS(node.ToXMLString(), "testbarbazmore texttextfoo"); + } + + void test_overlay_merge_empty() + { + // 'merge' nodes don't change the original value. + CParamNode node; + TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, "foobar"), PSRETURN_OK); + TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, "skippedreplaced"), PSRETURN_OK); + TS_ASSERT_STR_EQUALS(node.ToXMLString(), "foobar"); } void test_overlay_filtered_merge() @@ -161,7 +170,15 @@ public: CParamNode node; TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, " 1200 "), PSRETURN_OK); TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, " bar 1 "), PSRETURN_OK); - TS_ASSERT_WSTR_EQUALS(node.ToXML(), L"11200bar"); + TS_ASSERT_STR_EQUALS(node.ToXMLString(), "11200bar"); + } + + void test_overlay_ops() + { + CParamNode node; + TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, "555"), PSRETURN_OK); + TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, "530.55"), PSRETURN_OK); + TS_ASSERT_STR_EQUALS(node.ToXMLString(), "10153"); } void test_types() @@ -170,7 +187,7 @@ public: TS_ASSERT_EQUALS(CParamNode::LoadXMLString(node, "+010.75true"), PSRETURN_OK); TS_ASSERT(node.GetChild("test").IsOk()); TS_ASSERT(node.GetChild("test").GetChild("n").IsOk()); - TS_ASSERT_EQUALS(node.GetChild("test").GetChild("n").ToString(), L"+010.75"); + TS_ASSERT_EQUALS(node.GetChild("test").GetChild("n").ToString(), "+010.75"); TS_ASSERT_EQUALS(node.GetChild("test").GetChild("n").ToInt(), 10); TS_ASSERT_EQUALS(node.GetChild("test").GetChild("n").ToFixed().ToDouble(), 10.75); TS_ASSERT_EQUALS(node.GetChild("test").GetChild("n").ToBool(), false); @@ -179,14 +196,9 @@ public: void test_escape() { - TS_ASSERT_WSTR_EQUALS(CParamNode::EscapeXMLString(L"test"), L"test"); - TS_ASSERT_WSTR_EQUALS(CParamNode::EscapeXMLString(L"x < y << z"), L"x < y << z"); - TS_ASSERT_WSTR_EQUALS(CParamNode::EscapeXMLString(L"x < y \"&' y > z ]]> "), L"x < y "&' y > z ]]> "); - TS_ASSERT_WSTR_EQUALS(CParamNode::EscapeXMLString(L" \r\n\t "), L" "); - - wchar_t r = 0xFFFD; - wchar_t a[] = { 1, 2, 3, 4, 5, 6, 7, 8, /* 9, 10, */ 11, 12, /* 13, */ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 0xD7FF, 0xD800, 0xDFFF, 0xE000, 0xFFFE, 0xFFFF, 0 }; - wchar_t b[] = { r, r, r, r, r, r, r, r, /* */ r, r, /* */ r, r, r, r, r, r, r, r, r, r, r, r, r, r, r, r, r, r, 32, 0xD7FF, r, r, 0xE000, r, r, 0 }; - TS_ASSERT_WSTR_EQUALS(CParamNode::EscapeXMLString(a), b); + TS_ASSERT_STR_EQUALS(CParamNode::EscapeXMLString("test"), "test"); + TS_ASSERT_STR_EQUALS(CParamNode::EscapeXMLString("x < y << z"), "x < y << z"); + TS_ASSERT_STR_EQUALS(CParamNode::EscapeXMLString("x < y \"&' y > z ]]> "), "x < y "&' y > z ]]> "); + TS_ASSERT_STR_EQUALS(CParamNode::EscapeXMLString(" \r\n\t "), " "); } };