From f5c690633d50df30f806560fdaa403b2fe55519c Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Tue, 1 Aug 2023 20:40:05 +0100 Subject: Reformat with new clang-format --- slicer/db/sqlBinder.h | 2 ++ slicer/db/sqlCommon.cpp | 1 + slicer/db/sqlInsertSerializer.cpp | 1 + slicer/db/sqlInsertSerializer.h | 1 + slicer/db/sqlSelectDeserializer.h | 1 + slicer/db/sqlSource.h | 3 +++ slicer/db/sqlTablePatchSerializer.cpp | 3 +++ slicer/db/sqlTablePatchSerializer.h | 1 + slicer/db/sqlUpdateSerializer.h | 1 + slicer/db/testInsert.cpp | 1 + slicer/db/testMockCommon.h | 1 + slicer/db/testPatch.cpp | 2 ++ slicer/ice/testSpecifics.cpp | 1 + slicer/json/serializer.cpp | 4 ++++ slicer/slicer/enumMap.h | 1 + slicer/slicer/hook-test.cpp | 1 + slicer/slicer/hookMap.h | 1 + slicer/slicer/metadata.h | 1 + slicer/slicer/modelParts.h | 7 +++++-- slicer/slicer/modelPartsTypes.cpp | 35 +++++++++++++++++++++++++++++++++++ slicer/slicer/modelPartsTypes.h | 1 + slicer/slicer/modelPartsTypes.impl.h | 2 ++ slicer/slicer/serializer.h | 3 +++ slicer/slicer/slicer.cpp | 8 ++++++++ slicer/test/conversions.cpp | 18 ++++++++++-------- slicer/test/conversions.h | 1 + slicer/test/serializers.cpp | 2 ++ slicer/tool/icemetadata.cpp | 1 + slicer/tool/parser.cpp | 5 +++++ slicer/tool/parser.h | 2 ++ slicer/xml/serializer.cpp | 2 ++ slicer/xml/serializer.h | 1 + slicer/xml/testSpecifics.cpp | 1 + 33 files changed, 106 insertions(+), 10 deletions(-) diff --git a/slicer/db/sqlBinder.h b/slicer/db/sqlBinder.h index 4f5437c..71f23ea 100644 --- a/slicer/db/sqlBinder.h +++ b/slicer/db/sqlBinder.h @@ -6,6 +6,7 @@ #include #include #include + namespace DB { class Command; } @@ -33,6 +34,7 @@ namespace Slicer { DB::Command & command; const unsigned int idx; }; + typedef std::shared_ptr SqlBinderPtr; } diff --git a/slicer/db/sqlCommon.cpp b/slicer/db/sqlCommon.cpp index 40e43f7..21fb9e5 100644 --- a/slicer/db/sqlCommon.cpp +++ b/slicer/db/sqlCommon.cpp @@ -59,6 +59,7 @@ namespace Slicer { } AdHocFormatter(UnsuitableIdFieldTypeMsg, "Unsuitable id field type [%?]"); + void UnsuitableIdFieldType::ice_print(std::ostream & s) const { diff --git a/slicer/db/sqlInsertSerializer.cpp b/slicer/db/sqlInsertSerializer.cpp index 58e30e2..b4d46e6 100644 --- a/slicer/db/sqlInsertSerializer.cpp +++ b/slicer/db/sqlInsertSerializer.cpp @@ -88,6 +88,7 @@ namespace Slicer { private: DB::Connection * const connection; + template inline void doSet([[maybe_unused]] T & v, [[maybe_unused]] const char * Tname) const diff --git a/slicer/db/sqlInsertSerializer.h b/slicer/db/sqlInsertSerializer.h index b6a0d27..4a6a423 100644 --- a/slicer/db/sqlInsertSerializer.h +++ b/slicer/db/sqlInsertSerializer.h @@ -7,6 +7,7 @@ #include #include #include + namespace DB { class Connection; class ModifyCommand; diff --git a/slicer/db/sqlSelectDeserializer.h b/slicer/db/sqlSelectDeserializer.h index bf2b351..9e9d499 100644 --- a/slicer/db/sqlSelectDeserializer.h +++ b/slicer/db/sqlSelectDeserializer.h @@ -6,6 +6,7 @@ #include #include #include + namespace DB { class SelectCommand; } diff --git a/slicer/db/sqlSource.h b/slicer/db/sqlSource.h index 4b76974..70a0122 100644 --- a/slicer/db/sqlSource.h +++ b/slicer/db/sqlSource.h @@ -5,9 +5,11 @@ #include #include #include + namespace DB { class Column; } + namespace boost::posix_time { class ptime; class time_duration; @@ -36,6 +38,7 @@ namespace Slicer { private: const DB::Column & column; }; + typedef std::shared_ptr SqlSourcePtr; } diff --git a/slicer/db/sqlTablePatchSerializer.cpp b/slicer/db/sqlTablePatchSerializer.cpp index 3b73f05..a22f15a 100644 --- a/slicer/db/sqlTablePatchSerializer.cpp +++ b/slicer/db/sqlTablePatchSerializer.cpp @@ -11,6 +11,7 @@ namespace Slicer { AdHocFormatter(ttname, "slicer_tmp_%?"); + SqlTablePatchSerializer::SqlTablePatchSerializer(DB::Connection * const d, DB::TablePatch & tp) : db(d), tablePatch(tp) { @@ -47,6 +48,7 @@ namespace Slicer { } AdHocFormatter(createTmpTable, "CREATE TEMPORARY TABLE %? AS SELECT * FROM %? WHERE 1 = 0"); + void SqlTablePatchSerializer::createTemporaryTable() { @@ -54,6 +56,7 @@ namespace Slicer { } AdHocFormatter(dropTmpTable, "DROP TABLE %?"); + void SqlTablePatchSerializer::dropTemporaryTable() { diff --git a/slicer/db/sqlTablePatchSerializer.h b/slicer/db/sqlTablePatchSerializer.h index 21c8b3d..73e084d 100644 --- a/slicer/db/sqlTablePatchSerializer.h +++ b/slicer/db/sqlTablePatchSerializer.h @@ -4,6 +4,7 @@ #include #include #include + namespace DB { class Connection; class TablePatch; diff --git a/slicer/db/sqlUpdateSerializer.h b/slicer/db/sqlUpdateSerializer.h index 8707988..54a5f82 100644 --- a/slicer/db/sqlUpdateSerializer.h +++ b/slicer/db/sqlUpdateSerializer.h @@ -6,6 +6,7 @@ #include #include #include + namespace DB { class Connection; class ModifyCommand; diff --git a/slicer/db/testInsert.cpp b/slicer/db/testInsert.cpp index a9e42f1..24cae7e 100644 --- a/slicer/db/testInsert.cpp +++ b/slicer/db/testInsert.cpp @@ -25,6 +25,7 @@ using namespace std::literals; BOOST_TEST_DONT_PRINT_LOG_VALUE(TestModule::DateTime) BOOST_TEST_DONT_PRINT_LOG_VALUE(TestModule::IsoDate) BOOST_TEST_DONT_PRINT_LOG_VALUE(TestDatabase::Timespan) + // LCOV_EXCL_STOP namespace std { diff --git a/slicer/db/testMockCommon.h b/slicer/db/testMockCommon.h index e12d2c6..891fb74 100644 --- a/slicer/db/testMockCommon.h +++ b/slicer/db/testMockCommon.h @@ -5,6 +5,7 @@ #include #include #include + // IWYU pragma: no_forward_declare PQ::Mock namespace DB { class Connection; diff --git a/slicer/db/testPatch.cpp b/slicer/db/testPatch.cpp index 6db440a..3e8b1e4 100644 --- a/slicer/db/testPatch.cpp +++ b/slicer/db/testPatch.cpp @@ -11,9 +11,11 @@ #include #include #include + namespace TestDatabase { class Timespan; } + namespace TestModule { struct DateTime; struct IsoDate; diff --git a/slicer/ice/testSpecifics.cpp b/slicer/ice/testSpecifics.cpp index 2080993..6b6c0f0 100644 --- a/slicer/ice/testSpecifics.cpp +++ b/slicer/ice/testSpecifics.cpp @@ -18,6 +18,7 @@ // LCOV_EXCL_START // cppcheck-suppress unknownMacro BOOST_TEST_DONT_PRINT_LOG_VALUE(TestModule::IsoDate) + // LCOV_EXCL_STOP template diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp index e2db939..227f3c9 100644 --- a/slicer/json/serializer.cpp +++ b/slicer/json/serializer.cpp @@ -150,6 +150,7 @@ namespace Slicer { class DocumentTreeIterate { public: explicit DocumentTreeIterate(ModelPartPtr & mp) : modelPart(mp) { } + template void operator()(const SimpleT & v) const @@ -158,11 +159,13 @@ namespace Slicer { modelPart->SetValue(JsonValueSource(v)); modelPart->Complete(); } + void operator()(const json::Null &) const { modelPart->Complete(); } + void operator()(const json::Object & o) const { @@ -197,6 +200,7 @@ namespace Slicer { modelPart->Complete(); } } + void operator()(const json::Array & a) const { diff --git a/slicer/slicer/enumMap.h b/slicer/slicer/enumMap.h index 4c50bd8..e076a0c 100644 --- a/slicer/slicer/enumMap.h +++ b/slicer/slicer/enumMap.h @@ -52,6 +52,7 @@ namespace Slicer { EnumMap::begin = arr.begin(); EnumMap::end = arr.end(); } + const Arr arr; }; } diff --git a/slicer/slicer/hook-test.cpp b/slicer/slicer/hook-test.cpp index 3af28b4..2fa1b8b 100644 --- a/slicer/slicer/hook-test.cpp +++ b/slicer/slicer/hook-test.cpp @@ -15,6 +15,7 @@ namespace test { int AA; std::string b; }; + const std::string aa {"aa"}, aA {"aA"}, Aa {"Aa"}, AA {"AA"}, b {"b"}; using C = Slicer::ModelPartForComplex; diff --git a/slicer/slicer/hookMap.h b/slicer/slicer/hookMap.h index 92035de..5f71e17 100644 --- a/slicer/slicer/hookMap.h +++ b/slicer/slicer/hookMap.h @@ -13,6 +13,7 @@ namespace Slicer { void DLL_PUBLIC to_lower(std::string s); template class ModelPartForComplex; // IWYU pragma: keep + template class Hooks { public: using HookPtr = const typename ModelPartForComplex::HookBase *; diff --git a/slicer/slicer/metadata.h b/slicer/slicer/metadata.h index 6b209ae..8f24edb 100644 --- a/slicer/slicer/metadata.h +++ b/slicer/slicer/metadata.h @@ -109,6 +109,7 @@ namespace Slicer { template class DLL_PUBLIC MetaDataImpl : public MetaData<> { public: using Arr = ContainerBase; + constexpr inline explicit MetaDataImpl(const std::array & a) : arr {[&a]() { Arr rtn; diff --git a/slicer/slicer/modelParts.h b/slicer/slicer/modelParts.h index 1986a95..e5e323f 100644 --- a/slicer/slicer/modelParts.h +++ b/slicer/slicer/modelParts.h @@ -24,6 +24,7 @@ namespace Slicer { virtual void get(const T &) const = 0; SPECIAL_MEMBERS_DEFAULT(TValueTarget); }; + class ValueTarget : public TValueTarget, public TValueTarget, @@ -51,6 +52,7 @@ namespace Slicer { virtual void set(T &) const = 0; SPECIAL_MEMBERS_DEFAULT(TValueSource); }; + class ValueSource : public TValueSource, public TValueSource, @@ -119,6 +121,7 @@ namespace Slicer { name(n), nameLower(nl), nameStr(ns) { } + virtual ~HookCommon() = default; SPECIAL_MEMBERS_DEFAULT(HookCommon); @@ -132,8 +135,7 @@ namespace Slicer { const std::string * nameStr; }; - template struct DLL_PUBLIC Default { - }; + template struct DLL_PUBLIC Default { }; class DLL_PUBLIC ModelPart : public std::enable_shared_from_this { public: @@ -175,6 +177,7 @@ namespace Slicer { template class DLL_PUBLIC ModelPartModel { public: explicit ModelPartModel(T * m = nullptr) : Model(m) { } + T * Model; }; diff --git a/slicer/slicer/modelPartsTypes.cpp b/slicer/slicer/modelPartsTypes.cpp index 47543a6..aabbf57 100644 --- a/slicer/slicer/modelPartsTypes.cpp +++ b/slicer/slicer/modelPartsTypes.cpp @@ -17,6 +17,7 @@ #include #include #include + // IWYU pragma: no_forward_declare boost::multi_index::member // IWYU pragma: no_include @@ -172,57 +173,68 @@ namespace Slicer { ModelPartForSimpleBase::OnEachChild(const ChildHandler &) { } + ChildRef ModelPartForSimpleBase::GetAnonChildRef(const HookFilter &) { return ChildRef(); } + ChildRef ModelPartForSimpleBase::GetChildRef(std::string_view, const HookFilter &, bool) { return ChildRef(); } + bool ModelPartForSimpleBase::HasValue() const { return true; } + ModelPartType ModelPartForSimpleBase::GetType() const { return type; } + const ModelPartType ModelPartForSimpleBase::type = ModelPartType::Simple; void ModelPartForConvertedBase::OnEachChild(const ChildHandler &) { } + ChildRef ModelPartForConvertedBase::GetAnonChildRef(const HookFilter &) { return ChildRef(); } + ChildRef ModelPartForConvertedBase::GetChildRef(std::string_view, const HookFilter &, bool) { return ChildRef(); } + bool ModelPartForConvertedBase::HasValue() const { return true; } + ModelPartType ModelPartForConvertedBase::GetType() const { return type; } + void ModelPartForConvertedBase::conversion_fail(std::string_view typeName) { throw NoConversionFound(std::string {typeName}); } + const ModelPartType ModelPartForConvertedBase::type = ModelPartType::Simple; ModelPartType @@ -230,7 +242,9 @@ namespace Slicer { { return type; } + const ModelPartType ModelPartForComplexBase::type = ModelPartType::Complex; + void ModelPartForComplexBase::registerClass( const std::string & className, const std::string * typeName, const ClassRef & cr) @@ -240,6 +254,7 @@ namespace Slicer { Slicer::classNameMap()->insert({className, *typeName}); } } + void ModelPartForComplexBase::unregisterClass(const std::string & className, const std::string * typeName) { @@ -248,6 +263,7 @@ namespace Slicer { classNameMap()->get<0>().erase(className); } } + ModelPartPtr ModelPartForComplexBase::getSubclassModelPart(const std::string & name, void * m) { @@ -257,6 +273,7 @@ namespace Slicer { } return ref->second(m); } + TypeId ModelPartForComplexBase::getTypeId(const std::string & id, const std::string & className) { @@ -335,26 +352,31 @@ namespace Slicer { ModelPartForEnumBase::OnEachChild(const ChildHandler &) { } + ChildRef ModelPartForEnumBase::GetAnonChildRef(const HookFilter &) { return ChildRef(); } + ChildRef ModelPartForEnumBase::GetChildRef(std::string_view, const HookFilter &, bool) { return ChildRef(); } + bool ModelPartForEnumBase::HasValue() const { return true; } + ModelPartType ModelPartForEnumBase::GetType() const { return type; } + const ModelPartType ModelPartForEnumBase::type = ModelPartType::Simple; bool @@ -362,11 +384,13 @@ namespace Slicer { { return true; } + ModelPartType ModelPartForSequenceBase::GetType() const { return type; } + ChildRef ModelPartForSequenceBase::GetChildRef(std::string_view name, const HookFilter & flt, bool matchCase) { @@ -375,6 +399,7 @@ namespace Slicer { } return GetAnonChildRef(flt); } + const ModelPartType ModelPartForSequenceBase::type = ModelPartType::Sequence; bool @@ -382,11 +407,13 @@ namespace Slicer { { return true; } + ModelPartType ModelPartForDictionaryBase::GetType() const { return type; } + const ModelPartType ModelPartForDictionaryBase::type = ModelPartType::Dictionary; // Streams @@ -396,41 +423,49 @@ namespace Slicer { { throw InvalidStreamOperation(__FUNCTION__); } + // NOLINTNEXTLINE(hicpp-no-array-decay) ChildRef ModelPartForStreamBase::GetChildRef(std::string_view, const Slicer::HookFilter &, bool) { throw InvalidStreamOperation(__FUNCTION__); } + ModelPartType ModelPartForStreamBase::GetType() const { return ModelPartType::Sequence; } + bool ModelPartForStreamBase::HasValue() const { return true; } + // Stream Roots ModelPartForStreamRootBase::ModelPartForStreamRootBase(const ModelPartPtr & m) : ModelPartForRootBase(m) { } + // NOLINTNEXTLINE(hicpp-no-array-decay) void ModelPartForStreamRootBase::Write(Ice::OutputStream &) const { throw InvalidStreamOperation(__FUNCTION__); } + // NOLINTNEXTLINE(hicpp-no-array-decay) void ModelPartForStreamRootBase::Read(Ice::InputStream &) { throw InvalidStreamOperation(__FUNCTION__); } + bool ModelPartForStreamRootBase::HasValue() const { return mp->HasValue(); } + void ModelPartForStreamRootBase::OnEachChild(const ChildHandler & ch) { diff --git a/slicer/slicer/modelPartsTypes.h b/slicer/slicer/modelPartsTypes.h index 0355c62..7e84794 100644 --- a/slicer/slicer/modelPartsTypes.h +++ b/slicer/slicer/modelPartsTypes.h @@ -154,6 +154,7 @@ namespace Slicer { }; template class Hooks; + template class ModelPartForComplex : public ModelPartForComplexBase { public: class HookBase; diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h index 5423152..95d0a37 100644 --- a/slicer/slicer/modelPartsTypes.impl.h +++ b/slicer/slicer/modelPartsTypes.impl.h @@ -26,6 +26,7 @@ #include #include #include + // IWYU pragma: no_forward_declare Slicer::EnumMap namespace Ice { class Object; @@ -405,6 +406,7 @@ namespace Slicer { { static_assert(sizeof...(MD) == N, "Wrong amount of metadata"); } + ~Hook() override = default; SPECIAL_MEMBERS_DEFAULT(Hook); diff --git a/slicer/slicer/serializer.h b/slicer/slicer/serializer.h index 27d70a6..f26a914 100644 --- a/slicer/slicer/serializer.h +++ b/slicer/slicer/serializer.h @@ -8,6 +8,7 @@ #include #include #include + // IWYU pragma: no_include "factory.impl.h" namespace Slicer { @@ -20,6 +21,7 @@ namespace Slicer { virtual void Serialize(ModelPartForRootPtr) = 0; }; + using SerializerPtr = std::shared_ptr; class DLL_PUBLIC Deserializer { @@ -31,6 +33,7 @@ namespace Slicer { virtual void Deserialize(ModelPartForRootPtr) = 0; }; + using DeserializerPtr = std::shared_ptr; using StreamSerializerFactory = AdHoc::Factory; diff --git a/slicer/slicer/slicer.cpp b/slicer/slicer/slicer.cpp index b36d6c6..6f890c3 100644 --- a/slicer/slicer/slicer.cpp +++ b/slicer/slicer/slicer.cpp @@ -29,6 +29,7 @@ namespace Slicer { } AdHocFormatter(InvalidEnumerationSymbolMsg, "Invalid enumeration symbol [%?] for type [%?]"); + void InvalidEnumerationSymbol::ice_print(std::ostream & s) const { @@ -36,6 +37,7 @@ namespace Slicer { } AdHocFormatter(InvalidEnumerationValueMsg, "Invalid enumeration symbol [%?] for type [%?]"); + void InvalidEnumerationValue::ice_print(std::ostream & s) const { @@ -43,6 +45,7 @@ namespace Slicer { } AdHocFormatter(UnknownTypeMsg, "Unknown type [%?]"); + void UnknownType::ice_print(std::ostream & s) const { @@ -50,6 +53,7 @@ namespace Slicer { } AdHocFormatter(NoConversionFoundMsg, "No conversion found for type [%?]"); + void NoConversionFound::ice_print(std::ostream & s) const { @@ -69,6 +73,7 @@ namespace Slicer { } AdHocFormatter(IncorrectElementNameMsg, "Incorrect element name [%?]"); + void IncorrectElementName::ice_print(std::ostream & s) const { @@ -94,6 +99,7 @@ namespace Slicer { } AdHocFormatter(CompilerErrorMsg, "Slicer compiler: %?"); + void CompilerError::ice_print(std::ostream & s) const { @@ -101,6 +107,7 @@ namespace Slicer { } AdHocFormatter(InvalidStreamOperationMsg, "%? is not valid on streams"); + void InvalidStreamOperation::ice_print(std::ostream & s) const { @@ -108,6 +115,7 @@ namespace Slicer { } AdHocFormatter(AbstractClassExceptionMsg, "%? is an abstract class"); + void AbstractClassException::ice_print(std::ostream & s) const { diff --git a/slicer/test/conversions.cpp b/slicer/test/conversions.cpp index 6e74e26..a296197 100644 --- a/slicer/test/conversions.cpp +++ b/slicer/test/conversions.cpp @@ -13,6 +13,7 @@ #include #define SHORT(x) boost::numeric_cast<::Ice::Short, int64_t>(x) + inline auto USHORT(std::integral auto x) { @@ -40,8 +41,8 @@ namespace Slicer { std::string isoDateToString(const ::TestModule::IsoDate & in) { - struct tm tm { - }; + struct tm tm { }; + tm.tm_mday = in.day; tm.tm_mon = in.month - 1; tm.tm_year = in.year - 1900; @@ -56,8 +57,8 @@ namespace Slicer { ::TestModule::IsoDate stringToIsoDate(const std::string & in) { - struct tm tm { - }; + struct tm tm { }; + auto end = strptime(in.c_str(), "%Y-%m-%d", &tm); if (!end || *end) { // LCOV_EXCL_START @@ -71,8 +72,8 @@ namespace Slicer { std::string dateTimeToString(const ::TestModule::DateTime & in) { - struct tm tm { - }; + struct tm tm { }; + tm.tm_sec = in.second; tm.tm_min = in.minute; tm.tm_hour = in.hour; @@ -91,8 +92,8 @@ namespace Slicer { ::TestModule::DateTime stringToDateTime(const std::string & in) { - struct tm tm { - }; + struct tm tm { }; + auto end = strptime(in.c_str(), "%Y-%b-%d %H:%M:%S", &tm); if (!end || *end) { // LCOV_EXCL_START @@ -171,6 +172,7 @@ namespace TestModule { completions += 1; } } + namespace Slicer { template<> DLL_PUBLIC ModelPartPtr diff --git a/slicer/test/conversions.h b/slicer/test/conversions.h index cb46b93..bfa1c4b 100644 --- a/slicer/test/conversions.h +++ b/slicer/test/conversions.h @@ -28,6 +28,7 @@ namespace TestModule { void Complete() override; }; } + namespace Slicer { DLL_PUBLIC ::TestModule::DateTime stringToDateTime(const std::string & in); diff --git a/slicer/test/serializers.cpp b/slicer/test/serializers.cpp index 6efc02b..379551b 100644 --- a/slicer/test/serializers.cpp +++ b/slicer/test/serializers.cpp @@ -50,6 +50,7 @@ namespace fs = std::filesystem; // LCOV_EXCL_START BOOST_TEST_DONT_PRINT_LOG_VALUE(TestModule::ClassMap::iterator) BOOST_TEST_DONT_PRINT_LOG_VALUE(TestModule::SomeNumbers) + namespace std { template ostream & @@ -58,6 +59,7 @@ namespace std { return s; } } + // LCOV_EXCL_STOP class FileBased { diff --git a/slicer/tool/icemetadata.cpp b/slicer/tool/icemetadata.cpp index cecf703..4804542 100644 --- a/slicer/tool/icemetadata.cpp +++ b/slicer/tool/icemetadata.cpp @@ -1,6 +1,7 @@ #include "icemetadata.h" #include #include + // IWYU pragma: no_include namespace Slicer { diff --git a/slicer/tool/parser.cpp b/slicer/tool/parser.cpp index ec94a43..28252b5 100644 --- a/slicer/tool/parser.cpp +++ b/slicer/tool/parser.cpp @@ -53,26 +53,31 @@ namespace Slicer { { return countIfUsed(c, classes, !c->isInterface()); } + [[nodiscard]] bool visitStructStart(const Slice::StructPtr & s) override { return countIfUsed(s, structs); } + void visitSequence(const Slice::SequencePtr & s) override { countIfUsed(s, sequences); } + void visitDictionary(const Slice::DictionaryPtr & d) override { countIfUsed(d, dictionaries); } + void visitEnum(const Slice::EnumPtr & e) override { countIfUsed(e, enums); } + [[nodiscard]] auto complexes() const { diff --git a/slicer/tool/parser.h b/slicer/tool/parser.h index a784d7a..e56c90a 100644 --- a/slicer/tool/parser.h +++ b/slicer/tool/parser.h @@ -10,6 +10,7 @@ #include #include #include + // IWYU pragma: no_include namespace Slicer { @@ -27,6 +28,7 @@ namespace Slicer { public: struct Args : public SplitString { explicit inline Args(std::string_view in) : SplitString {in, ","} { } + using SplitString::SplitString; }; diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp index 96c1a9f..1ffa897 100644 --- a/slicer/xml/serializer.cpp +++ b/slicer/xml/serializer.cpp @@ -119,6 +119,7 @@ namespace Slicer { class XmlContentValueSource : public XmlValueSource { public: explicit XmlContentValueSource() : XmlValueSource(Glib::ustring()) { } + explicit XmlContentValueSource(const xmlpp::ContentNode * c) : XmlValueSource(c->get_content()) { } }; @@ -474,6 +475,7 @@ namespace Slicer { } AdHocFormatter(BadBooleanValueMsg, "Bad boolean value [%?]"); + void BadBooleanValue::ice_print(std::ostream & s) const { diff --git a/slicer/xml/serializer.h b/slicer/xml/serializer.h index d07a77e..23a6140 100644 --- a/slicer/xml/serializer.h +++ b/slicer/xml/serializer.h @@ -19,6 +19,7 @@ #include #include #include + namespace Glib { class ustring; } diff --git a/slicer/xml/testSpecifics.cpp b/slicer/xml/testSpecifics.cpp index e2d7691..ec9fe11 100644 --- a/slicer/xml/testSpecifics.cpp +++ b/slicer/xml/testSpecifics.cpp @@ -16,6 +16,7 @@ #include #include #include + // IWYU pragma: no_forward_declare Slicer::BadBooleanValue // IWYU pragma: no_forward_declare Slicer::XmlDocumentDeserializer -- cgit v1.2.3 From 8235ae6999b4fe148805651bd7be6ee667cbb8c2 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 5 Aug 2023 12:19:35 +0100 Subject: Refactor JsonSerializer::ModelTreeIterate with no pointer copy --- slicer/json/serializer.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp index 227f3c9..0c993c4 100644 --- a/slicer/json/serializer.cpp +++ b/slicer/json/serializer.cpp @@ -267,17 +267,20 @@ namespace Slicer { } case ModelPartType::Complex: if (mp->HasValue()) { - json::Object nn; + auto oec = [n, &name](const auto & lmp) { + auto & obj = std::get(*n).emplace(name, json::Object {}).first->second; + lmp->OnEachChild([&obj](auto && PH1, auto && PH2, auto &&) { + return JsonSerializer::ModelTreeIterate(&obj, PH1, PH2); + }); + return &std::get(obj); + }; if (auto typeIdName = mp->GetTypeIdProperty()) { if (auto typeId = mp->GetTypeId()) { - nn.insert({*typeIdName, *typeId}); - mp = mp->GetSubclassModelPart(*typeId); + oec(mp->GetSubclassModelPart(*typeId))->emplace(*typeIdName, *typeId); + return; } } - mp->OnEachChild([capture0 = &std::get(*n).insert({name, nn}).first->second]( - auto && PH1, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterate(capture0, PH1, PH2); - }); + oec(mp); } break; case ModelPartType::Sequence: -- cgit v1.2.3 From b3f01efdec0a74dc353e14ce278e9bdabb51793f Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 5 Aug 2023 12:33:31 +0100 Subject: Refactor JsonSerializer::ModelTreeIterateRoot with no pointer copy --- slicer/json/serializer.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp index 0c993c4..728d174 100644 --- a/slicer/json/serializer.cpp +++ b/slicer/json/serializer.cpp @@ -324,18 +324,23 @@ namespace Slicer { case ModelPartType::Simple: mp->GetValue(JsonValueTarget(*n)); break; - case ModelPartType::Complex: - *n = json::Object(); + case ModelPartType::Complex: { + auto oec = [n](const auto & lmp) { + *n = json::Object(); + lmp->OnEachChild([n](auto && PH1, auto && PH2, auto &&) { + return JsonSerializer::ModelTreeIterate(n, PH1, PH2); + }); + return &std::get(*n); + }; if (auto typeIdName = mp->GetTypeIdProperty()) { if (auto typeId = mp->GetTypeId()) { - std::get(*n).insert({*typeIdName, *typeId}); - mp = mp->GetSubclassModelPart(*typeId); + oec(mp->GetSubclassModelPart(*typeId))->emplace(*typeIdName, *typeId); + return; } } - mp->OnEachChild([n](auto && PH1, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterate(n, PH1, PH2); - }); + oec(mp); break; + } case ModelPartType::Sequence: *n = json::Array(); mp->OnEachChild([n](auto &&, auto && PH2, auto &&) { -- cgit v1.2.3 From 2ef69e79492a47704eed0faa01351ba88a4e6605 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 5 Aug 2023 12:52:19 +0100 Subject: Refactor XmlSerializer::ModelTreeProcessElement with no pointer copy --- slicer/xml/serializer.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp index 1ffa897..acbb83d 100644 --- a/slicer/xml/serializer.cpp +++ b/slicer/xml/serializer.cpp @@ -407,16 +407,19 @@ namespace Slicer { mp->GetValue(XmlContentValueTarget(cec)); } else if (mp->HasValue()) { - auto typeIdPropName = mp->GetTypeIdProperty(); - auto typeId = mp->GetTypeId(); - auto element = cec.get(); - if (typeId && typeIdPropName) { - element->set_attribute(*typeIdPropName, *typeId); - mp = mp->GetSubclassModelPart(*typeId); + auto oec = [element = cec.get(), &ec](const auto & lmp) { + lmp->OnEachChild([element, &ec](auto && PH1, auto && PH2, auto && PH3) { + return XmlSerializer::ModelTreeIterate(element, PH1, PH2, PH3, ec); + }); + return element; + }; + if (auto typeIdPropName = mp->GetTypeIdProperty()) { + if (auto typeId = mp->GetTypeId()) { + oec(mp->GetSubclassModelPart(*typeId))->set_attribute(*typeIdPropName, *typeId); + return; + } } - mp->OnEachChild([element, ec](auto && PH1, auto && PH2, auto && PH3) { - return XmlSerializer::ModelTreeIterate(element, PH1, PH2, PH3, ec); - }); + oec(mp); } } -- cgit v1.2.3 From d88e0d955d74f6b274d094539c4a223243ef948c Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 5 Aug 2023 13:05:56 +0100 Subject: Refactor XmlDeserializer::DocumentTreeIterateElement with no pointer copy --- slicer/xml/serializer.cpp | 52 +++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp index acbb83d..609eac2 100644 --- a/slicer/xml/serializer.cpp +++ b/slicer/xml/serializer.cpp @@ -255,35 +255,39 @@ namespace Slicer { void XmlDeserializer::DocumentTreeIterateElement(const xmlpp::Element * element, ModelPartPtr smp, const ChildRef & smpr) { - if (auto typeIdPropName = smp->GetTypeIdProperty()) { - if (auto typeAttr = element->get_attribute(*typeIdPropName)) { - smp = smp->GetSubclassModelPart(typeAttr->get_value()); - } - } - smp->Create(); - if (smpr.ChildMetaData().flagSet(md_attributes)) { - auto attrs(element->get_attributes()); - if (!attrs.empty()) { - DocumentTreeIterateDictAttrs(attrs, smp); - } - } - else if (smpr.ChildMetaData().flagSet(md_elements)) { - DocumentTreeIterateDictElements(element, smp); - } - else { - auto attrs(element->get_attributes()); - if (!attrs.empty()) { - DocumentTreeIterate(attrs.front(), smp); + auto oec = [&smpr, element](const auto & lmp) { + lmp->Create(); + if (smpr.ChildMetaData().flagSet(md_attributes)) { + auto attrs(element->get_attributes()); + if (!attrs.empty()) { + DocumentTreeIterateDictAttrs(attrs, lmp); + } } - auto firstChild = element->get_first_child(); - if (firstChild) { - DocumentTreeIterate(firstChild, smp); + else if (smpr.ChildMetaData().flagSet(md_elements)) { + DocumentTreeIterateDictElements(element, lmp); } else { - smp->SetValue(XmlContentValueSource()); + auto attrs(element->get_attributes()); + if (!attrs.empty()) { + DocumentTreeIterate(attrs.front(), lmp); + } + auto firstChild = element->get_first_child(); + if (firstChild) { + DocumentTreeIterate(firstChild, lmp); + } + else { + lmp->SetValue(XmlContentValueSource()); + } + } + lmp->Complete(); + }; + if (auto typeIdPropName = smp->GetTypeIdProperty()) { + if (auto typeAttr = element->get_attribute(*typeIdPropName)) { + oec(smp->GetSubclassModelPart(typeAttr->get_value())); + return; } } - smp->Complete(); + oec(smp); } void -- cgit v1.2.3 From b7b55963d23b661b69b1a2d9e40d51c1f809391f Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 5 Aug 2023 14:02:39 +0100 Subject: Constref correctness for shared_ptr parameters --- slicer/json/serializer.cpp | 4 ++-- slicer/json/serializer.h | 4 ++-- slicer/slicer/modelPartsTypes.cpp | 3 --- slicer/slicer/modelPartsTypes.h | 2 +- slicer/slicer/slicer.cpp | 2 +- slicer/xml/serializer.cpp | 5 +++-- slicer/xml/serializer.h | 6 ++++-- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp index 728d174..d20efeb 100644 --- a/slicer/json/serializer.cpp +++ b/slicer/json/serializer.cpp @@ -249,7 +249,7 @@ namespace Slicer { } void - JsonSerializer::ModelTreeIterate(json::Value * n, const std::string & name, ModelPartPtr mp) + JsonSerializer::ModelTreeIterate(json::Value * n, const std::string & name, const ModelPartPtr & mp) { if (name.empty() || !n || !mp) { return; @@ -314,7 +314,7 @@ namespace Slicer { } void - JsonSerializer::ModelTreeIterateRoot(json::Value * n, ModelPartPtr mp) + JsonSerializer::ModelTreeIterateRoot(json::Value * n, const ModelPartPtr & mp) { if (mp) { switch (mp->GetType()) { diff --git a/slicer/json/serializer.h b/slicer/json/serializer.h index e2687ce..3d92053 100644 --- a/slicer/json/serializer.h +++ b/slicer/json/serializer.h @@ -13,10 +13,10 @@ namespace Slicer { class JsonSerializer : public Serializer { protected: - static void ModelTreeIterate(json::Value *, const std::string &, ModelPartPtr mp); + static void ModelTreeIterate(json::Value *, const std::string &, const ModelPartPtr & mp); static void ModelTreeIterateDictObj(json::Value *, const ModelPartPtr & mp); static void ModelTreeIterateSeq(json::Value *, const ModelPartPtr & mp); - static void ModelTreeIterateRoot(json::Value *, ModelPartPtr mp); + static void ModelTreeIterateRoot(json::Value *, const ModelPartPtr & mp); }; class DLL_PUBLIC JsonValueSerializer : public JsonSerializer { diff --git a/slicer/slicer/modelPartsTypes.cpp b/slicer/slicer/modelPartsTypes.cpp index aabbf57..cd22c05 100644 --- a/slicer/slicer/modelPartsTypes.cpp +++ b/slicer/slicer/modelPartsTypes.cpp @@ -443,9 +443,6 @@ namespace Slicer { return true; } - // Stream Roots - ModelPartForStreamRootBase::ModelPartForStreamRootBase(const ModelPartPtr & m) : ModelPartForRootBase(m) { } - // NOLINTNEXTLINE(hicpp-no-array-decay) void ModelPartForStreamRootBase::Write(Ice::OutputStream &) const diff --git a/slicer/slicer/modelPartsTypes.h b/slicer/slicer/modelPartsTypes.h index 7e84794..b6e7b3c 100644 --- a/slicer/slicer/modelPartsTypes.h +++ b/slicer/slicer/modelPartsTypes.h @@ -354,7 +354,7 @@ namespace Slicer { class DLL_PUBLIC ModelPartForStreamRootBase : public ModelPartForRootBase { public: - explicit ModelPartForStreamRootBase(const ModelPartPtr & mp); + using ModelPartForRootBase::ModelPartForRootBase; void Write(Ice::OutputStream &) const override; void Read(Ice::InputStream &) override; diff --git a/slicer/slicer/slicer.cpp b/slicer/slicer/slicer.cpp index 6f890c3..2eda740 100644 --- a/slicer/slicer/slicer.cpp +++ b/slicer/slicer/slicer.cpp @@ -9,7 +9,7 @@ namespace Slicer { Slicer::ChildRef::ChildRef(ModelPartPtr m) : mpp(std::move(m)), mdr(emptyMetadata) { } - Slicer::ChildRef::ChildRef(Slicer::ModelPartPtr mp, const Slicer::Metadata & md) : mpp(std::move(mp)), mdr(md) { } + Slicer::ChildRef::ChildRef(ModelPartPtr mp, const Slicer::Metadata & md) : mpp(std::move(mp)), mdr(md) { } ModelPartPtr Slicer::ChildRef::Child() const diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp index 609eac2..27bf10b 100644 --- a/slicer/xml/serializer.cpp +++ b/slicer/xml/serializer.cpp @@ -253,7 +253,8 @@ namespace Slicer { } void - XmlDeserializer::DocumentTreeIterateElement(const xmlpp::Element * element, ModelPartPtr smp, const ChildRef & smpr) + XmlDeserializer::DocumentTreeIterateElement( + const xmlpp::Element * element, const ModelPartPtr & smp, const ChildRef & smpr) { auto oec = [&smpr, element](const auto & lmp) { lmp->Create(); @@ -405,7 +406,7 @@ namespace Slicer { void XmlSerializer::ModelTreeProcessElement( - const CurrentElementCreator & cec, ModelPartPtr mp, const ElementCreator & ec) + const CurrentElementCreator & cec, const ModelPartPtr & mp, const ElementCreator & ec) { if (mp->GetType() == ModelPartType::Simple) { mp->GetValue(XmlContentValueTarget(cec)); diff --git a/slicer/xml/serializer.h b/slicer/xml/serializer.h index 23a6140..9b8fa21 100644 --- a/slicer/xml/serializer.h +++ b/slicer/xml/serializer.h @@ -35,7 +35,8 @@ namespace Slicer { static void ModelTreeIterateRoot(xmlpp::Document *, const std::string &, const ModelPartPtr & mp); protected: - static void ModelTreeProcessElement(const CurrentElementCreator &, ModelPartPtr mp, const ElementCreator &); + static void ModelTreeProcessElement( + const CurrentElementCreator &, const ModelPartPtr & mp, const ElementCreator &); static void ModelTreeIterateDictAttrs(xmlpp::Element * element, const ModelPartPtr & dict); static void ModelTreeIterateDictElements(xmlpp::Element * element, const ModelPartPtr & dict); }; @@ -69,7 +70,8 @@ namespace Slicer { class DLL_PUBLIC XmlDeserializer : public Deserializer { protected: static void DocumentTreeIterate(const xmlpp::Node * node, const ModelPartPtr & mp); - static void DocumentTreeIterateElement(const xmlpp::Element * element, ModelPartPtr mp, const ChildRef & c); + static void DocumentTreeIterateElement( + const xmlpp::Element * element, const ModelPartPtr & mp, const ChildRef & c); static void DocumentTreeIterate(const xmlpp::Document * doc, const ModelPartPtr & mp); static void DocumentTreeIterateDictAttrs( const xmlpp::Element::const_AttributeList & attrs, const ModelPartPtr & dict); -- cgit v1.2.3 From 56fef50c0a7c0e3a604b8a9b68017ed265b9fa88 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 5 Aug 2023 15:23:10 +0100 Subject: Use faster std::from_chars over boost::lexical_cast for XML numeric parse --- slicer/xml/serializer.cpp | 31 +++++++++++++++++++++++++------ slicer/xml/testSpecifics.cpp | 6 +++--- slicer/xml/xmlExceptions.ice | 4 ++++ 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp index 27bf10b..56cdbaa 100644 --- a/slicer/xml/serializer.cpp +++ b/slicer/xml/serializer.cpp @@ -1,5 +1,6 @@ #include "serializer.h" #include +#include #include #include #pragma GCC diagnostic push @@ -73,37 +74,37 @@ namespace Slicer { void set(Ice::Byte & v) const override { - v = boost::numeric_cast(boost::lexical_cast(value)); + from_chars(v); } void set(Ice::Short & v) const override { - v = boost::lexical_cast(value); + from_chars(v); } void set(Ice::Int & v) const override { - v = boost::lexical_cast(value); + from_chars(v); } void set(Ice::Long & v) const override { - v = boost::lexical_cast(value); + from_chars(v); } void set(Ice::Float & v) const override { - v = boost::lexical_cast(value); + from_chars(v); } void set(Ice::Double & v) const override { - v = boost::lexical_cast(value); + from_chars(v); } void @@ -113,6 +114,16 @@ namespace Slicer { } private: + template + void + from_chars(T & v) const + { + std::string_view raw {value.raw()}; + if (std::from_chars(raw.begin(), raw.end(), v).ec != std::errc {}) { + throw BadNumericValue(value); + } + } + const Glib::ustring value; }; @@ -489,4 +500,12 @@ namespace Slicer { { BadBooleanValueMsg::write(s, text); } + + AdHocFormatter(BadNumericValueMsg, "Bad numeric value [%?]"); + + void + BadNumericValue::ice_print(std::ostream & s) const + { + BadNumericValueMsg::write(s, text); + } } diff --git a/slicer/xml/testSpecifics.cpp b/slicer/xml/testSpecifics.cpp index ec9fe11..24edf78 100644 --- a/slicer/xml/testSpecifics.cpp +++ b/slicer/xml/testSpecifics.cpp @@ -54,11 +54,11 @@ BOOST_AUTO_TEST_CASE(int_values) doc.parse_memory("-4"); BOOST_REQUIRE_EQUAL(-4, BoostThrowWrapperHelper(doc.get_document())); doc.parse_memory(" "); - BOOST_REQUIRE_THROW(BoostThrowWrapperHelper(doc.get_document()), std::bad_cast); + BOOST_REQUIRE_THROW(BoostThrowWrapperHelper(doc.get_document()), Slicer::BadNumericValue); doc.parse_memory("notanint"); - BOOST_REQUIRE_THROW(BoostThrowWrapperHelper(doc.get_document()), std::bad_cast); + BOOST_REQUIRE_THROW(BoostThrowWrapperHelper(doc.get_document()), Slicer::BadNumericValue); doc.parse_memory(""); - BOOST_REQUIRE_THROW(BoostThrowWrapperHelper(doc.get_document()), std::bad_cast); + BOOST_REQUIRE_THROW(BoostThrowWrapperHelper(doc.get_document()), Slicer::BadNumericValue); } BOOST_AUTO_TEST_CASE(factories) diff --git a/slicer/xml/xmlExceptions.ice b/slicer/xml/xmlExceptions.ice index 390f458..26d8aa2 100644 --- a/slicer/xml/xmlExceptions.ice +++ b/slicer/xml/xmlExceptions.ice @@ -8,6 +8,10 @@ module Slicer { exception BadBooleanValue extends DeserializerError { string text; }; + ["cpp:ice_print"] + exception BadNumericValue extends DeserializerError { + string text; + }; }; #endif -- cgit v1.2.3 From c70948134af3be3239b2fc1e08d1226ded3a2cdf Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 5 Aug 2023 15:43:57 +0100 Subject: Use Glib::ustring::format over boost::lexical_cast for XML numeric format --- slicer/xml/serializer.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp index 56cdbaa..7494c6e 100644 --- a/slicer/xml/serializer.cpp +++ b/slicer/xml/serializer.cpp @@ -1,5 +1,4 @@ #include "serializer.h" -#include #include #include #include @@ -157,37 +156,37 @@ namespace Slicer { void get(const Ice::Byte & value) const override { - apply(boost::lexical_cast(value)); + apply(Glib::ustring::format(value)); } void get(const Ice::Short & value) const override { - apply(boost::lexical_cast(value)); + apply(Glib::ustring::format(value)); } void get(const Ice::Int & value) const override { - apply(boost::lexical_cast(value)); + apply(Glib::ustring::format(value)); } void get(const Ice::Long & value) const override { - apply(boost::lexical_cast(value)); + apply(Glib::ustring::format(value)); } void get(const Ice::Float & value) const override { - apply(boost::lexical_cast(value)); + apply(Glib::ustring::format(value)); } void get(const Ice::Double & value) const override { - apply(boost::lexical_cast(value)); + apply(Glib::ustring::format(value)); } void -- cgit v1.2.3 From cc387b9da6b3e884e8e69296293bd30413247a32 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 5 Aug 2023 16:24:58 +0100 Subject: Modernize XML specific tests --- slicer/xml/testSpecifics.cpp | 81 +++++++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 32 deletions(-) diff --git a/slicer/xml/testSpecifics.cpp b/slicer/xml/testSpecifics.cpp index 24edf78..6f94ed4 100644 --- a/slicer/xml/testSpecifics.cpp +++ b/slicer/xml/testSpecifics.cpp @@ -1,4 +1,5 @@ #define BOOST_TEST_MODULE xml_specifics +#include #include #include "serializer.h" @@ -20,47 +21,63 @@ // IWYU pragma: no_forward_declare Slicer::BadBooleanValue // IWYU pragma: no_forward_declare Slicer::XmlDocumentDeserializer -template -T -BoostThrowWrapperHelper(P &&... p) +template +const auto BoostThrowWrapperHelper + = Slicer::DeserializeAny; + +template using data = std::tuple; +BOOST_FIXTURE_TEST_SUITE(doc, xmlpp::DomParser) + +BOOST_DATA_TEST_CASE(good_boolean_values, + boost::unit_test::data::make>({ + {"true", true}, + {"false", false}, + }), + in, exp) +{ + parse_memory(in); + BOOST_CHECK_EQUAL(exp, BoostThrowWrapperHelper(get_document())); +} + +BOOST_DATA_TEST_CASE(bad_boolean_values, + boost::unit_test::data::make({ + "nonsense", + " ", + "", + }), + in) { - return Slicer::DeserializeAny(std::forward

(p)...); + parse_memory(in); + BOOST_CHECK_THROW(BoostThrowWrapperHelper(get_document()), Slicer::BadBooleanValue); } -BOOST_AUTO_TEST_CASE(boolean_values) +BOOST_DATA_TEST_CASE(good_integer_values, + boost::unit_test::data::make>({ + {"13", 13}, + {"84", 84}, + {"0", 0}, + {"-4", -4}, + }), + in, exp) { - xmlpp::DomParser doc; - doc.parse_memory("true"); - BOOST_REQUIRE_EQUAL(true, BoostThrowWrapperHelper(doc.get_document())); - doc.parse_memory("false"); - BOOST_REQUIRE_EQUAL(false, BoostThrowWrapperHelper(doc.get_document())); - doc.parse_memory("nonsense"); - BOOST_REQUIRE_THROW(BoostThrowWrapperHelper(doc.get_document()), Slicer::BadBooleanValue); - doc.parse_memory(" "); - BOOST_REQUIRE_THROW(BoostThrowWrapperHelper(doc.get_document()), Slicer::BadBooleanValue); - doc.parse_memory(""); - BOOST_REQUIRE_THROW(BoostThrowWrapperHelper(doc.get_document()), Slicer::BadBooleanValue); + parse_memory(in); + BOOST_CHECK_EQUAL(exp, BoostThrowWrapperHelper(get_document())); } -BOOST_AUTO_TEST_CASE(int_values) +BOOST_DATA_TEST_CASE(bad_integer_values, + boost::unit_test::data::make({ + " ", + "notanint", + "", + }), + in) { - xmlpp::DomParser doc; - doc.parse_memory("13"); - BOOST_REQUIRE_EQUAL(13, BoostThrowWrapperHelper(doc.get_document())); - doc.parse_memory("84"); - BOOST_REQUIRE_EQUAL(84, BoostThrowWrapperHelper(doc.get_document())); - doc.parse_memory("0"); - BOOST_REQUIRE_EQUAL(0, BoostThrowWrapperHelper(doc.get_document())); - doc.parse_memory("-4"); - BOOST_REQUIRE_EQUAL(-4, BoostThrowWrapperHelper(doc.get_document())); - doc.parse_memory(" "); - BOOST_REQUIRE_THROW(BoostThrowWrapperHelper(doc.get_document()), Slicer::BadNumericValue); - doc.parse_memory("notanint"); - BOOST_REQUIRE_THROW(BoostThrowWrapperHelper(doc.get_document()), Slicer::BadNumericValue); - doc.parse_memory(""); - BOOST_REQUIRE_THROW(BoostThrowWrapperHelper(doc.get_document()), Slicer::BadNumericValue); + parse_memory(in); + BOOST_CHECK_THROW(BoostThrowWrapperHelper(get_document()), Slicer::BadNumericValue); } +BOOST_AUTO_TEST_SUITE_END() + BOOST_AUTO_TEST_CASE(factories) { BOOST_REQUIRE(Slicer::FileSerializerFactory::createNew(".xml", "/some.xml")); -- cgit v1.2.3 From 8f3ddf449bc8a9174f9b29483dc5bcb55a28b8f4 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 5 Aug 2023 17:44:47 +0100 Subject: Fix constref correctness for shared_ptr parameter in ChildHandler --- slicer/slicer/modelParts.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slicer/slicer/modelParts.h b/slicer/slicer/modelParts.h index e5e323f..d0a1f06 100644 --- a/slicer/slicer/modelParts.h +++ b/slicer/slicer/modelParts.h @@ -80,7 +80,7 @@ namespace Slicer { using ModelPartPtr = std::shared_ptr; using ModelPartForRootPtr = std::shared_ptr; using TypeId = std::optional; - using ChildHandler = std::function; + using ChildHandler = std::function; using ClassRef = std::function; using HookFilter = std::function; using Metadata = MetaData<>; -- cgit v1.2.3 From fc206f13c627908526a3eed6b2dba04098ecc2e7 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 5 Aug 2023 19:57:14 +0100 Subject: Introduce any_ptr and replace shared_ptr model part params --- slicer/db/sqlInsertSerializer.cpp | 22 ++++++++-------- slicer/db/sqlInsertSerializer.h | 18 ++++++------- slicer/db/sqlSelectDeserializer.cpp | 8 +++--- slicer/db/sqlSelectDeserializer.h | 8 +++--- slicer/db/sqlUpdateSerializer.cpp | 18 ++++++------- slicer/db/sqlUpdateSerializer.h | 8 +++--- slicer/json/serializer.cpp | 8 +++--- slicer/json/serializer.h | 8 +++--- slicer/slicer/any_ptr.h | 52 +++++++++++++++++++++++++++++++++++++ slicer/slicer/modelParts.cpp | 2 +- slicer/slicer/modelParts.h | 6 +++-- slicer/test/compilation.cpp | 2 +- slicer/xml/serializer.cpp | 20 +++++++------- slicer/xml/serializer.h | 24 ++++++++--------- 14 files changed, 128 insertions(+), 76 deletions(-) create mode 100644 slicer/slicer/any_ptr.h diff --git a/slicer/db/sqlInsertSerializer.cpp b/slicer/db/sqlInsertSerializer.cpp index b4d46e6..c120f10 100644 --- a/slicer/db/sqlInsertSerializer.cpp +++ b/slicer/db/sqlInsertSerializer.cpp @@ -42,23 +42,23 @@ namespace Slicer { } void - SqlInsertSerializer::SerializeObject(const Slicer::ModelPartPtr & mp) const + SqlInsertSerializer::SerializeObject(ModelPartParam mp) const { auto ins = createInsert(mp); bindObjectAndExecute(mp, ins.get()); } void - SqlInsertSerializer::SerializeSequence(const Slicer::ModelPartPtr & mp) const + SqlInsertSerializer::SerializeSequence(ModelPartParam mp) const { auto ins = createInsert(mp->GetContainedModelPart()); - mp->OnEachChild([&ins, this](const std::string &, const ModelPartPtr & cmp, const HookCommon *) { + mp->OnEachChild([&ins, this](auto &&, auto && cmp, auto &&) { bindObjectAndExecute(cmp, ins.get()); }); } void - SqlInsertSerializer::bindObjectAndExecute(const Slicer::ModelPartPtr & cmp, DB::ModifyCommand * ins) const + SqlInsertSerializer::bindObjectAndExecute(ModelPartParam cmp, DB::ModifyCommand * ins) const { unsigned int paramNo = 0; cmp->OnEachChild([this, ¶mNo, ins](auto &&, auto && PH2, auto && PH3) { @@ -103,10 +103,10 @@ namespace Slicer { }; void - SqlFetchIdInsertSerializer::bindObjectAndExecute(const Slicer::ModelPartPtr & mp, DB::ModifyCommand * ins) const + SqlFetchIdInsertSerializer::bindObjectAndExecute(ModelPartParam mp, DB::ModifyCommand * ins) const { SqlAutoIdInsertSerializer::bindObjectAndExecute(mp, ins); - mp->OnEachChild([this](const std::string &, const ModelPartPtr & cmp, const HookCommon * h) { + mp->OnEachChild([this](auto &&, auto && cmp, auto && h) { if (isAuto(h)) { cmp->SetValue(IdSave(connection)); } @@ -114,8 +114,8 @@ namespace Slicer { } void - SqlInsertSerializer::bindObjectAndExecuteField(unsigned int & paramNo, DB::ModifyCommand * ins, - const Slicer::ModelPartPtr & cmp, const HookCommon * h) const + SqlInsertSerializer::bindObjectAndExecuteField( + unsigned int & paramNo, DB::ModifyCommand * ins, ModelPartParam cmp, const HookCommon * h) const { if (isBind(h)) { if (!cmp->GetValue(SqlBinder(*ins, paramNo))) { @@ -126,8 +126,8 @@ namespace Slicer { } void - SqlAutoIdInsertSerializer::bindObjectAndExecuteField(unsigned int & paramNo, DB::ModifyCommand * ins, - const Slicer::ModelPartPtr & cmp, const HookCommon * h) const + SqlAutoIdInsertSerializer::bindObjectAndExecuteField( + unsigned int & paramNo, DB::ModifyCommand * ins, ModelPartParam cmp, const HookCommon * h) const { if (isNotAuto(h)) { SqlInsertSerializer::bindObjectAndExecuteField(paramNo, ins, cmp, h); @@ -135,7 +135,7 @@ namespace Slicer { } DB::ModifyCommandPtr - SqlInsertSerializer::createInsert(const Slicer::ModelPartPtr & mp) const + SqlInsertSerializer::createInsert(ModelPartParam mp) const { using namespace AdHoc::literals; std::stringstream insert; diff --git a/slicer/db/sqlInsertSerializer.h b/slicer/db/sqlInsertSerializer.h index 4a6a423..3451455 100644 --- a/slicer/db/sqlInsertSerializer.h +++ b/slicer/db/sqlInsertSerializer.h @@ -21,14 +21,14 @@ namespace Slicer { void Serialize(Slicer::ModelPartForRootPtr) override; protected: - void SerializeObject(const Slicer::ModelPartPtr &) const; - void SerializeSequence(const Slicer::ModelPartPtr &) const; - DB::ModifyCommandPtr createInsert(const Slicer::ModelPartPtr &) const; + void SerializeObject(ModelPartParam) const; + void SerializeSequence(ModelPartParam) const; + [[nodiscard]] DB::ModifyCommandPtr createInsert(ModelPartParam) const; virtual void createInsertField( unsigned int & fieldNo, std::ostream & insert, const std::string & name, const HookCommon * h) const; - virtual void bindObjectAndExecute(const Slicer::ModelPartPtr &, DB::ModifyCommand *) const; + virtual void bindObjectAndExecute(ModelPartParam, DB::ModifyCommand *) const; virtual void bindObjectAndExecuteField( - unsigned int & paramNo, DB::ModifyCommand *, const Slicer::ModelPartPtr &, const HookCommon *) const; + unsigned int & paramNo, DB::ModifyCommand *, ModelPartParam, const HookCommon *) const; DB::Connection * const connection; const std::string tableName; @@ -42,10 +42,10 @@ namespace Slicer { } protected: - virtual void createInsertField(unsigned int & fieldNo, std::ostream & insert, const std::string & name, + void createInsertField(unsigned int & fieldNo, std::ostream & insert, const std::string & name, const HookCommon * h) const override; - virtual void bindObjectAndExecuteField(unsigned int & paramNo, DB::ModifyCommand *, - const Slicer::ModelPartPtr &, const HookCommon *) const override; + void bindObjectAndExecuteField( + unsigned int & paramNo, DB::ModifyCommand *, ModelPartParam, const HookCommon *) const override; }; class DLL_PUBLIC SqlFetchIdInsertSerializer : public SqlAutoIdInsertSerializer { @@ -56,7 +56,7 @@ namespace Slicer { } protected: - virtual void bindObjectAndExecute(const Slicer::ModelPartPtr &, DB::ModifyCommand *) const override; + void bindObjectAndExecute(ModelPartParam, DB::ModifyCommand *) const override; }; } diff --git a/slicer/db/sqlSelectDeserializer.cpp b/slicer/db/sqlSelectDeserializer.cpp index f3f3c07..554703f 100644 --- a/slicer/db/sqlSelectDeserializer.cpp +++ b/slicer/db/sqlSelectDeserializer.cpp @@ -38,7 +38,7 @@ namespace Slicer { } void - SqlSelectDeserializer::DeserializeSimple(const Slicer::ModelPartPtr & mp) + SqlSelectDeserializer::DeserializeSimple(ModelPartParam mp) { if (!cmd->fetch()) { if (!mp->IsOptional()) { @@ -58,7 +58,7 @@ namespace Slicer { } void - SqlSelectDeserializer::DeserializeSequence(const Slicer::ModelPartPtr & omp) + SqlSelectDeserializer::DeserializeSequence(ModelPartParam omp) { auto mp = omp->GetAnonChild(); while (cmd->fetch()) { @@ -67,7 +67,7 @@ namespace Slicer { } void - SqlSelectDeserializer::DeserializeObject(const Slicer::ModelPartPtr & mp) + SqlSelectDeserializer::DeserializeObject(ModelPartParam mp) { if (!cmd->fetch()) { if (!mp->IsOptional()) { @@ -83,7 +83,7 @@ namespace Slicer { } void - SqlSelectDeserializer::DeserializeRow(const Slicer::ModelPartPtr & mp) + SqlSelectDeserializer::DeserializeRow(ModelPartParam mp) { auto rmp = mp->GetAnonChild(); if (rmp) { diff --git a/slicer/db/sqlSelectDeserializer.h b/slicer/db/sqlSelectDeserializer.h index 9e9d499..32106d7 100644 --- a/slicer/db/sqlSelectDeserializer.h +++ b/slicer/db/sqlSelectDeserializer.h @@ -20,10 +20,10 @@ namespace Slicer { void Deserialize(Slicer::ModelPartForRootPtr) override; protected: - void DLL_PRIVATE DeserializeSimple(const Slicer::ModelPartPtr &); - void DLL_PRIVATE DeserializeObject(const Slicer::ModelPartPtr &); - void DLL_PRIVATE DeserializeSequence(const Slicer::ModelPartPtr &); - void DLL_PRIVATE DeserializeRow(const Slicer::ModelPartPtr &); + void DLL_PRIVATE DeserializeSimple(ModelPartParam); + void DLL_PRIVATE DeserializeObject(ModelPartParam); + void DLL_PRIVATE DeserializeSequence(ModelPartParam); + void DLL_PRIVATE DeserializeRow(ModelPartParam); DB::SelectCommand * cmd; unsigned int columnCount; diff --git a/slicer/db/sqlUpdateSerializer.cpp b/slicer/db/sqlUpdateSerializer.cpp index 038f28e..8a3c3a4 100644 --- a/slicer/db/sqlUpdateSerializer.cpp +++ b/slicer/db/sqlUpdateSerializer.cpp @@ -40,26 +40,26 @@ namespace Slicer { } void - SqlUpdateSerializer::SerializeObject(const Slicer::ModelPartPtr & mp) const + SqlUpdateSerializer::SerializeObject(ModelPartParam mp) const { auto ins = createUpdate(mp); bindObjectAndExecute(mp, ins.get()); } void - SqlUpdateSerializer::SerializeSequence(const Slicer::ModelPartPtr & mp) const + SqlUpdateSerializer::SerializeSequence(ModelPartParam mp) const { auto ins = createUpdate(mp->GetContainedModelPart()); - mp->OnEachChild([&ins](const std::string &, const ModelPartPtr & cmp, const HookCommon *) { + mp->OnEachChild([&ins](auto &&, auto && cmp, auto &&) { bindObjectAndExecute(cmp, ins.get()); }); } void - SqlUpdateSerializer::bindObjectAndExecute(const Slicer::ModelPartPtr & mp, DB::ModifyCommand * upd) + SqlUpdateSerializer::bindObjectAndExecute(ModelPartParam mp, DB::ModifyCommand * upd) { unsigned int paramNo = 0; - mp->OnEachChild([&upd, ¶mNo](const std::string &, const ModelPartPtr & cmp, const HookCommon * h) { + mp->OnEachChild([&upd, ¶mNo](auto &&, auto && cmp, auto && h) { if (isValue(h)) { if (!cmp->GetValue(SqlBinder(*upd, paramNo))) { upd->bindNull(paramNo); @@ -67,7 +67,7 @@ namespace Slicer { paramNo++; } }); - mp->OnEachChild([&upd, ¶mNo](const std::string &, const ModelPartPtr & cmp, const HookCommon * h) { + mp->OnEachChild([&upd, ¶mNo](auto &&, auto && cmp, auto && h) { if (isPKey(h)) { cmp->GetValue(SqlBinder(*upd, paramNo++)); } @@ -78,13 +78,13 @@ namespace Slicer { } DB::ModifyCommandPtr - SqlUpdateSerializer::createUpdate(const Slicer::ModelPartPtr & mp) const + SqlUpdateSerializer::createUpdate(ModelPartParam mp) const { using namespace AdHoc::literals; std::stringstream update; "UPDATE %? SET "_fmt(update, tableName); int fieldNo = 0; - mp->OnEachChild([&update, &fieldNo](const std::string & name, const ModelPartPtr &, const HookCommon * h) { + mp->OnEachChild([&update, &fieldNo](auto && name, auto &&, auto && h) { if (isValue(h)) { if (fieldNo++) { update << ", "; @@ -94,7 +94,7 @@ namespace Slicer { }); update << " WHERE "; fieldNo = 0; - mp->OnEachChild([&update, &fieldNo](const std::string & name, const ModelPartPtr &, const HookCommon * h) { + mp->OnEachChild([&update, &fieldNo](auto && name, auto &&, auto && h) { if (isPKey(h)) { if (fieldNo++) { update << " AND "; diff --git a/slicer/db/sqlUpdateSerializer.h b/slicer/db/sqlUpdateSerializer.h index 54a5f82..07ee5bb 100644 --- a/slicer/db/sqlUpdateSerializer.h +++ b/slicer/db/sqlUpdateSerializer.h @@ -20,10 +20,10 @@ namespace Slicer { void Serialize(Slicer::ModelPartForRootPtr) override; protected: - void SerializeObject(const Slicer::ModelPartPtr &) const; - void SerializeSequence(const Slicer::ModelPartPtr &) const; - DB::ModifyCommandPtr createUpdate(const Slicer::ModelPartPtr &) const; - static void bindObjectAndExecute(const Slicer::ModelPartPtr &, DB::ModifyCommand *); + void SerializeObject(ModelPartParam) const; + void SerializeSequence(ModelPartParam) const; + [[nodiscard]] DB::ModifyCommandPtr createUpdate(ModelPartParam) const; + static void bindObjectAndExecute(ModelPartParam, DB::ModifyCommand *); DB::Connection * const connection; const std::string tableName; diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp index d20efeb..4c37d71 100644 --- a/slicer/json/serializer.cpp +++ b/slicer/json/serializer.cpp @@ -221,7 +221,7 @@ namespace Slicer { }; void - JsonSerializer::ModelTreeIterateSeq(json::Value * n, const ModelPartPtr & mp) + JsonSerializer::ModelTreeIterateSeq(json::Value * n, ModelPartParam mp) { if (!mp->HasValue()) { return; @@ -232,7 +232,7 @@ namespace Slicer { } void - JsonSerializer::ModelTreeIterateDictObj(json::Value * n, const ModelPartPtr & mp) + JsonSerializer::ModelTreeIterateDictObj(json::Value * n, ModelPartParam mp) { if (!mp->HasValue()) { return; @@ -249,7 +249,7 @@ namespace Slicer { } void - JsonSerializer::ModelTreeIterate(json::Value * n, const std::string & name, const ModelPartPtr & mp) + JsonSerializer::ModelTreeIterate(json::Value * n, const std::string & name, ModelPartParam mp) { if (name.empty() || !n || !mp) { return; @@ -314,7 +314,7 @@ namespace Slicer { } void - JsonSerializer::ModelTreeIterateRoot(json::Value * n, const ModelPartPtr & mp) + JsonSerializer::ModelTreeIterateRoot(json::Value * n, ModelPartParam mp) { if (mp) { switch (mp->GetType()) { diff --git a/slicer/json/serializer.h b/slicer/json/serializer.h index 3d92053..230f1c9 100644 --- a/slicer/json/serializer.h +++ b/slicer/json/serializer.h @@ -13,10 +13,10 @@ namespace Slicer { class JsonSerializer : public Serializer { protected: - static void ModelTreeIterate(json::Value *, const std::string &, const ModelPartPtr & mp); - static void ModelTreeIterateDictObj(json::Value *, const ModelPartPtr & mp); - static void ModelTreeIterateSeq(json::Value *, const ModelPartPtr & mp); - static void ModelTreeIterateRoot(json::Value *, const ModelPartPtr & mp); + static void ModelTreeIterate(json::Value *, const std::string &, ModelPartParam mp); + static void ModelTreeIterateDictObj(json::Value *, ModelPartParam mp); + static void ModelTreeIterateSeq(json::Value *, ModelPartParam mp); + static void ModelTreeIterateRoot(json::Value *, ModelPartParam mp); }; class DLL_PUBLIC JsonValueSerializer : public JsonSerializer { diff --git a/slicer/slicer/any_ptr.h b/slicer/slicer/any_ptr.h new file mode 100644 index 0000000..34f8529 --- /dev/null +++ b/slicer/slicer/any_ptr.h @@ -0,0 +1,52 @@ +#pragma once + +#include +#include + +namespace Slicer { + template struct any_ptr { + // cppcheck-suppress noExplicitConstructor + // NOLINTNEXTLINE(hicpp-explicit-conversions) + inline constexpr any_ptr(T * p) noexcept : ptr {p} { } + + template + requires requires(S p) { p.get(); } + // cppcheck-suppress noExplicitConstructor + // NOLINTNEXTLINE(hicpp-explicit-conversions) + inline constexpr any_ptr(const S & p) noexcept : ptr {p.get()} + { + } + + inline constexpr auto + get() const noexcept + { + return ptr; + } + + inline constexpr auto + operator->() const noexcept + { + return ptr; + } + + inline constexpr auto & + operator*() const noexcept + { + return *ptr; + } + + inline constexpr explicit operator bool() const noexcept + { + return ptr; + } + + inline constexpr bool + operator!() const noexcept + { + return !ptr; + } + + private: + T * ptr; + }; +} diff --git a/slicer/slicer/modelParts.cpp b/slicer/slicer/modelParts.cpp index 7a31b05..e46d3f7 100644 --- a/slicer/slicer/modelParts.cpp +++ b/slicer/slicer/modelParts.cpp @@ -79,7 +79,7 @@ namespace Slicer { } void - HookCommon::apply(const ChildHandler & ch, const ModelPartPtr & modelPart) const + HookCommon::apply(const ChildHandler & ch, const ModelPartParam & modelPart) const { ch(*this->nameStr, modelPart, this); } diff --git a/slicer/slicer/modelParts.h b/slicer/slicer/modelParts.h index d0a1f06..f2e26e1 100644 --- a/slicer/slicer/modelParts.h +++ b/slicer/slicer/modelParts.h @@ -1,6 +1,7 @@ #ifndef SLICER_MODELPARTS_H #define SLICER_MODELPARTS_H +#include "any_ptr.h" #include "metadata.h" #include #include @@ -79,8 +80,9 @@ namespace Slicer { using ModelPartPtr = std::shared_ptr; using ModelPartForRootPtr = std::shared_ptr; + using ModelPartParam = any_ptr; using TypeId = std::optional; - using ChildHandler = std::function; + using ChildHandler = std::function; using ClassRef = std::function; using HookFilter = std::function; using Metadata = MetaData<>; @@ -126,7 +128,7 @@ namespace Slicer { SPECIAL_MEMBERS_DEFAULT(HookCommon); [[nodiscard]] bool filter(const HookFilter & flt) const; - void apply(const ChildHandler & ch, const ModelPartPtr & modelPart) const; + void apply(const ChildHandler & ch, const ModelPartParam & modelPart) const; [[nodiscard]] virtual const Metadata & GetMetadata() const = 0; diff --git a/slicer/test/compilation.cpp b/slicer/test/compilation.cpp index 2920e99..6bc6993 100644 --- a/slicer/test/compilation.cpp +++ b/slicer/test/compilation.cpp @@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_class) } static void -hookHandler(std::vector * names, const std::string & name, const Slicer::ModelPartPtr & mpp, +hookHandler(std::vector * names, const std::string & name, Slicer::ModelPartParam mpp, const Slicer::HookCommon * h) { names->push_back(name); diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp index 7494c6e..7053756 100644 --- a/slicer/xml/serializer.cpp +++ b/slicer/xml/serializer.cpp @@ -228,7 +228,7 @@ namespace Slicer { void XmlDeserializer::DocumentTreeIterateDictAttrs( - const xmlpp::Element::const_AttributeList & attrs, const ModelPartPtr & dict) + const xmlpp::Element::const_AttributeList & attrs, ModelPartParam dict) { for (const auto & attr : attrs) { auto emp = dict->GetAnonChild(); @@ -244,7 +244,7 @@ namespace Slicer { } void - XmlDeserializer::DocumentTreeIterateDictElements(const xmlpp::Element * element, const ModelPartPtr & dict) + XmlDeserializer::DocumentTreeIterateDictElements(const xmlpp::Element * element, ModelPartParam dict) { auto node = element->get_first_child(); while (node) { @@ -264,7 +264,7 @@ namespace Slicer { void XmlDeserializer::DocumentTreeIterateElement( - const xmlpp::Element * element, const ModelPartPtr & smp, const ChildRef & smpr) + const xmlpp::Element * element, ModelPartParam smp, const ChildRef & smpr) { auto oec = [&smpr, element](const auto & lmp) { lmp->Create(); @@ -302,7 +302,7 @@ namespace Slicer { } void - XmlDeserializer::DocumentTreeIterate(const xmlpp::Node * node, const ModelPartPtr & mp) + XmlDeserializer::DocumentTreeIterate(const xmlpp::Node * node, ModelPartParam mp) { while (node) { if (auto element = dynamic_cast(node)) { @@ -348,13 +348,13 @@ namespace Slicer { } void - XmlDeserializer::DocumentTreeIterate(const xmlpp::Document * doc, const ModelPartPtr & mp) + XmlDeserializer::DocumentTreeIterate(const xmlpp::Document * doc, ModelPartParam mp) { DocumentTreeIterate(doc->get_root_node(), mp); } void - XmlSerializer::ModelTreeIterate(xmlpp::Element * n, const std::string & name, const ModelPartPtr & mp, + XmlSerializer::ModelTreeIterate(xmlpp::Element * n, const std::string & name, ModelPartParam mp, const HookCommon * hp, const ElementCreator & ec) { if (name.empty()) { @@ -388,7 +388,7 @@ namespace Slicer { } void - XmlSerializer::ModelTreeIterateDictAttrs(xmlpp::Element * element, const ModelPartPtr & dict) + XmlSerializer::ModelTreeIterateDictAttrs(xmlpp::Element * element, ModelPartParam dict) { dict->OnEachChild([element](const auto &, const auto & mp, const auto &) { if (mp->HasValue()) { @@ -400,7 +400,7 @@ namespace Slicer { } void - XmlSerializer::ModelTreeIterateDictElements(xmlpp::Element * element, const ModelPartPtr & dict) + XmlSerializer::ModelTreeIterateDictElements(xmlpp::Element * element, ModelPartParam dict) { dict->OnEachChild([element](const auto &, const auto & mp, const auto &) { if (mp->HasValue()) { @@ -416,7 +416,7 @@ namespace Slicer { void XmlSerializer::ModelTreeProcessElement( - const CurrentElementCreator & cec, const ModelPartPtr & mp, const ElementCreator & ec) + const CurrentElementCreator & cec, ModelPartParam mp, const ElementCreator & ec) { if (mp->GetType() == ModelPartType::Simple) { mp->GetValue(XmlContentValueTarget(cec)); @@ -439,7 +439,7 @@ namespace Slicer { } void - XmlSerializer::ModelTreeIterateRoot(xmlpp::Document * doc, const std::string & name, const ModelPartPtr & mp) + XmlSerializer::ModelTreeIterateRoot(xmlpp::Document * doc, const std::string & name, ModelPartParam mp) { ModelTreeProcessElement(doc->create_root_node(name), mp, defaultElementCreator); } diff --git a/slicer/xml/serializer.h b/slicer/xml/serializer.h index 9b8fa21..4ee818a 100644 --- a/slicer/xml/serializer.h +++ b/slicer/xml/serializer.h @@ -30,15 +30,14 @@ namespace Slicer { class DLL_PUBLIC XmlSerializer : public Serializer { protected: using ElementCreator = std::function; - static void ModelTreeIterate(xmlpp::Element *, const std::string &, const ModelPartPtr & mp, - const HookCommon * hp, const ElementCreator &); - static void ModelTreeIterateRoot(xmlpp::Document *, const std::string &, const ModelPartPtr & mp); + static void ModelTreeIterate(xmlpp::Element *, const std::string &, ModelPartParam mp, const HookCommon * hp, + const ElementCreator &); + static void ModelTreeIterateRoot(xmlpp::Document *, const std::string &, ModelPartParam mp); protected: - static void ModelTreeProcessElement( - const CurrentElementCreator &, const ModelPartPtr & mp, const ElementCreator &); - static void ModelTreeIterateDictAttrs(xmlpp::Element * element, const ModelPartPtr & dict); - static void ModelTreeIterateDictElements(xmlpp::Element * element, const ModelPartPtr & dict); + static void ModelTreeProcessElement(const CurrentElementCreator &, ModelPartParam mp, const ElementCreator &); + static void ModelTreeIterateDictAttrs(xmlpp::Element * element, ModelPartParam dict); + static void ModelTreeIterateDictElements(xmlpp::Element * element, ModelPartParam dict); }; class DLL_PUBLIC XmlDocumentSerializer : public XmlSerializer { @@ -69,13 +68,12 @@ namespace Slicer { class DLL_PUBLIC XmlDeserializer : public Deserializer { protected: - static void DocumentTreeIterate(const xmlpp::Node * node, const ModelPartPtr & mp); - static void DocumentTreeIterateElement( - const xmlpp::Element * element, const ModelPartPtr & mp, const ChildRef & c); - static void DocumentTreeIterate(const xmlpp::Document * doc, const ModelPartPtr & mp); + static void DocumentTreeIterate(const xmlpp::Node * node, ModelPartParam mp); + static void DocumentTreeIterateElement(const xmlpp::Element * element, ModelPartParam mp, const ChildRef & c); + static void DocumentTreeIterate(const xmlpp::Document * doc, ModelPartParam mp); static void DocumentTreeIterateDictAttrs( - const xmlpp::Element::const_AttributeList & attrs, const ModelPartPtr & dict); - static void DocumentTreeIterateDictElements(const xmlpp::Element * parent, const ModelPartPtr & dict); + const xmlpp::Element::const_AttributeList & attrs, ModelPartParam dict); + static void DocumentTreeIterateDictElements(const xmlpp::Element * parent, ModelPartParam dict); }; class DLL_PUBLIC XmlStreamDeserializer : public XmlDeserializer { -- cgit v1.2.3 From 10049bab0f9765a726dd268aacd431d52d35b144 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 6 Aug 2023 11:22:34 +0100 Subject: Replace lots of shared_ptr with unique_ptr or any_ptr --- slicer/db/sqlInsertSerializer.cpp | 2 +- slicer/db/sqlInsertSerializer.h | 2 +- slicer/db/sqlSelectDeserializer.cpp | 2 +- slicer/db/sqlSelectDeserializer.h | 2 +- slicer/db/sqlTablePatchSerializer.cpp | 2 +- slicer/db/sqlTablePatchSerializer.h | 2 +- slicer/db/sqlUpdateSerializer.cpp | 2 +- slicer/db/sqlUpdateSerializer.h | 2 +- slicer/ice/serializer.cpp | 8 ++++---- slicer/ice/serializer.h | 8 ++++---- slicer/json/serializer.cpp | 10 +++++----- slicer/json/serializer.h | 10 +++++----- slicer/slicer/modelParts.h | 3 ++- slicer/slicer/modelPartsTypes.impl.h | 6 +++--- slicer/slicer/serializer.h | 4 ++-- slicer/xml/serializer.cpp | 10 +++++----- slicer/xml/serializer.h | 10 +++++----- 17 files changed, 43 insertions(+), 42 deletions(-) diff --git a/slicer/db/sqlInsertSerializer.cpp b/slicer/db/sqlInsertSerializer.cpp index c120f10..ff30c7c 100644 --- a/slicer/db/sqlInsertSerializer.cpp +++ b/slicer/db/sqlInsertSerializer.cpp @@ -23,7 +23,7 @@ namespace Slicer { } void - SqlInsertSerializer::Serialize(Slicer::ModelPartForRootPtr mp) + SqlInsertSerializer::Serialize(ModelPartForRootParam mp) { switch (mp->GetType()) { case Slicer::ModelPartType::Sequence: diff --git a/slicer/db/sqlInsertSerializer.h b/slicer/db/sqlInsertSerializer.h index 3451455..f9f4fdf 100644 --- a/slicer/db/sqlInsertSerializer.h +++ b/slicer/db/sqlInsertSerializer.h @@ -18,7 +18,7 @@ namespace Slicer { public: SqlInsertSerializer(DB::Connection * const, std::string tableName); - void Serialize(Slicer::ModelPartForRootPtr) override; + void Serialize(ModelPartForRootParam) override; protected: void SerializeObject(ModelPartParam) const; diff --git a/slicer/db/sqlSelectDeserializer.cpp b/slicer/db/sqlSelectDeserializer.cpp index 554703f..526f4b7 100644 --- a/slicer/db/sqlSelectDeserializer.cpp +++ b/slicer/db/sqlSelectDeserializer.cpp @@ -15,7 +15,7 @@ namespace Slicer { } void - SqlSelectDeserializer::Deserialize(Slicer::ModelPartForRootPtr mp) + SqlSelectDeserializer::Deserialize(ModelPartForRootParam mp) { cmd->execute(); columnCount = cmd->columnCount(); diff --git a/slicer/db/sqlSelectDeserializer.h b/slicer/db/sqlSelectDeserializer.h index 32106d7..f8fce08 100644 --- a/slicer/db/sqlSelectDeserializer.h +++ b/slicer/db/sqlSelectDeserializer.h @@ -17,7 +17,7 @@ namespace Slicer { explicit SqlSelectDeserializer( DB::SelectCommand *, std::optional typeIdCol = std::optional()); - void Deserialize(Slicer::ModelPartForRootPtr) override; + void Deserialize(ModelPartForRootParam) override; protected: void DLL_PRIVATE DeserializeSimple(ModelPartParam); diff --git a/slicer/db/sqlTablePatchSerializer.cpp b/slicer/db/sqlTablePatchSerializer.cpp index a22f15a..69acb16 100644 --- a/slicer/db/sqlTablePatchSerializer.cpp +++ b/slicer/db/sqlTablePatchSerializer.cpp @@ -19,7 +19,7 @@ namespace Slicer { } void - SqlTablePatchSerializer::Serialize(Slicer::ModelPartForRootPtr mpr) + SqlTablePatchSerializer::Serialize(ModelPartForRootParam mpr) { tablePatch.pk.clear(); tablePatch.cols.clear(); diff --git a/slicer/db/sqlTablePatchSerializer.h b/slicer/db/sqlTablePatchSerializer.h index 73e084d..1da29a6 100644 --- a/slicer/db/sqlTablePatchSerializer.h +++ b/slicer/db/sqlTablePatchSerializer.h @@ -15,7 +15,7 @@ namespace Slicer { public: SqlTablePatchSerializer(DB::Connection * const, DB::TablePatch &); - void Serialize(Slicer::ModelPartForRootPtr) override; + void Serialize(ModelPartForRootParam) override; private: void createTemporaryTable(); diff --git a/slicer/db/sqlUpdateSerializer.cpp b/slicer/db/sqlUpdateSerializer.cpp index 8a3c3a4..c054764 100644 --- a/slicer/db/sqlUpdateSerializer.cpp +++ b/slicer/db/sqlUpdateSerializer.cpp @@ -21,7 +21,7 @@ namespace Slicer { } void - SqlUpdateSerializer::Serialize(Slicer::ModelPartForRootPtr mp) + SqlUpdateSerializer::Serialize(ModelPartForRootParam mp) { switch (mp->GetType()) { case Slicer::ModelPartType::Sequence: diff --git a/slicer/db/sqlUpdateSerializer.h b/slicer/db/sqlUpdateSerializer.h index 07ee5bb..c634ff5 100644 --- a/slicer/db/sqlUpdateSerializer.h +++ b/slicer/db/sqlUpdateSerializer.h @@ -17,7 +17,7 @@ namespace Slicer { public: SqlUpdateSerializer(DB::Connection * const, std::string tableName); - void Serialize(Slicer::ModelPartForRootPtr) override; + void Serialize(ModelPartForRootParam) override; protected: void SerializeObject(ModelPartParam) const; diff --git a/slicer/ice/serializer.cpp b/slicer/ice/serializer.cpp index eacecf8..eb27729 100644 --- a/slicer/ice/serializer.cpp +++ b/slicer/ice/serializer.cpp @@ -22,7 +22,7 @@ namespace Slicer { } void - IceBlobSerializer::Serialize(ModelPartForRootPtr mp) + IceBlobSerializer::Serialize(ModelPartForRootParam mp) { Ice::OutputStream s(ic); mp->Write(s); @@ -32,7 +32,7 @@ namespace Slicer { IceStreamSerializer::IceStreamSerializer(std::ostream & os) : strm(os) { } void - IceStreamSerializer::Serialize(ModelPartForRootPtr mp) + IceStreamSerializer::Serialize(ModelPartForRootParam mp) { IceBlobSerializer::Serialize(mp); strm.write(reinterpret_cast(blob.data()), static_cast(blob.size())); @@ -41,7 +41,7 @@ namespace Slicer { IceBlobDeserializer::IceBlobDeserializer(const Ice::ByteSeq & b) : refblob(b) { } void - IceBlobDeserializer::Deserialize(ModelPartForRootPtr mp) + IceBlobDeserializer::Deserialize(ModelPartForRootParam mp) { Ice::InputStream s(ic, refblob); mp->Read(s); @@ -50,7 +50,7 @@ namespace Slicer { IceStreamDeserializer::IceStreamDeserializer(std::istream & is) : IceBlobDeserializer(blob), strm(is) { } void - IceStreamDeserializer::Deserialize(ModelPartForRootPtr mp) + IceStreamDeserializer::Deserialize(ModelPartForRootParam mp) { blob.assign(std::istreambuf_iterator(strm), std::istreambuf_iterator()); IceBlobDeserializer::Deserialize(mp); diff --git a/slicer/ice/serializer.h b/slicer/ice/serializer.h index db467cd..0e9919d 100644 --- a/slicer/ice/serializer.h +++ b/slicer/ice/serializer.h @@ -21,7 +21,7 @@ namespace Slicer { class DLL_PUBLIC IceBlobSerializer : public Serializer, protected IceBase { public: - void Serialize(ModelPartForRootPtr) override; + void Serialize(ModelPartForRootParam) override; protected: Ice::ByteSeq blob; @@ -31,7 +31,7 @@ namespace Slicer { public: explicit IceStreamSerializer(std::ostream &); - void Serialize(ModelPartForRootPtr) override; + void Serialize(ModelPartForRootParam) override; protected: std::ostream & strm; @@ -41,7 +41,7 @@ namespace Slicer { public: explicit IceBlobDeserializer(const Ice::ByteSeq &); - void Deserialize(ModelPartForRootPtr) override; + void Deserialize(ModelPartForRootParam) override; protected: const Ice::ByteSeq & refblob; @@ -51,7 +51,7 @@ namespace Slicer { public: explicit IceStreamDeserializer(std::istream &); - void Deserialize(ModelPartForRootPtr) override; + void Deserialize(ModelPartForRootParam) override; protected: std::istream & strm; diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp index 4c37d71..db77607 100644 --- a/slicer/json/serializer.cpp +++ b/slicer/json/serializer.cpp @@ -370,7 +370,7 @@ namespace Slicer { JsonStreamDeserializer::JsonStreamDeserializer(std::istream & s) : strm(s) { } void - JsonStreamDeserializer::Deserialize(ModelPartForRootPtr modelRoot) + JsonStreamDeserializer::Deserialize(ModelPartForRootParam modelRoot) { json::Value obj = json::parseValue(strm); auto mp = modelRoot->GetAnonChild(); @@ -378,7 +378,7 @@ namespace Slicer { } void - JsonStreamSerializer::Serialize(ModelPartForRootPtr modelRoot) + JsonStreamSerializer::Serialize(ModelPartForRootParam modelRoot) { JsonValueSerializer::Serialize(modelRoot); json::serializeValue(value, strm, "utf-8"); @@ -389,7 +389,7 @@ namespace Slicer { JsonFileDeserializer::JsonFileDeserializer(std::filesystem::path p) : path(std::move(p)) { } void - JsonFileDeserializer::Deserialize(ModelPartForRootPtr modelRoot) + JsonFileDeserializer::Deserialize(ModelPartForRootParam modelRoot) { std::ifstream inFile(path); json::Value obj = json::parseValue(inFile); @@ -400,14 +400,14 @@ namespace Slicer { JsonValueDeserializer::JsonValueDeserializer(const json::Value & v) : value(v) { } void - JsonValueDeserializer::Deserialize(ModelPartForRootPtr modelRoot) + JsonValueDeserializer::Deserialize(ModelPartForRootParam modelRoot) { auto mp = modelRoot->GetAnonChild(); std::visit(DocumentTreeIterate(mp), value); } void - JsonValueSerializer::Serialize(ModelPartForRootPtr modelRoot) + JsonValueSerializer::Serialize(ModelPartForRootParam modelRoot) { modelRoot->OnEachChild([this](auto &&, auto && PH2, auto &&) { return JsonSerializer::ModelTreeIterateRoot(&value, PH2); diff --git a/slicer/json/serializer.h b/slicer/json/serializer.h index 230f1c9..1e373d1 100644 --- a/slicer/json/serializer.h +++ b/slicer/json/serializer.h @@ -21,7 +21,7 @@ namespace Slicer { class DLL_PUBLIC JsonValueSerializer : public JsonSerializer { public: - void Serialize(ModelPartForRootPtr) override; + void Serialize(ModelPartForRootParam) override; protected: json::Value value; @@ -31,7 +31,7 @@ namespace Slicer { public: explicit JsonStreamSerializer(std::ostream &); - void Serialize(ModelPartForRootPtr) override; + void Serialize(ModelPartForRootParam) override; protected: std::ostream & strm; @@ -49,7 +49,7 @@ namespace Slicer { public: explicit JsonStreamDeserializer(std::istream &); - void Deserialize(ModelPartForRootPtr) override; + void Deserialize(ModelPartForRootParam) override; protected: std::istream & strm; @@ -59,7 +59,7 @@ namespace Slicer { public: explicit JsonFileDeserializer(std::filesystem::path); - void Deserialize(ModelPartForRootPtr) override; + void Deserialize(ModelPartForRootParam) override; protected: const std::filesystem::path path; @@ -69,7 +69,7 @@ namespace Slicer { public: explicit JsonValueDeserializer(const json::Value &); - void Deserialize(ModelPartForRootPtr) override; + void Deserialize(ModelPartForRootParam) override; protected: const json::Value & value; diff --git a/slicer/slicer/modelParts.h b/slicer/slicer/modelParts.h index f2e26e1..6514c69 100644 --- a/slicer/slicer/modelParts.h +++ b/slicer/slicer/modelParts.h @@ -79,8 +79,9 @@ namespace Slicer { class HookCommon; using ModelPartPtr = std::shared_ptr; - using ModelPartForRootPtr = std::shared_ptr; + using ModelPartForRootPtr = std::unique_ptr; using ModelPartParam = any_ptr; + using ModelPartForRootParam = any_ptr; using TypeId = std::optional; using ChildHandler = std::function; using ClassRef = std::function; diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h index 95d0a37..2d2f7c8 100644 --- a/slicer/slicer/modelPartsTypes.impl.h +++ b/slicer/slicer/modelPartsTypes.impl.h @@ -69,11 +69,11 @@ namespace Ice { } \ template<> DLL_PUBLIC ModelPartForRootPtr ModelPart::CreateRootFor(Type & s) \ { \ - return std::make_shared>(&s); \ + return std::make_unique>(&s); \ } \ template<> DLL_PUBLIC ModelPartForRootPtr ModelPart::CreateRootFor(Ice::optional & s) \ { \ - return std::make_shared>>(&s); \ + return std::make_unique>>(&s); \ } \ template<> DLL_PUBLIC ModelPartForRootPtr ModelPart::CreateRootFor(const Type & s) \ { \ @@ -94,7 +94,7 @@ namespace Ice { DLL_PUBLIC ModelPartForRootPtr \ ModelPart::CreateRootFor(const StreamImpl & stream) \ { \ - return std::make_shared>( \ + return std::make_unique>( \ const_cast(&stream)); \ } \ } diff --git a/slicer/slicer/serializer.h b/slicer/slicer/serializer.h index f26a914..653e61a 100644 --- a/slicer/slicer/serializer.h +++ b/slicer/slicer/serializer.h @@ -19,7 +19,7 @@ namespace Slicer { virtual ~Serializer() = default; - virtual void Serialize(ModelPartForRootPtr) = 0; + virtual void Serialize(ModelPartForRootParam) = 0; }; using SerializerPtr = std::shared_ptr; @@ -31,7 +31,7 @@ namespace Slicer { virtual ~Deserializer() = default; - virtual void Deserialize(ModelPartForRootPtr) = 0; + virtual void Deserialize(ModelPartForRootParam) = 0; }; using DeserializerPtr = std::shared_ptr; diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp index 7053756..f9cb045 100644 --- a/slicer/xml/serializer.cpp +++ b/slicer/xml/serializer.cpp @@ -449,7 +449,7 @@ namespace Slicer { XmlStreamDeserializer::XmlStreamDeserializer(std::istream & s) : strm(s) { } void - XmlStreamDeserializer::Deserialize(ModelPartForRootPtr modelRoot) + XmlStreamDeserializer::Deserialize(ModelPartForRootParam modelRoot) { xmlpp::DomParser dom; dom.parse_stream(strm); @@ -458,7 +458,7 @@ namespace Slicer { } void - XmlStreamSerializer::Serialize(ModelPartForRootPtr modelRoot) + XmlStreamSerializer::Serialize(ModelPartForRootParam modelRoot) { XmlDocumentSerializer::Serialize(modelRoot); doc.write_to_stream(strm); @@ -469,7 +469,7 @@ namespace Slicer { XmlFileDeserializer::XmlFileDeserializer(std::filesystem::path p) : path(std::move(p)) { } void - XmlFileDeserializer::Deserialize(ModelPartForRootPtr modelRoot) + XmlFileDeserializer::Deserialize(ModelPartForRootParam modelRoot) { xmlpp::DomParser dom(path); auto doc = dom.get_document(); @@ -479,13 +479,13 @@ namespace Slicer { XmlDocumentDeserializer::XmlDocumentDeserializer(const xmlpp::Document * d) : doc(d) { } void - XmlDocumentDeserializer::Deserialize(ModelPartForRootPtr modelRoot) + XmlDocumentDeserializer::Deserialize(ModelPartForRootParam modelRoot) { DocumentTreeIterate(doc, modelRoot); } void - XmlDocumentSerializer::Serialize(ModelPartForRootPtr modelRoot) + XmlDocumentSerializer::Serialize(ModelPartForRootParam modelRoot) { modelRoot->OnEachChild([this](auto && PH1, auto && PH2, auto &&) { return XmlSerializer::ModelTreeIterateRoot(&doc, PH1, PH2); diff --git a/slicer/xml/serializer.h b/slicer/xml/serializer.h index 4ee818a..d138ac0 100644 --- a/slicer/xml/serializer.h +++ b/slicer/xml/serializer.h @@ -42,7 +42,7 @@ namespace Slicer { class DLL_PUBLIC XmlDocumentSerializer : public XmlSerializer { public: - void Serialize(ModelPartForRootPtr) override; + void Serialize(ModelPartForRootParam) override; protected: xmlpp::Document doc; @@ -52,7 +52,7 @@ namespace Slicer { public: explicit XmlStreamSerializer(std::ostream &); - void Serialize(ModelPartForRootPtr) override; + void Serialize(ModelPartForRootParam) override; protected: std::ostream & strm; @@ -80,7 +80,7 @@ namespace Slicer { public: explicit XmlStreamDeserializer(std::istream &); - void Deserialize(ModelPartForRootPtr) override; + void Deserialize(ModelPartForRootParam) override; protected: std::istream & strm; @@ -90,7 +90,7 @@ namespace Slicer { public: explicit XmlFileDeserializer(std::filesystem::path); - void Deserialize(ModelPartForRootPtr) override; + void Deserialize(ModelPartForRootParam) override; protected: const std::filesystem::path path; @@ -100,7 +100,7 @@ namespace Slicer { public: explicit XmlDocumentDeserializer(const xmlpp::Document *); - void Deserialize(ModelPartForRootPtr) override; + void Deserialize(ModelPartForRootParam) override; protected: const xmlpp::Document * doc; -- cgit v1.2.3 From 3dfdafccd7d24187ddd4967f99f5d5ef46110211 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 6 Aug 2023 12:09:36 +0100 Subject: any_ptr accepts refs and forward refs --- slicer/slicer/any_ptr.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/slicer/slicer/any_ptr.h b/slicer/slicer/any_ptr.h index 34f8529..14199c0 100644 --- a/slicer/slicer/any_ptr.h +++ b/slicer/slicer/any_ptr.h @@ -9,6 +9,14 @@ namespace Slicer { // NOLINTNEXTLINE(hicpp-explicit-conversions) inline constexpr any_ptr(T * p) noexcept : ptr {p} { } + // cppcheck-suppress noExplicitConstructor + // NOLINTNEXTLINE(hicpp-explicit-conversions) + inline constexpr any_ptr(T & p) noexcept : ptr {&p} { } + + // cppcheck-suppress noExplicitConstructor + // NOLINTNEXTLINE(hicpp-explicit-conversions) + inline constexpr any_ptr(T && p) noexcept : ptr {&p} { } + template requires requires(S p) { p.get(); } // cppcheck-suppress noExplicitConstructor -- cgit v1.2.3 From 520b0bbec3b825667093184909ce96be680e6f0f Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 6 Aug 2023 12:10:43 +0100 Subject: ModelPartForDictionary::OnEachChild creates pair MP on stack --- slicer/slicer/modelPartsTypes.impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h index 2d2f7c8..5f5acf5 100644 --- a/slicer/slicer/modelPartsTypes.impl.h +++ b/slicer/slicer/modelPartsTypes.impl.h @@ -660,7 +660,7 @@ namespace Slicer { { BOOST_ASSERT(this->Model); for (auto & pair : *this->Model) { - ch(pairName, std::make_shared>(&pair), nullptr); + ch(pairName, ModelPartForStruct(&pair), nullptr); } } -- cgit v1.2.3 From 1aa38a090e9de24c8a5ea8e12c6601d66fa6e2d7 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 6 Aug 2023 12:12:00 +0100 Subject: [De]serializeAny[With] uses unique_ptr --- slicer/slicer/slicer.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/slicer/slicer/slicer.h b/slicer/slicer/slicer.h index ce7e037..5450722 100644 --- a/slicer/slicer/slicer.h +++ b/slicer/slicer/slicer.h @@ -8,7 +8,7 @@ namespace Slicer { template Object - DeserializeAnyWith(const DeserializerPtr & deserializer) + DeserializeAnyWith(any_ptr deserializer) { Object object {}; deserializer->Deserialize(ModelPart::CreateRootFor(object)); @@ -19,12 +19,12 @@ namespace Slicer { Object DeserializeAny(SerializerParams &&... sp) { - return DeserializeAnyWith(std::make_shared(std::forward(sp)...)); + return DeserializeAnyWith(std::make_unique(std::forward(sp)...)); } template void - SerializeAnyWith(const Object & object, const SerializerPtr & serializer) + SerializeAnyWith(const Object & object, any_ptr serializer) { serializer->Serialize(ModelPart::CreateRootFor(object)); } @@ -33,7 +33,7 @@ namespace Slicer { void SerializeAny(const Object & object, SerializerParams &&... sp) { - SerializeAnyWith(object, std::make_shared(std::forward(sp)...)); + SerializeAnyWith(object, std::make_unique(std::forward(sp)...)); } } -- cgit v1.2.3 From 4a78d1ee35343f5609186a582e6352f2939acb1f Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 6 Aug 2023 12:28:46 +0100 Subject: Test making deserializers on stack --- slicer/test/serializers.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slicer/test/serializers.cpp b/slicer/test/serializers.cpp index 379551b..5e643a9 100644 --- a/slicer/test/serializers.cpp +++ b/slicer/test/serializers.cpp @@ -589,11 +589,11 @@ BOOST_AUTO_TEST_CASE(xml_streams) BOOST_AUTO_TEST_CASE(invalid_enum) { - auto jdeserializer = std::make_shared(rootDir / "initial" / "invalidEnum.json"); + Slicer::JsonFileDeserializer jdeserializer {rootDir / "initial" / "invalidEnum.json"}; BOOST_REQUIRE_THROW( Slicer::DeserializeAnyWith(jdeserializer), Slicer::InvalidEnumerationSymbol); - auto xdeserializer = std::make_shared(rootDir / "initial" / "invalidEnum.xml"); + Slicer::XmlFileDeserializer xdeserializer {rootDir / "initial" / "invalidEnum.xml"}; BOOST_REQUIRE_THROW( Slicer::DeserializeAnyWith(xdeserializer), Slicer::InvalidEnumerationSymbol); } -- cgit v1.2.3 From 6f93598311a76fec29df4897a7497458bcb70a65 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 6 Aug 2023 14:26:43 +0100 Subject: Add missing special members to IceBase --- slicer/ice/serializer.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/slicer/ice/serializer.h b/slicer/ice/serializer.h index 0e9919d..4a10508 100644 --- a/slicer/ice/serializer.h +++ b/slicer/ice/serializer.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -13,6 +14,8 @@ namespace Slicer { public: virtual ~IceBase(); + SPECIAL_MEMBERS_DELETE(IceBase); + protected: IceBase(); -- cgit v1.2.3 From 313f5ebd1e5116b84b57f7399326137176d10ace Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 6 Aug 2023 14:27:18 +0100 Subject: Add missing DLL_PUBLIC to IceBase destructor --- slicer/ice/serializer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slicer/ice/serializer.h b/slicer/ice/serializer.h index 4a10508..8e8ff03 100644 --- a/slicer/ice/serializer.h +++ b/slicer/ice/serializer.h @@ -10,7 +10,7 @@ #include namespace Slicer { - class IceBase { + class DLL_PUBLIC IceBase { public: virtual ~IceBase(); -- cgit v1.2.3 From f1ea89056938253289751c422c2b82977ee44aa3 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 6 Aug 2023 14:39:05 +0100 Subject: Make [de]serializers on stack --- slicer/slicer/slicer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slicer/slicer/slicer.h b/slicer/slicer/slicer.h index 5450722..66e4537 100644 --- a/slicer/slicer/slicer.h +++ b/slicer/slicer/slicer.h @@ -19,7 +19,7 @@ namespace Slicer { Object DeserializeAny(SerializerParams &&... sp) { - return DeserializeAnyWith(std::make_unique(std::forward(sp)...)); + return DeserializeAnyWith(Deserializer(std::forward(sp)...)); } template @@ -33,7 +33,7 @@ namespace Slicer { void SerializeAny(const Object & object, SerializerParams &&... sp) { - SerializeAnyWith(object, std::make_unique(std::forward(sp)...)); + SerializeAnyWith(object, Serializer(std::forward(sp)...)); } } -- cgit v1.2.3 From 1adc252d8b7cdff8a6707f40ba6a68d0afee11cd Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 6 Aug 2023 17:04:46 +0100 Subject: Modernize set up of class name/ref maps --- slicer/slicer/modelPartsTypes.cpp | 66 ++++++++++++++------------------------- 1 file changed, 23 insertions(+), 43 deletions(-) diff --git a/slicer/slicer/modelPartsTypes.cpp b/slicer/slicer/modelPartsTypes.cpp index cd22c05..bd130bf 100644 --- a/slicer/slicer/modelPartsTypes.cpp +++ b/slicer/slicer/modelPartsTypes.cpp @@ -38,45 +38,26 @@ namespace Slicer { boost::multi_index::member, std::less<>>>>; - static void createClassMaps() __attribute__((constructor(208))); - static void deleteClassMaps() __attribute__((destructor(208))); - static ClassNameMap * names; - static ClassRefMap * refs; + namespace { + constinit std::unique_ptr names; + constinit std::unique_ptr refs; - void - createClassMaps() - { - names = new ClassNameMap(); - refs = new ClassRefMap(); - } + void createClassMaps() __attribute__((constructor(208))); - static void - deleteClassMaps() - { - delete names; - delete refs; - names = nullptr; - refs = nullptr; - } - - ClassNameMap * - classNameMap() - { - return names; - } - - ClassRefMap * - classRefMap() - { - return refs; + void + createClassMaps() + { + names = std::make_unique(); + refs = std::make_unique(); + } } const std::string & ModelPartForComplexBase::ToModelTypeName(const std::string & name) { - auto & right = classNameMap()->get<1>(); - auto mapped = right.find(name); - if (mapped != right.end()) { + const auto & right = names->get<1>(); + + if (const auto mapped = right.find(name); mapped != right.end()) { return mapped->first; } return name; @@ -85,9 +66,9 @@ namespace Slicer { const std::string & ModelPartForComplexBase::ToExchangeTypeName(const std::string & name) { - auto & left = classNameMap()->get<0>(); - auto mapped = left.find(name); - if (mapped != left.end()) { + const auto & left = names->get<0>(); + + if (const auto mapped = left.find(name); mapped != left.end()) { return mapped->second; } return name; @@ -249,29 +230,28 @@ namespace Slicer { ModelPartForComplexBase::registerClass( const std::string & className, const std::string * typeName, const ClassRef & cr) { - Slicer::classRefMap()->insert({className, cr}); + refs->emplace(className, cr); if (typeName) { - Slicer::classNameMap()->insert({className, *typeName}); + names->emplace(className, *typeName); } } void ModelPartForComplexBase::unregisterClass(const std::string & className, const std::string * typeName) { - Slicer::classRefMap()->erase(className); + refs->erase(className); if (typeName) { - classNameMap()->get<0>().erase(className); + names->get<0>().erase(className); } } ModelPartPtr ModelPartForComplexBase::getSubclassModelPart(const std::string & name, void * m) { - auto ref = classRefMap()->find(ToModelTypeName(name)); - if (ref == classRefMap()->end()) { - throw UnknownType(name); + if (const auto ref = refs->find(ToModelTypeName(name)); ref != refs->end()) { + return ref->second(m); } - return ref->second(m); + throw UnknownType(name); } TypeId -- cgit v1.2.3 From 841503f320d4cd3d3f139af1ba0caf3c5fa8af99 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 6 Aug 2023 18:17:23 +0100 Subject: Single call point for DocumentTreeIterate::visit --- slicer/json/serializer.cpp | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp index db77607..449e0b4 100644 --- a/slicer/json/serializer.cpp +++ b/slicer/json/serializer.cpp @@ -149,7 +149,11 @@ namespace Slicer { class DocumentTreeIterate { public: - explicit DocumentTreeIterate(ModelPartPtr & mp) : modelPart(mp) { } + static void + visit(ModelPartPtr && mp, const json::Value & v) + { + std::visit(DocumentTreeIterate {std::move(mp)}, v); + } template void @@ -181,19 +185,17 @@ namespace Slicer { auto emp = modelPart->GetAnonChild(); emp->Create(); auto key = emp->GetChild(keyName); - auto value = emp->GetChild(valueName); key->Create(); key->SetValue(JsonValueSource(element.first)); key->Complete(); - std::visit(DocumentTreeIterate(value), element.second); + visit(emp->GetChild(valueName), element.second); emp->Complete(); } } else { for (const auto & element : o) { - auto emp = modelPart->GetChild(element.first); - if (emp) { - std::visit(DocumentTreeIterate(emp), element.second); + if (auto emp = modelPart->GetChild(element.first)) { + visit(std::move(emp), element.second); emp->Complete(); } } @@ -206,18 +208,16 @@ namespace Slicer { { modelPart->Create(); for (const auto & element : a) { - auto emp = modelPart->GetAnonChild(); - if (emp) { + if (auto emp = modelPart->GetAnonChild()) { emp->Create(); - std::visit(DocumentTreeIterate(emp), element); + visit(std::move(emp), element); emp->Complete(); } } modelPart->Complete(); } - private: - ModelPartPtr & modelPart; + ModelPartPtr && modelPart; }; void @@ -372,9 +372,7 @@ namespace Slicer { void JsonStreamDeserializer::Deserialize(ModelPartForRootParam modelRoot) { - json::Value obj = json::parseValue(strm); - auto mp = modelRoot->GetAnonChild(); - std::visit(DocumentTreeIterate(mp), obj); + DocumentTreeIterate::visit(modelRoot->GetAnonChild(), json::parseValue(strm)); } void @@ -392,9 +390,7 @@ namespace Slicer { JsonFileDeserializer::Deserialize(ModelPartForRootParam modelRoot) { std::ifstream inFile(path); - json::Value obj = json::parseValue(inFile); - auto mp = modelRoot->GetAnonChild(); - std::visit(DocumentTreeIterate(mp), obj); + DocumentTreeIterate::visit(modelRoot->GetAnonChild(), json::parseValue(inFile)); } JsonValueDeserializer::JsonValueDeserializer(const json::Value & v) : value(v) { } @@ -402,8 +398,7 @@ namespace Slicer { void JsonValueDeserializer::Deserialize(ModelPartForRootParam modelRoot) { - auto mp = modelRoot->GetAnonChild(); - std::visit(DocumentTreeIterate(mp), value); + DocumentTreeIterate::visit(modelRoot->GetAnonChild(), value); } void -- cgit v1.2.3 From bb2515df72feacf84ff65ed752dedf1c5fb266cd Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 6 Aug 2023 18:19:48 +0100 Subject: Prefer [moving] emplace over insert --- slicer/json/serializer.cpp | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp index 449e0b4..ce1b6e0 100644 --- a/slicer/json/serializer.cpp +++ b/slicer/json/serializer.cpp @@ -237,15 +237,13 @@ namespace Slicer { if (!mp->HasValue()) { return; } - auto obj = std::get_if(n); json::Object::key_type k; json::Value v; json::Value kv; mp->GetChild(keyName)->GetValue(JsonValueTarget(kv)); - JsonValueSource s(kv); - s.set(k); + JsonValueSource(kv).set(k); ModelTreeIterateRoot(&v, mp->GetChild(valueName)); - obj->insert({k, v}); + std::get_if(n)->emplace(std::move(k), std::move(v)); } void @@ -256,12 +254,11 @@ namespace Slicer { } switch (mp->GetType()) { case ModelPartType::Null: - std::get(*n).insert({name, json::Null()}); + std::get(*n).emplace(name, json::Null()); return; case ModelPartType::Simple: { - json::Value v; - if (mp->GetValue(JsonValueTarget(v))) { - std::get(*n).insert({name, v}); + if (json::Value v; mp->GetValue(JsonValueTarget(v))) { + std::get(*n).emplace(name, std::move(v)); } break; } @@ -285,25 +282,24 @@ namespace Slicer { break; case ModelPartType::Sequence: if (mp->HasValue()) { - mp->OnEachChild( - [capture0 = &std::get(*n).insert({name, json::Array()}).first->second]( - auto &&, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterateSeq(capture0, PH2); - }); + mp->OnEachChild([capture0 = &std::get(*n).emplace(name, json::Array()).first->second]( + auto &&, auto && PH2, auto &&) { + return JsonSerializer::ModelTreeIterateSeq(capture0, PH2); + }); } break; case ModelPartType::Dictionary: if (mp->HasValue()) { if (mp->GetMetadata().flagSet(md_object)) { mp->OnEachChild( - [capture0 = &std::get(*n).insert({name, json::Object()}).first->second]( + [capture0 = &std::get(*n).emplace(name, json::Object()).first->second]( auto &&, auto && PH2, auto &&) { return JsonSerializer::ModelTreeIterateDictObj(capture0, PH2); }); } else { mp->OnEachChild( - [capture0 = &std::get(*n).insert({name, json::Array()}).first->second]( + [capture0 = &std::get(*n).emplace(name, json::Array()).first->second]( auto &&, auto && PH2, auto &&) { return JsonSerializer::ModelTreeIterateSeq(capture0, PH2); }); -- cgit v1.2.3 From 7e4012ce070394de9871d05dec960a97e35b8bfd Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 6 Aug 2023 18:23:15 +0100 Subject: Move private stuff into anon namespace --- slicer/json/serializer.cpp | 320 +++++++++++++++++++++++---------------------- 1 file changed, 161 insertions(+), 159 deletions(-) diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp index ce1b6e0..d9f7db8 100644 --- a/slicer/json/serializer.cpp +++ b/slicer/json/serializer.cpp @@ -26,199 +26,201 @@ NAMEDFACTORY("application/json", Slicer::JsonStreamSerializer, Slicer::StreamSer NAMEDFACTORY("application/json", Slicer::JsonStreamDeserializer, Slicer::StreamDeserializerFactory) namespace Slicer { - constexpr std::string_view md_object {"json:object"}; - constexpr std::string_view keyName {"key"}; - constexpr std::string_view valueName {"value"}; + namespace { + constexpr std::string_view md_object {"json:object"}; + constexpr std::string_view keyName {"key"}; + constexpr std::string_view valueName {"value"}; - using namespace std::placeholders; + using namespace std::placeholders; - class JsonValueSource : public ValueSource { - public: - explicit JsonValueSource(const json::Value & s) : value(s) { } + class JsonValueSource : public ValueSource { + public: + explicit JsonValueSource(const json::Value & s) : value(s) { } - void - set(bool & v) const override - { - v = std::get(value); - } - - void - set(Ice::Byte & v) const override - { - v = boost::numeric_cast(std::get(value)); - } + void + set(bool & v) const override + { + v = std::get(value); + } - void - set(Ice::Short & v) const override - { - v = boost::numeric_cast(std::get(value)); - } + void + set(Ice::Byte & v) const override + { + v = boost::numeric_cast(std::get(value)); + } - void - set(Ice::Int & v) const override - { - v = boost::numeric_cast(std::get(value)); - } + void + set(Ice::Short & v) const override + { + v = boost::numeric_cast(std::get(value)); + } - void - set(Ice::Long & v) const override - { - v = boost::numeric_cast(std::get(value)); - } + void + set(Ice::Int & v) const override + { + v = boost::numeric_cast(std::get(value)); + } - void - set(Ice::Float & v) const override - { - v = boost::numeric_cast(std::get(value)); - } + void + set(Ice::Long & v) const override + { + v = boost::numeric_cast(std::get(value)); + } - void - set(Ice::Double & v) const override - { - v = boost::numeric_cast(std::get(value)); - } + void + set(Ice::Float & v) const override + { + v = boost::numeric_cast(std::get(value)); + } - void - set(std::string & v) const override - { - v = std::get(value); - } + void + set(Ice::Double & v) const override + { + v = boost::numeric_cast(std::get(value)); + } - private: - const json::Value & value; - }; + void + set(std::string & v) const override + { + v = std::get(value); + } - class JsonValueTarget : public ValueTarget { - public: - explicit JsonValueTarget(json::Value & t) : target(t) - { - target = json::Null(); - } + private: + const json::Value & value; + }; - void - get(const bool & value) const override - { - target = value; - } + class JsonValueTarget : public ValueTarget { + public: + explicit JsonValueTarget(json::Value & t) : target(t) + { + target = json::Null(); + } - void - get(const Ice::Byte & value) const override - { - target = boost::numeric_cast(value); - } + void + get(const bool & value) const override + { + target = value; + } - void - get(const Ice::Short & value) const override - { - target = boost::numeric_cast(value); - } + void + get(const Ice::Byte & value) const override + { + target = boost::numeric_cast(value); + } - void - get(const Ice::Int & value) const override - { - target = boost::numeric_cast(value); - } + void + get(const Ice::Short & value) const override + { + target = boost::numeric_cast(value); + } - void - get(const Ice::Long & value) const override - { - target = boost::numeric_cast(value); - } + void + get(const Ice::Int & value) const override + { + target = boost::numeric_cast(value); + } - void - get(const Ice::Float & value) const override - { - target = boost::numeric_cast(value); - } + void + get(const Ice::Long & value) const override + { + target = boost::numeric_cast(value); + } - void - get(const Ice::Double & value) const override - { - target = boost::numeric_cast(value); - } + void + get(const Ice::Float & value) const override + { + target = boost::numeric_cast(value); + } - void - get(const std::string & value) const override - { - target = value; - } + void + get(const Ice::Double & value) const override + { + target = boost::numeric_cast(value); + } - private: - json::Value & target; - }; + void + get(const std::string & value) const override + { + target = value; + } - class DocumentTreeIterate { - public: - static void - visit(ModelPartPtr && mp, const json::Value & v) - { - std::visit(DocumentTreeIterate {std::move(mp)}, v); - } + private: + json::Value & target; + }; - template - void - operator()(const SimpleT & v) const - { - modelPart->Create(); - modelPart->SetValue(JsonValueSource(v)); - modelPart->Complete(); - } + class DocumentTreeIterate { + public: + static void + visit(ModelPartPtr && mp, const json::Value & v) + { + std::visit(DocumentTreeIterate {std::move(mp)}, v); + } - void - operator()(const json::Null &) const - { - modelPart->Complete(); - } + template + void + operator()(const SimpleT & v) const + { + modelPart->Create(); + modelPart->SetValue(JsonValueSource(v)); + modelPart->Complete(); + } - void - operator()(const json::Object & o) const - { - if (auto typeIdName = modelPart->GetTypeIdProperty()) { - auto typeAttrItr = o.find(*typeIdName); - if (typeAttrItr != o.end() && std::holds_alternative(typeAttrItr->second)) { - modelPart = modelPart->GetSubclassModelPart(std::get(typeAttrItr->second)); - } + void + operator()(const json::Null &) const + { + modelPart->Complete(); } - modelPart->Create(); - if (modelPart->GetMetadata().flagSet(md_object)) { - for (const auto & element : o) { - auto emp = modelPart->GetAnonChild(); - emp->Create(); - auto key = emp->GetChild(keyName); - key->Create(); - key->SetValue(JsonValueSource(element.first)); - key->Complete(); - visit(emp->GetChild(valueName), element.second); - emp->Complete(); + + void + operator()(const json::Object & o) const + { + if (auto typeIdName = modelPart->GetTypeIdProperty()) { + auto typeAttrItr = o.find(*typeIdName); + if (typeAttrItr != o.end() && std::holds_alternative(typeAttrItr->second)) { + modelPart = modelPart->GetSubclassModelPart(std::get(typeAttrItr->second)); + } } - } - else { - for (const auto & element : o) { - if (auto emp = modelPart->GetChild(element.first)) { - visit(std::move(emp), element.second); + modelPart->Create(); + if (modelPart->GetMetadata().flagSet(md_object)) { + for (const auto & element : o) { + auto emp = modelPart->GetAnonChild(); + emp->Create(); + auto key = emp->GetChild(keyName); + key->Create(); + key->SetValue(JsonValueSource(element.first)); + key->Complete(); + visit(emp->GetChild(valueName), element.second); emp->Complete(); } } - modelPart->Complete(); + else { + for (const auto & element : o) { + if (auto emp = modelPart->GetChild(element.first)) { + visit(std::move(emp), element.second); + emp->Complete(); + } + } + modelPart->Complete(); + } } - } - void - operator()(const json::Array & a) const - { - modelPart->Create(); - for (const auto & element : a) { - if (auto emp = modelPart->GetAnonChild()) { - emp->Create(); - visit(std::move(emp), element); - emp->Complete(); + void + operator()(const json::Array & a) const + { + modelPart->Create(); + for (const auto & element : a) { + if (auto emp = modelPart->GetAnonChild()) { + emp->Create(); + visit(std::move(emp), element); + emp->Complete(); + } } + modelPart->Complete(); } - modelPart->Complete(); - } - ModelPartPtr && modelPart; - }; + ModelPartPtr && modelPart; + }; + } void JsonSerializer::ModelTreeIterateSeq(json::Value * n, ModelPartParam mp) -- cgit v1.2.3 From 7cb938a227979d66b58685b2199a86e6bff9b046 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 6 Aug 2023 20:25:26 +0100 Subject: Fix implementation of json dictionary serialize in non-object mode --- slicer/json/serializer.cpp | 4 ++-- slicer/test/serializers.cpp | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp index d9f7db8..6470df9 100644 --- a/slicer/json/serializer.cpp +++ b/slicer/json/serializer.cpp @@ -354,8 +354,8 @@ namespace Slicer { } else { *n = json::Array(); - mp->OnEachChild([n](auto && PH1, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterate(n, PH1, PH2); + mp->OnEachChild([&a = n->emplace()](auto &&, auto && PH2, auto &&) { + return JsonSerializer::ModelTreeIterateRoot(&a.emplace_back(), PH2); }); } break; diff --git a/slicer/test/serializers.cpp b/slicer/test/serializers.cpp index 5e643a9..6a41cdd 100644 --- a/slicer/test/serializers.cpp +++ b/slicer/test/serializers.cpp @@ -674,6 +674,18 @@ BOOST_AUTO_TEST_CASE(DeserializeXmlAbstractImpl) BOOST_CHECK_EQUAL("value", impl->testVal); } +BOOST_AUTO_TEST_CASE(SerializeJsonClassMap) +{ + TestModule::ClassMap d; + d[1] = std::make_shared(1, 2); + d[2] = std::make_shared(3, 4); + d[3] = std::make_shared(5, 6); + std::stringstream out; + Slicer::SerializeAnyWith(d, Slicer::JsonStreamSerializer {out}); + BOOST_CHECK_EQUAL(out.view(), + R"([{"key":1,"value":{"a":1,"b":2}},{"key":2,"value":{"a":3,"b":4}},{"key":3,"value":{"a":5,"b":6}}])"); +} + BOOST_AUTO_TEST_CASE(DeserializeXmlIncorrectSeqElementName) { std::stringstream in(R"X( -- cgit v1.2.3 From 92f61bb05fc6645511a2e33ade0cee654afd1bf7 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 7 Aug 2023 17:52:23 +0100 Subject: Type-safe variant emplace based model tree iteration --- slicer/json/serializer.cpp | 89 +++++++++++++++++++++------------------------- slicer/json/serializer.h | 8 ++--- 2 files changed, 44 insertions(+), 53 deletions(-) diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp index 6470df9..59201ca 100644 --- a/slicer/json/serializer.cpp +++ b/slicer/json/serializer.cpp @@ -223,55 +223,52 @@ namespace Slicer { } void - JsonSerializer::ModelTreeIterateSeq(json::Value * n, ModelPartParam mp) + JsonSerializer::ModelTreeIterateSeq(json::Array & a, ModelPartParam mp) { if (!mp->HasValue()) { return; } - auto arr = std::get_if(n); - arr->emplace_back(); - ModelTreeIterateRoot(&arr->back(), mp); + + ModelTreeIterateRoot(a.emplace_back(), mp); } void - JsonSerializer::ModelTreeIterateDictObj(json::Value * n, ModelPartParam mp) + JsonSerializer::ModelTreeIterateDictObj(json::Object & d, ModelPartParam mp) { if (!mp->HasValue()) { return; } json::Object::key_type k; - json::Value v; json::Value kv; mp->GetChild(keyName)->GetValue(JsonValueTarget(kv)); JsonValueSource(kv).set(k); - ModelTreeIterateRoot(&v, mp->GetChild(valueName)); - std::get_if(n)->emplace(std::move(k), std::move(v)); + ModelTreeIterateRoot(d[std::move(k)], mp->GetChild(valueName)); } void - JsonSerializer::ModelTreeIterate(json::Value * n, const std::string & name, ModelPartParam mp) + JsonSerializer::ModelTreeIterate(json::Object & o, const std::string & name, ModelPartParam mp) { - if (name.empty() || !n || !mp) { + if (name.empty() || !mp) { return; } switch (mp->GetType()) { case ModelPartType::Null: - std::get(*n).emplace(name, json::Null()); - return; + o[name].emplace(); + break; case ModelPartType::Simple: { if (json::Value v; mp->GetValue(JsonValueTarget(v))) { - std::get(*n).emplace(name, std::move(v)); + o[name] = std::move(v); } break; } case ModelPartType::Complex: if (mp->HasValue()) { - auto oec = [n, &name](const auto & lmp) { - auto & obj = std::get(*n).emplace(name, json::Object {}).first->second; + auto oec = [&o, &name](const auto & lmp) { + auto & obj = o[name].emplace(); lmp->OnEachChild([&obj](auto && PH1, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterate(&obj, PH1, PH2); + return JsonSerializer::ModelTreeIterate(obj, PH1, PH2); }); - return &std::get(obj); + return &obj; }; if (auto typeIdName = mp->GetTypeIdProperty()) { if (auto typeId = mp->GetTypeId()) { @@ -284,27 +281,22 @@ namespace Slicer { break; case ModelPartType::Sequence: if (mp->HasValue()) { - mp->OnEachChild([capture0 = &std::get(*n).emplace(name, json::Array()).first->second]( - auto &&, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterateSeq(capture0, PH2); + mp->OnEachChild([&array = o[name].emplace()](auto &&, auto && PH2, auto &&) { + return JsonSerializer::ModelTreeIterateSeq(array, PH2); }); } break; case ModelPartType::Dictionary: if (mp->HasValue()) { if (mp->GetMetadata().flagSet(md_object)) { - mp->OnEachChild( - [capture0 = &std::get(*n).emplace(name, json::Object()).first->second]( - auto &&, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterateDictObj(capture0, PH2); - }); + mp->OnEachChild([&obj = o[name].emplace()](auto &&, auto && PH2, auto &&) { + return JsonSerializer::ModelTreeIterateDictObj(obj, PH2); + }); } else { - mp->OnEachChild( - [capture0 = &std::get(*n).emplace(name, json::Array()).first->second]( - auto &&, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterateSeq(capture0, PH2); - }); + mp->OnEachChild([&array = o[name].emplace()](auto &&, auto && PH2, auto &&) { + return JsonSerializer::ModelTreeIterateSeq(array, PH2); + }); } } break; @@ -312,23 +304,25 @@ namespace Slicer { } void - JsonSerializer::ModelTreeIterateRoot(json::Value * n, ModelPartParam mp) + JsonSerializer::ModelTreeIterateRoot(json::Value & n, ModelPartParam mp) { if (mp) { switch (mp->GetType()) { case ModelPartType::Null: - *n = json::Null(); - return; + n.emplace(); + break; case ModelPartType::Simple: - mp->GetValue(JsonValueTarget(*n)); + if (json::Value v; mp->GetValue(JsonValueTarget(v))) { + n = std::move(v); + } break; case ModelPartType::Complex: { - auto oec = [n](const auto & lmp) { - *n = json::Object(); - lmp->OnEachChild([n](auto && PH1, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterate(n, PH1, PH2); + auto oec = [&n](const auto & lmp) { + auto & obj = n.emplace(); + lmp->OnEachChild([&obj](auto && PH1, auto && PH2, auto &&) { + return JsonSerializer::ModelTreeIterate(obj, PH1, PH2); }); - return &std::get(*n); + return &obj; }; if (auto typeIdName = mp->GetTypeIdProperty()) { if (auto typeId = mp->GetTypeId()) { @@ -340,22 +334,19 @@ namespace Slicer { break; } case ModelPartType::Sequence: - *n = json::Array(); - mp->OnEachChild([n](auto &&, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterateSeq(n, PH2); + mp->OnEachChild([&arr = n.emplace()](auto &&, auto && PH2, auto &&) { + return JsonSerializer::ModelTreeIterateSeq(arr, PH2); }); break; case ModelPartType::Dictionary: if (mp->GetMetadata().flagSet(md_object)) { - *n = json::Object(); - mp->OnEachChild([n](auto &&, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterateDictObj(n, PH2); + mp->OnEachChild([&obj = n.emplace()](auto &&, auto && PH2, auto &&) { + return JsonSerializer::ModelTreeIterateDictObj(obj, PH2); }); } else { - *n = json::Array(); - mp->OnEachChild([&a = n->emplace()](auto &&, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterateRoot(&a.emplace_back(), PH2); + mp->OnEachChild([&arr = n.emplace()](auto &&, auto && PH2, auto &&) { + return JsonSerializer::ModelTreeIterateSeq(arr, PH2); }); } break; @@ -403,7 +394,7 @@ namespace Slicer { JsonValueSerializer::Serialize(ModelPartForRootParam modelRoot) { modelRoot->OnEachChild([this](auto &&, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterateRoot(&value, PH2); + return JsonSerializer::ModelTreeIterateRoot(value, PH2); }); } } diff --git a/slicer/json/serializer.h b/slicer/json/serializer.h index 1e373d1..447821e 100644 --- a/slicer/json/serializer.h +++ b/slicer/json/serializer.h @@ -13,10 +13,10 @@ namespace Slicer { class JsonSerializer : public Serializer { protected: - static void ModelTreeIterate(json::Value *, const std::string &, ModelPartParam mp); - static void ModelTreeIterateDictObj(json::Value *, ModelPartParam mp); - static void ModelTreeIterateSeq(json::Value *, ModelPartParam mp); - static void ModelTreeIterateRoot(json::Value *, ModelPartParam mp); + static void ModelTreeIterate(json::Object &, const std::string &, ModelPartParam mp); + static void ModelTreeIterateDictObj(json::Object &, ModelPartParam mp); + static void ModelTreeIterateSeq(json::Array &, ModelPartParam mp); + static void ModelTreeIterateRoot(json::Value &, ModelPartParam mp); }; class DLL_PUBLIC JsonValueSerializer : public JsonSerializer { -- cgit v1.2.3 From 18c188ca112773a39f02b3c4637e22a3d5c15af6 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 7 Aug 2023 19:09:21 +0100 Subject: Implement ModelTreeIterate as a wrapper around ModelTreeIterateRoot Adding the HasValue() checks for complex, sequence and dictionary. --- slicer/json/serializer.cpp | 146 ++++++++++++++++++--------------------------- slicer/json/serializer.h | 2 +- 2 files changed, 60 insertions(+), 88 deletions(-) diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp index 59201ca..1019602 100644 --- a/slicer/json/serializer.cpp +++ b/slicer/json/serializer.cpp @@ -229,7 +229,11 @@ namespace Slicer { return; } - ModelTreeIterateRoot(a.emplace_back(), mp); + ModelTreeIterateTo( + [&a]() -> json::Value & { + return a.emplace_back(); + }, + mp); } void @@ -238,118 +242,82 @@ namespace Slicer { if (!mp->HasValue()) { return; } - json::Object::key_type k; - json::Value kv; - mp->GetChild(keyName)->GetValue(JsonValueTarget(kv)); - JsonValueSource(kv).set(k); - ModelTreeIterateRoot(d[std::move(k)], mp->GetChild(valueName)); + ModelTreeIterateTo( + [&d, mp]() -> json::Value & { + json::Object::key_type k; + json::Value kv; + mp->GetChild(keyName)->GetValue(JsonValueTarget(kv)); + JsonValueSource(kv).set(k); + return d[std::move(k)]; + }, + mp->GetChild(valueName)); } void JsonSerializer::ModelTreeIterate(json::Object & o, const std::string & name, ModelPartParam mp) { - if (name.empty() || !mp) { + if (name.empty()) { return; } - switch (mp->GetType()) { - case ModelPartType::Null: - o[name].emplace(); - break; - case ModelPartType::Simple: { - if (json::Value v; mp->GetValue(JsonValueTarget(v))) { - o[name] = std::move(v); - } - break; - } - case ModelPartType::Complex: - if (mp->HasValue()) { - auto oec = [&o, &name](const auto & lmp) { - auto & obj = o[name].emplace(); - lmp->OnEachChild([&obj](auto && PH1, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterate(obj, PH1, PH2); - }); - return &obj; - }; - if (auto typeIdName = mp->GetTypeIdProperty()) { - if (auto typeId = mp->GetTypeId()) { - oec(mp->GetSubclassModelPart(*typeId))->emplace(*typeIdName, *typeId); - return; - } - } - oec(mp); - } - break; - case ModelPartType::Sequence: - if (mp->HasValue()) { - mp->OnEachChild([&array = o[name].emplace()](auto &&, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterateSeq(array, PH2); - }); - } - break; - case ModelPartType::Dictionary: - if (mp->HasValue()) { - if (mp->GetMetadata().flagSet(md_object)) { - mp->OnEachChild([&obj = o[name].emplace()](auto &&, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterateDictObj(obj, PH2); - }); - } - else { - mp->OnEachChild([&array = o[name].emplace()](auto &&, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterateSeq(array, PH2); - }); - } - } - break; - } + ModelTreeIterateTo( + [&o, &name]() -> json::Value & { + return o[name]; + }, + mp); } void - JsonSerializer::ModelTreeIterateRoot(json::Value & n, ModelPartParam mp) + JsonSerializer::ModelTreeIterateTo(const std::function & n, ModelPartParam mp) { if (mp) { switch (mp->GetType()) { case ModelPartType::Null: - n.emplace(); + n().emplace(); break; case ModelPartType::Simple: if (json::Value v; mp->GetValue(JsonValueTarget(v))) { - n = std::move(v); + n() = std::move(v); } break; - case ModelPartType::Complex: { - auto oec = [&n](const auto & lmp) { - auto & obj = n.emplace(); - lmp->OnEachChild([&obj](auto && PH1, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterate(obj, PH1, PH2); - }); - return &obj; - }; - if (auto typeIdName = mp->GetTypeIdProperty()) { - if (auto typeId = mp->GetTypeId()) { - oec(mp->GetSubclassModelPart(*typeId))->emplace(*typeIdName, *typeId); - return; + case ModelPartType::Complex: + if (mp->HasValue()) { + auto oec = [&n](const auto & lmp) { + auto & obj = n().emplace(); + lmp->OnEachChild([&obj](auto && PH1, auto && PH2, auto &&) { + return JsonSerializer::ModelTreeIterate(obj, PH1, PH2); + }); + return &obj; + }; + if (auto typeIdName = mp->GetTypeIdProperty()) { + if (auto typeId = mp->GetTypeId()) { + oec(mp->GetSubclassModelPart(*typeId))->emplace(*typeIdName, *typeId); + return; + } } + oec(mp); } - oec(mp); break; - } case ModelPartType::Sequence: - mp->OnEachChild([&arr = n.emplace()](auto &&, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterateSeq(arr, PH2); - }); - break; - case ModelPartType::Dictionary: - if (mp->GetMetadata().flagSet(md_object)) { - mp->OnEachChild([&obj = n.emplace()](auto &&, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterateDictObj(obj, PH2); - }); - } - else { - mp->OnEachChild([&arr = n.emplace()](auto &&, auto && PH2, auto &&) { + if (mp->HasValue()) { + mp->OnEachChild([&arr = n().emplace()](auto &&, auto && PH2, auto &&) { return JsonSerializer::ModelTreeIterateSeq(arr, PH2); }); } break; + case ModelPartType::Dictionary: + if (mp->HasValue()) { + if (mp->GetMetadata().flagSet(md_object)) { + mp->OnEachChild([&obj = n().emplace()](auto &&, auto && PH2, auto &&) { + return JsonSerializer::ModelTreeIterateDictObj(obj, PH2); + }); + } + else { + mp->OnEachChild([&arr = n().emplace()](auto &&, auto && PH2, auto &&) { + return JsonSerializer::ModelTreeIterateSeq(arr, PH2); + }); + } + } + break; } } } @@ -394,7 +362,11 @@ namespace Slicer { JsonValueSerializer::Serialize(ModelPartForRootParam modelRoot) { modelRoot->OnEachChild([this](auto &&, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterateRoot(value, PH2); + return JsonSerializer::ModelTreeIterateTo( + [this]() -> json::Value & { + return value; + }, + PH2); }); } } diff --git a/slicer/json/serializer.h b/slicer/json/serializer.h index 447821e..923c37b 100644 --- a/slicer/json/serializer.h +++ b/slicer/json/serializer.h @@ -16,7 +16,7 @@ namespace Slicer { static void ModelTreeIterate(json::Object &, const std::string &, ModelPartParam mp); static void ModelTreeIterateDictObj(json::Object &, ModelPartParam mp); static void ModelTreeIterateSeq(json::Array &, ModelPartParam mp); - static void ModelTreeIterateRoot(json::Value &, ModelPartParam mp); + static void ModelTreeIterateTo(const std::function &, ModelPartParam mp); }; class DLL_PUBLIC JsonValueSerializer : public JsonSerializer { -- cgit v1.2.3 From 6de4a2c7a1721490726fd135d66bf4bd9ce29d77 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 7 Aug 2023 19:32:04 +0100 Subject: Move ModelTreeIterate* into the anonymous namespace Removes otherwise pointless base class --- slicer/json/serializer.cpp | 176 +++++++++++++++++++++++---------------------- slicer/json/serializer.h | 10 +-- 2 files changed, 90 insertions(+), 96 deletions(-) diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp index 1019602..9bbd508 100644 --- a/slicer/json/serializer.cpp +++ b/slicer/json/serializer.cpp @@ -220,104 +220,106 @@ namespace Slicer { ModelPartPtr && modelPart; }; - } - void - JsonSerializer::ModelTreeIterateSeq(json::Array & a, ModelPartParam mp) - { - if (!mp->HasValue()) { - return; - } + void ModelTreeIterateTo(const std::function &, ModelPartParam mp); - ModelTreeIterateTo( - [&a]() -> json::Value & { - return a.emplace_back(); - }, - mp); - } + void + ModelTreeIterateSeq(json::Array & a, ModelPartParam mp) + { + if (!mp->HasValue()) { + return; + } - void - JsonSerializer::ModelTreeIterateDictObj(json::Object & d, ModelPartParam mp) - { - if (!mp->HasValue()) { - return; + ModelTreeIterateTo( + [&a]() -> json::Value & { + return a.emplace_back(); + }, + mp); } - ModelTreeIterateTo( - [&d, mp]() -> json::Value & { - json::Object::key_type k; - json::Value kv; - mp->GetChild(keyName)->GetValue(JsonValueTarget(kv)); - JsonValueSource(kv).set(k); - return d[std::move(k)]; - }, - mp->GetChild(valueName)); - } - void - JsonSerializer::ModelTreeIterate(json::Object & o, const std::string & name, ModelPartParam mp) - { - if (name.empty()) { - return; + void + ModelTreeIterateDictObj(json::Object & d, ModelPartParam mp) + { + if (!mp->HasValue()) { + return; + } + ModelTreeIterateTo( + [&d, mp]() -> json::Value & { + json::Object::key_type k; + json::Value kv; + mp->GetChild(keyName)->GetValue(JsonValueTarget(kv)); + JsonValueSource(kv).set(k); + return d[std::move(k)]; + }, + mp->GetChild(valueName)); } - ModelTreeIterateTo( - [&o, &name]() -> json::Value & { - return o[name]; - }, - mp); - } - void - JsonSerializer::ModelTreeIterateTo(const std::function & n, ModelPartParam mp) - { - if (mp) { - switch (mp->GetType()) { - case ModelPartType::Null: - n().emplace(); - break; - case ModelPartType::Simple: - if (json::Value v; mp->GetValue(JsonValueTarget(v))) { - n() = std::move(v); - } - break; - case ModelPartType::Complex: - if (mp->HasValue()) { - auto oec = [&n](const auto & lmp) { - auto & obj = n().emplace(); - lmp->OnEachChild([&obj](auto && PH1, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterate(obj, PH1, PH2); - }); - return &obj; - }; - if (auto typeIdName = mp->GetTypeIdProperty()) { - if (auto typeId = mp->GetTypeId()) { - oec(mp->GetSubclassModelPart(*typeId))->emplace(*typeIdName, *typeId); - return; - } + void + ModelTreeIterate(json::Object & o, const std::string & name, ModelPartParam mp) + { + if (name.empty()) { + return; + } + ModelTreeIterateTo( + [&o, &name]() -> json::Value & { + return o[name]; + }, + mp); + } + + void + ModelTreeIterateTo(const std::function & n, ModelPartParam mp) + { + if (mp) { + switch (mp->GetType()) { + case ModelPartType::Null: + n().emplace(); + break; + case ModelPartType::Simple: + if (json::Value v; mp->GetValue(JsonValueTarget(v))) { + n() = std::move(v); } - oec(mp); - } - break; - case ModelPartType::Sequence: - if (mp->HasValue()) { - mp->OnEachChild([&arr = n().emplace()](auto &&, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterateSeq(arr, PH2); - }); - } - break; - case ModelPartType::Dictionary: - if (mp->HasValue()) { - if (mp->GetMetadata().flagSet(md_object)) { - mp->OnEachChild([&obj = n().emplace()](auto &&, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterateDictObj(obj, PH2); - }); + break; + case ModelPartType::Complex: + if (mp->HasValue()) { + auto oec = [&n](const auto & lmp) { + auto & obj = n().emplace(); + lmp->OnEachChild([&obj](auto && PH1, auto && PH2, auto &&) { + return ModelTreeIterate(obj, PH1, PH2); + }); + return &obj; + }; + if (auto typeIdName = mp->GetTypeIdProperty()) { + if (auto typeId = mp->GetTypeId()) { + oec(mp->GetSubclassModelPart(*typeId))->emplace(*typeIdName, *typeId); + return; + } + } + oec(mp); } - else { + break; + case ModelPartType::Sequence: + if (mp->HasValue()) { mp->OnEachChild([&arr = n().emplace()](auto &&, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterateSeq(arr, PH2); + return ModelTreeIterateSeq(arr, PH2); }); } - } - break; + break; + case ModelPartType::Dictionary: + if (mp->HasValue()) { + if (mp->GetMetadata().flagSet(md_object)) { + mp->OnEachChild([&obj = n().emplace()](auto &&, auto && PH2, auto &&) { + return ModelTreeIterateDictObj(obj, PH2); + }); + } + else { + mp->OnEachChild([&arr = n().emplace()](auto &&, auto && PH2, auto &&) { + return ModelTreeIterateSeq(arr, PH2); + }); + } + } + break; + } } } } @@ -362,7 +364,7 @@ namespace Slicer { JsonValueSerializer::Serialize(ModelPartForRootParam modelRoot) { modelRoot->OnEachChild([this](auto &&, auto && PH2, auto &&) { - return JsonSerializer::ModelTreeIterateTo( + return ModelTreeIterateTo( [this]() -> json::Value & { return value; }, diff --git a/slicer/json/serializer.h b/slicer/json/serializer.h index 923c37b..bba1486 100644 --- a/slicer/json/serializer.h +++ b/slicer/json/serializer.h @@ -11,15 +11,7 @@ #include namespace Slicer { - class JsonSerializer : public Serializer { - protected: - static void ModelTreeIterate(json::Object &, const std::string &, ModelPartParam mp); - static void ModelTreeIterateDictObj(json::Object &, ModelPartParam mp); - static void ModelTreeIterateSeq(json::Array &, ModelPartParam mp); - static void ModelTreeIterateTo(const std::function &, ModelPartParam mp); - }; - - class DLL_PUBLIC JsonValueSerializer : public JsonSerializer { + class DLL_PUBLIC JsonValueSerializer : public Serializer { public: void Serialize(ModelPartForRootParam) override; -- cgit v1.2.3 From ec56144613e47cea2636b7179f3a8b27eacdba50 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Thu, 10 Aug 2023 23:16:36 +0100 Subject: Move private stuff into anon namespace --- slicer/xml/serializer.cpp | 687 +++++++++++++++++++++++----------------------- slicer/xml/serializer.h | 37 +-- 2 files changed, 355 insertions(+), 369 deletions(-) diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp index f9cb045..f508a6f 100644 --- a/slicer/xml/serializer.cpp +++ b/slicer/xml/serializer.cpp @@ -10,16 +10,16 @@ #endif #include #include +#include #include #include #include +#include #pragma GCC diagnostic pop #include #include #include #include -#include -#include #include #include #include @@ -37,411 +37,426 @@ NAMEDFACTORY("application/xml", Slicer::XmlStreamSerializer, Slicer::StreamSeria NAMEDFACTORY("application/xml", Slicer::XmlStreamDeserializer, Slicer::StreamDeserializerFactory) namespace Slicer { - constexpr std::string_view md_attribute {"xml:attribute"}; - constexpr std::string_view md_text {"xml:text"}; - constexpr std::string_view md_bare {"xml:bare"}; - constexpr std::string_view md_attributes {"xml:attributes"}; - constexpr std::string_view md_elements {"xml:elements"}; - constexpr std::string_view keyName {"key"}; - constexpr std::string_view valueName {"value"}; - - constexpr auto defaultElementCreator = [](auto && element, auto && name) { - return element->add_child_element(name); - }; + namespace { + constexpr std::string_view md_attribute {"xml:attribute"}; + constexpr std::string_view md_text {"xml:text"}; + constexpr std::string_view md_bare {"xml:bare"}; + constexpr std::string_view md_attributes {"xml:attributes"}; + constexpr std::string_view md_elements {"xml:elements"}; + constexpr std::string_view keyName {"key"}; + constexpr std::string_view valueName {"value"}; + + using CurrentElementCreator = ::AdHoc::LazyPointer; + using ElementCreator = std::function; + + constexpr auto defaultElementCreator = [](auto && element, auto && name) { + return element->add_child_element(name); + }; - static const Glib::ustring TrueText("true"); - static const Glib::ustring FalseText("false"); + const Glib::ustring TrueText("true"); + const Glib::ustring FalseText("false"); - class XmlValueSource : public ValueSource { - public: - explicit XmlValueSource(Glib::ustring s) : value(std::move(s)) { } + class XmlValueSource : public ValueSource { + public: + explicit XmlValueSource(Glib::ustring s) : value(std::move(s)) { } - void - set(bool & v) const override - { - if (value == TrueText) { - v = true; - return; - } - if (value == FalseText) { - v = false; - return; + void + set(bool & v) const override + { + if (value == TrueText) { + v = true; + return; + } + if (value == FalseText) { + v = false; + return; + } + throw BadBooleanValue(value); } - throw BadBooleanValue(value); - } - void - set(Ice::Byte & v) const override - { - from_chars(v); - } + void + set(Ice::Byte & v) const override + { + from_chars(v); + } - void - set(Ice::Short & v) const override - { - from_chars(v); - } + void + set(Ice::Short & v) const override + { + from_chars(v); + } - void - set(Ice::Int & v) const override - { - from_chars(v); - } + void + set(Ice::Int & v) const override + { + from_chars(v); + } - void - set(Ice::Long & v) const override - { - from_chars(v); - } + void + set(Ice::Long & v) const override + { + from_chars(v); + } - void - set(Ice::Float & v) const override - { - from_chars(v); - } + void + set(Ice::Float & v) const override + { + from_chars(v); + } - void - set(Ice::Double & v) const override - { - from_chars(v); - } + void + set(Ice::Double & v) const override + { + from_chars(v); + } - void - set(std::string & v) const override - { - v = value.raw(); - } + void + set(std::string & v) const override + { + v = value.raw(); + } - private: - template - void - from_chars(T & v) const - { - std::string_view raw {value.raw()}; - if (std::from_chars(raw.begin(), raw.end(), v).ec != std::errc {}) { - throw BadNumericValue(value); + private: + template + void + from_chars(T & v) const + { + std::string_view raw {value.raw()}; + if (std::from_chars(raw.begin(), raw.end(), v).ec != std::errc {}) { + throw BadNumericValue(value); + } } - } - const Glib::ustring value; - }; + const Glib::ustring value; + }; - class XmlContentValueSource : public XmlValueSource { - public: - explicit XmlContentValueSource() : XmlValueSource(Glib::ustring()) { } + class XmlContentValueSource : public XmlValueSource { + public: + explicit XmlContentValueSource() : XmlValueSource(Glib::ustring()) { } - explicit XmlContentValueSource(const xmlpp::ContentNode * c) : XmlValueSource(c->get_content()) { } - }; + explicit XmlContentValueSource(const xmlpp::ContentNode * c) : XmlValueSource(c->get_content()) { } + }; - class XmlAttributeValueSource : public XmlValueSource { - public: - explicit XmlAttributeValueSource(const xmlpp::Attribute * a) : XmlValueSource(a->get_value()) { } - }; + class XmlAttributeValueSource : public XmlValueSource { + public: + explicit XmlAttributeValueSource(const xmlpp::Attribute * a) : XmlValueSource(a->get_value()) { } + }; - class XmlValueTarget : public ValueTarget { - public: - explicit XmlValueTarget(std::function a) : apply(std::move(a)) { } + class XmlValueTarget : public ValueTarget { + public: + explicit XmlValueTarget(std::function a) : apply(std::move(a)) { } - void - get(const bool & value) const override - { - if (value) { - apply(TrueText); + void + get(const bool & value) const override + { + if (value) { + apply(TrueText); + } + else { + apply(FalseText); + } } - else { - apply(FalseText); + + void + get(const Ice::Byte & value) const override + { + apply(Glib::ustring::format(value)); } - } - void - get(const Ice::Byte & value) const override - { - apply(Glib::ustring::format(value)); - } + void + get(const Ice::Short & value) const override + { + apply(Glib::ustring::format(value)); + } - void - get(const Ice::Short & value) const override - { - apply(Glib::ustring::format(value)); - } + void + get(const Ice::Int & value) const override + { + apply(Glib::ustring::format(value)); + } - void - get(const Ice::Int & value) const override - { - apply(Glib::ustring::format(value)); - } + void + get(const Ice::Long & value) const override + { + apply(Glib::ustring::format(value)); + } - void - get(const Ice::Long & value) const override - { - apply(Glib::ustring::format(value)); - } + void + get(const Ice::Float & value) const override + { + apply(Glib::ustring::format(value)); + } - void - get(const Ice::Float & value) const override - { - apply(Glib::ustring::format(value)); - } + void + get(const Ice::Double & value) const override + { + apply(Glib::ustring::format(value)); + } - void - get(const Ice::Double & value) const override - { - apply(Glib::ustring::format(value)); - } + void + get(const std::string & value) const override + { + apply(value); + } - void - get(const std::string & value) const override - { - apply(value); - } + private: + const std::function apply; + }; - private: - const std::function apply; - }; + class XmlAttributeValueTarget : public XmlValueTarget { + public: + explicit XmlAttributeValueTarget(xmlpp::Element * p, const std::string & n) : + XmlValueTarget([p, n](auto && PH1) { + p->set_attribute(n, PH1); + }) + { + } + }; - class XmlAttributeValueTarget : public XmlValueTarget { - public: - explicit XmlAttributeValueTarget(xmlpp::Element * p, const std::string & n) : - XmlValueTarget([p, n](auto && PH1) { - p->set_attribute(n, PH1); - }) - { - } - }; - - class XmlContentValueTarget : public XmlValueTarget { - public: - explicit XmlContentValueTarget(xmlpp::Element * p) : - XmlValueTarget([p](auto && PH1) { - p->set_first_child_text(PH1); - }) - { - } + class XmlContentValueTarget : public XmlValueTarget { + public: + explicit XmlContentValueTarget(xmlpp::Element * p) : + XmlValueTarget([p](auto && PH1) { + p->set_first_child_text(PH1); + }) + { + } - explicit XmlContentValueTarget(const CurrentElementCreator & cec) : - XmlValueTarget([&](auto && PH1) { - cec->set_first_child_text(PH1); - }) - { - } - }; + explicit XmlContentValueTarget(const CurrentElementCreator & cec) : + XmlValueTarget([&](auto && PH1) { + cec->set_first_child_text(PH1); + }) + { + } + }; - void - XmlDeserializer::DocumentTreeIterateDictAttrs( - const xmlpp::Element::const_AttributeList & attrs, ModelPartParam dict) - { - for (const auto & attr : attrs) { - auto emp = dict->GetAnonChild(); - emp->Create(); - auto key = emp->GetChild(keyName); - auto value = emp->GetChild(valueName); - key->SetValue(XmlValueSource(attr->get_name())); - key->Complete(); - value->SetValue(XmlValueSource(attr->get_value())); - value->Complete(); - emp->Complete(); - } - } + void DocumentTreeIterate(const xmlpp::Node * node, ModelPartParam mp); + void DocumentTreeIterateElement(const xmlpp::Element * element, ModelPartParam mp, const ChildRef & c); + void DocumentTreeIterate(const xmlpp::Document * doc, ModelPartParam mp); + void DocumentTreeIterateDictAttrs(const xmlpp::Element::const_AttributeList & attrs, ModelPartParam dict); + void DocumentTreeIterateDictElements(const xmlpp::Element * parent, ModelPartParam dict); - void - XmlDeserializer::DocumentTreeIterateDictElements(const xmlpp::Element * element, ModelPartParam dict) - { - auto node = element->get_first_child(); - while (node) { - if (auto childElement = dynamic_cast(node)) { + void + DocumentTreeIterateDictAttrs(const xmlpp::Element::const_AttributeList & attrs, ModelPartParam dict) + { + for (const auto & attr : attrs) { auto emp = dict->GetAnonChild(); emp->Create(); auto key = emp->GetChild(keyName); - auto value = emp->GetChildRef(valueName); - key->SetValue(XmlValueSource(childElement->get_name())); + auto value = emp->GetChild(valueName); + key->SetValue(XmlValueSource(attr->get_name())); key->Complete(); - DocumentTreeIterateElement(childElement, value.Child(), value); + value->SetValue(XmlValueSource(attr->get_value())); + value->Complete(); emp->Complete(); } - node = node->get_next_sibling(); } - } - void - XmlDeserializer::DocumentTreeIterateElement( - const xmlpp::Element * element, ModelPartParam smp, const ChildRef & smpr) - { - auto oec = [&smpr, element](const auto & lmp) { - lmp->Create(); - if (smpr.ChildMetaData().flagSet(md_attributes)) { - auto attrs(element->get_attributes()); - if (!attrs.empty()) { - DocumentTreeIterateDictAttrs(attrs, lmp); + void + DocumentTreeIterateDictElements(const xmlpp::Element * element, ModelPartParam dict) + { + auto node = element->get_first_child(); + while (node) { + if (auto childElement = dynamic_cast(node)) { + auto emp = dict->GetAnonChild(); + emp->Create(); + auto key = emp->GetChild(keyName); + auto value = emp->GetChildRef(valueName); + key->SetValue(XmlValueSource(childElement->get_name())); + key->Complete(); + DocumentTreeIterateElement(childElement, value.Child(), value); + emp->Complete(); } + node = node->get_next_sibling(); } - else if (smpr.ChildMetaData().flagSet(md_elements)) { - DocumentTreeIterateDictElements(element, lmp); - } - else { - auto attrs(element->get_attributes()); - if (!attrs.empty()) { - DocumentTreeIterate(attrs.front(), lmp); + } + + void + DocumentTreeIterateElement(const xmlpp::Element * element, ModelPartParam smp, const ChildRef & smpr) + { + auto oec = [&smpr, element](const auto & lmp) { + lmp->Create(); + if (smpr.ChildMetaData().flagSet(md_attributes)) { + auto attrs(element->get_attributes()); + if (!attrs.empty()) { + DocumentTreeIterateDictAttrs(attrs, lmp); + } } - auto firstChild = element->get_first_child(); - if (firstChild) { - DocumentTreeIterate(firstChild, lmp); + else if (smpr.ChildMetaData().flagSet(md_elements)) { + DocumentTreeIterateDictElements(element, lmp); } else { - lmp->SetValue(XmlContentValueSource()); + auto attrs(element->get_attributes()); + if (!attrs.empty()) { + DocumentTreeIterate(attrs.front(), lmp); + } + auto firstChild = element->get_first_child(); + if (firstChild) { + DocumentTreeIterate(firstChild, lmp); + } + else { + lmp->SetValue(XmlContentValueSource()); + } + } + lmp->Complete(); + }; + if (auto typeIdPropName = smp->GetTypeIdProperty()) { + if (auto typeAttr = element->get_attribute(*typeIdPropName)) { + oec(smp->GetSubclassModelPart(typeAttr->get_value())); + return; } } - lmp->Complete(); - }; - if (auto typeIdPropName = smp->GetTypeIdProperty()) { - if (auto typeAttr = element->get_attribute(*typeIdPropName)) { - oec(smp->GetSubclassModelPart(typeAttr->get_value())); - return; - } + oec(smp); } - oec(smp); - } - void - XmlDeserializer::DocumentTreeIterate(const xmlpp::Node * node, ModelPartParam mp) - { - while (node) { - if (auto element = dynamic_cast(node)) { - auto smpr = mp->GetChildRef(element->get_name().raw(), [](const auto & h) { - return h->GetMetadata().flagNotSet(md_attribute); - }); - if (smpr) { - auto smp = smpr.Child(); - if (smpr.ChildMetaData().flagSet(md_bare)) { - smp = smp->GetAnonChild(); + void + DocumentTreeIterate(const xmlpp::Node * node, ModelPartParam mp) + { + while (node) { + if (auto element = dynamic_cast(node)) { + auto smpr = mp->GetChildRef(element->get_name().raw(), [](const auto & h) { + return h->GetMetadata().flagNotSet(md_attribute); + }); + if (smpr) { + auto smp = smpr.Child(); + if (smpr.ChildMetaData().flagSet(md_bare)) { + smp = smp->GetAnonChild(); + } + if (smp) { + DocumentTreeIterateElement(element, smp, smpr); + } } + } + else if (auto attribute = dynamic_cast(node)) { + auto smp = mp->GetChild(attribute->get_name().raw(), [](const auto & h) { + return h->GetMetadata().flagSet(md_attribute); + }); if (smp) { - DocumentTreeIterateElement(element, smp, smpr); + smp->Create(); + smp->SetValue(XmlAttributeValueSource(attribute)); + smp->Complete(); } } - } - else if (auto attribute = dynamic_cast(node)) { - auto smp = mp->GetChild(attribute->get_name().raw(), [](const auto & h) { - return h->GetMetadata().flagSet(md_attribute); - }); - if (smp) { - smp->Create(); - smp->SetValue(XmlAttributeValueSource(attribute)); - smp->Complete(); + else if (auto content = dynamic_cast(node)) { + ModelPartPtr smp; + if (!content->is_white_space()) { + smp = mp->GetAnonChild([](const auto & h) { + return h->GetMetadata().flagSet(md_text); + }); + } + if (smp) { + smp->SetValue(XmlContentValueSource(content)); + } + else { + mp->SetValue(XmlContentValueSource(content)); + } } + node = node->get_next_sibling(); + } + } + + void + DocumentTreeIterate(const xmlpp::Document * doc, ModelPartParam mp) + { + DocumentTreeIterate(doc->get_root_node(), mp); + } + + void ModelTreeIterate(xmlpp::Element *, const std::string &, ModelPartParam mp, const HookCommon * hp, + const ElementCreator &); + void ModelTreeIterateRoot(xmlpp::Document *, const std::string &, ModelPartParam mp); + void ModelTreeProcessElement(const CurrentElementCreator &, ModelPartParam mp, const ElementCreator &); + void ModelTreeIterateDictAttrs(xmlpp::Element * element, ModelPartParam dict); + void ModelTreeIterateDictElements(xmlpp::Element * element, ModelPartParam dict); + + void + ModelTreeIterate(xmlpp::Element * n, const std::string & name, ModelPartParam mp, const HookCommon * hp, + const ElementCreator & ec) + { + if (name.empty()) { + return; + } + if (hp && hp->GetMetadata().flagSet(md_attribute)) { + mp->GetValue(XmlAttributeValueTarget(n, name)); + } + else if (hp && hp->GetMetadata().flagSet(md_text)) { + mp->GetValue(XmlContentValueTarget(n)); + } + else if (hp && hp->GetMetadata().flagSet(md_attributes)) { + ModelTreeIterateDictAttrs(n->add_child_element(name), mp); } - else if (auto content = dynamic_cast(node)) { - ModelPartPtr smp; - if (!content->is_white_space()) { - smp = mp->GetAnonChild([](const auto & h) { - return h->GetMetadata().flagSet(md_text); + else if (hp && hp->GetMetadata().flagSet(md_elements)) { + ModelTreeIterateDictElements(n->add_child_element(name), mp); + } + else { + if (hp && hp->GetMetadata().flagSet(md_bare)) { + ModelTreeProcessElement(n, mp, [name](auto && PH1, auto &&) { + return PH1->add_child_element(name); }); } - if (smp) { - smp->SetValue(XmlContentValueSource(content)); - } else { - mp->SetValue(XmlContentValueSource(content)); + CurrentElementCreator cec([ec, n, name] { + return ec(n, name); + }); + ModelTreeProcessElement(cec, mp, defaultElementCreator); } } - node = node->get_next_sibling(); } - } - void - XmlDeserializer::DocumentTreeIterate(const xmlpp::Document * doc, ModelPartParam mp) - { - DocumentTreeIterate(doc->get_root_node(), mp); - } - - void - XmlSerializer::ModelTreeIterate(xmlpp::Element * n, const std::string & name, ModelPartParam mp, - const HookCommon * hp, const ElementCreator & ec) - { - if (name.empty()) { - return; - } - if (hp && hp->GetMetadata().flagSet(md_attribute)) { - mp->GetValue(XmlAttributeValueTarget(n, name)); - } - else if (hp && hp->GetMetadata().flagSet(md_text)) { - mp->GetValue(XmlContentValueTarget(n)); - } - else if (hp && hp->GetMetadata().flagSet(md_attributes)) { - ModelTreeIterateDictAttrs(n->add_child_element(name), mp); - } - else if (hp && hp->GetMetadata().flagSet(md_elements)) { - ModelTreeIterateDictElements(n->add_child_element(name), mp); + void + ModelTreeIterateDictAttrs(xmlpp::Element * element, ModelPartParam dict) + { + dict->OnEachChild([element](const auto &, const auto & mp, const auto &) { + if (mp->HasValue()) { + mp->GetChild(keyName)->GetValue(XmlValueTarget([&mp, element](const auto & name) { + mp->GetChild(valueName)->GetValue(XmlAttributeValueTarget(element, name)); + })); + } + }); } - else { - if (hp && hp->GetMetadata().flagSet(md_bare)) { - ModelTreeProcessElement(n, mp, [name](auto && PH1, auto &&) { - return PH1->add_child_element(name); - }); - } - else { - CurrentElementCreator cec([ec, n, name] { - return ec(n, name); - }); - ModelTreeProcessElement(cec, mp, defaultElementCreator); - } + + void + ModelTreeIterateDictElements(xmlpp::Element * element, ModelPartParam dict) + { + dict->OnEachChild([element](const auto &, const auto & mp, const auto &) { + if (mp->HasValue()) { + mp->GetChild(keyName)->GetValue(XmlValueTarget([&mp, element](const auto & name) { + CurrentElementCreator cec([&element, &name]() { + return element->add_child_element(name); + }); + ModelTreeProcessElement(cec, mp->GetChild(valueName), defaultElementCreator); + })); + } + }); } - } - void - XmlSerializer::ModelTreeIterateDictAttrs(xmlpp::Element * element, ModelPartParam dict) - { - dict->OnEachChild([element](const auto &, const auto & mp, const auto &) { - if (mp->HasValue()) { - mp->GetChild(keyName)->GetValue(XmlValueTarget([&mp, element](const auto & name) { - mp->GetChild(valueName)->GetValue(XmlAttributeValueTarget(element, name)); - })); + void + ModelTreeProcessElement(const CurrentElementCreator & cec, ModelPartParam mp, const ElementCreator & ec) + { + if (mp->GetType() == ModelPartType::Simple) { + mp->GetValue(XmlContentValueTarget(cec)); } - }); - } - - void - XmlSerializer::ModelTreeIterateDictElements(xmlpp::Element * element, ModelPartParam dict) - { - dict->OnEachChild([element](const auto &, const auto & mp, const auto &) { - if (mp->HasValue()) { - mp->GetChild(keyName)->GetValue(XmlValueTarget([&mp, element](const auto & name) { - CurrentElementCreator cec([&element, &name]() { - return element->add_child_element(name); + else if (mp->HasValue()) { + auto oec = [element = cec.get(), &ec](const auto & lmp) { + lmp->OnEachChild([element, &ec](auto && PH1, auto && PH2, auto && PH3) { + return ModelTreeIterate(element, PH1, PH2, PH3, ec); }); - ModelTreeProcessElement(cec, mp->GetChild(valueName), defaultElementCreator); - })); - } - }); - } - - void - XmlSerializer::ModelTreeProcessElement( - const CurrentElementCreator & cec, ModelPartParam mp, const ElementCreator & ec) - { - if (mp->GetType() == ModelPartType::Simple) { - mp->GetValue(XmlContentValueTarget(cec)); - } - else if (mp->HasValue()) { - auto oec = [element = cec.get(), &ec](const auto & lmp) { - lmp->OnEachChild([element, &ec](auto && PH1, auto && PH2, auto && PH3) { - return XmlSerializer::ModelTreeIterate(element, PH1, PH2, PH3, ec); - }); - return element; - }; - if (auto typeIdPropName = mp->GetTypeIdProperty()) { - if (auto typeId = mp->GetTypeId()) { - oec(mp->GetSubclassModelPart(*typeId))->set_attribute(*typeIdPropName, *typeId); - return; + return element; + }; + if (auto typeIdPropName = mp->GetTypeIdProperty()) { + if (auto typeId = mp->GetTypeId()) { + oec(mp->GetSubclassModelPart(*typeId))->set_attribute(*typeIdPropName, *typeId); + return; + } } + oec(mp); } - oec(mp); } - } - void - XmlSerializer::ModelTreeIterateRoot(xmlpp::Document * doc, const std::string & name, ModelPartParam mp) - { - ModelTreeProcessElement(doc->create_root_node(name), mp, defaultElementCreator); + void + ModelTreeIterateRoot(xmlpp::Document * doc, const std::string & name, ModelPartParam mp) + { + ModelTreeProcessElement(doc->create_root_node(name), mp, defaultElementCreator); + } } XmlStreamSerializer::XmlStreamSerializer(std::ostream & s) : strm(s) { } @@ -488,7 +503,7 @@ namespace Slicer { XmlDocumentSerializer::Serialize(ModelPartForRootParam modelRoot) { modelRoot->OnEachChild([this](auto && PH1, auto && PH2, auto &&) { - return XmlSerializer::ModelTreeIterateRoot(&doc, PH1, PH2); + return ModelTreeIterateRoot(&doc, PH1, PH2); }); } diff --git a/slicer/xml/serializer.h b/slicer/xml/serializer.h index d138ac0..9c6e1ae 100644 --- a/slicer/xml/serializer.h +++ b/slicer/xml/serializer.h @@ -1,7 +1,6 @@ #ifndef SLICER_XML_H #define SLICER_XML_H -#include #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wold-style-cast" #pragma GCC diagnostic ignored "-Wsign-conversion" @@ -9,12 +8,9 @@ # pragma GCC diagnostic ignored "-Wuseless-cast" #endif #include -#include #pragma GCC diagnostic pop #include #include -#include -#include #include #include #include @@ -25,22 +21,7 @@ namespace Glib { } namespace Slicer { - using CurrentElementCreator = ::AdHoc::LazyPointer; - - class DLL_PUBLIC XmlSerializer : public Serializer { - protected: - using ElementCreator = std::function; - static void ModelTreeIterate(xmlpp::Element *, const std::string &, ModelPartParam mp, const HookCommon * hp, - const ElementCreator &); - static void ModelTreeIterateRoot(xmlpp::Document *, const std::string &, ModelPartParam mp); - - protected: - static void ModelTreeProcessElement(const CurrentElementCreator &, ModelPartParam mp, const ElementCreator &); - static void ModelTreeIterateDictAttrs(xmlpp::Element * element, ModelPartParam dict); - static void ModelTreeIterateDictElements(xmlpp::Element * element, ModelPartParam dict); - }; - - class DLL_PUBLIC XmlDocumentSerializer : public XmlSerializer { + class DLL_PUBLIC XmlDocumentSerializer : public Serializer { public: void Serialize(ModelPartForRootParam) override; @@ -66,17 +47,7 @@ namespace Slicer { std::ofstream strm; }; - class DLL_PUBLIC XmlDeserializer : public Deserializer { - protected: - static void DocumentTreeIterate(const xmlpp::Node * node, ModelPartParam mp); - static void DocumentTreeIterateElement(const xmlpp::Element * element, ModelPartParam mp, const ChildRef & c); - static void DocumentTreeIterate(const xmlpp::Document * doc, ModelPartParam mp); - static void DocumentTreeIterateDictAttrs( - const xmlpp::Element::const_AttributeList & attrs, ModelPartParam dict); - static void DocumentTreeIterateDictElements(const xmlpp::Element * parent, ModelPartParam dict); - }; - - class DLL_PUBLIC XmlStreamDeserializer : public XmlDeserializer { + class DLL_PUBLIC XmlStreamDeserializer : public Deserializer { public: explicit XmlStreamDeserializer(std::istream &); @@ -86,7 +57,7 @@ namespace Slicer { std::istream & strm; }; - class DLL_PUBLIC XmlFileDeserializer : public XmlDeserializer { + class DLL_PUBLIC XmlFileDeserializer : public Deserializer { public: explicit XmlFileDeserializer(std::filesystem::path); @@ -96,7 +67,7 @@ namespace Slicer { const std::filesystem::path path; }; - class DLL_PUBLIC XmlDocumentDeserializer : public XmlDeserializer { + class DLL_PUBLIC XmlDocumentDeserializer : public Deserializer { public: explicit XmlDocumentDeserializer(const xmlpp::Document *); -- cgit v1.2.3 From 1e6226de5193e640af13327bae2def4787695b40 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Thu, 10 Aug 2023 23:59:58 +0100 Subject: Remove unnecessary ValueTarget wrappers Whole types just to initialize a member differently... bye. --- slicer/xml/serializer.cpp | 84 +++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 47 deletions(-) diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp index f508a6f..cb0b0e4 100644 --- a/slicer/xml/serializer.cpp +++ b/slicer/xml/serializer.cpp @@ -58,8 +58,14 @@ namespace Slicer { class XmlValueSource : public ValueSource { public: + explicit XmlValueSource() = default; + explicit XmlValueSource(Glib::ustring s) : value(std::move(s)) { } + explicit XmlValueSource(const xmlpp::ContentNode * c) : value(c->get_content()) { } + + explicit XmlValueSource(const xmlpp::Attribute * a) : value(a->get_value()) { } + void set(bool & v) const override { @@ -130,21 +136,32 @@ namespace Slicer { const Glib::ustring value; }; - class XmlContentValueSource : public XmlValueSource { + class XmlValueTarget : public ValueTarget { public: - explicit XmlContentValueSource() : XmlValueSource(Glib::ustring()) { } + using ApplyFunction = std::function; - explicit XmlContentValueSource(const xmlpp::ContentNode * c) : XmlValueSource(c->get_content()) { } - }; + explicit XmlValueTarget(ApplyFunction a) : apply(std::move(a)) { } - class XmlAttributeValueSource : public XmlValueSource { - public: - explicit XmlAttributeValueSource(const xmlpp::Attribute * a) : XmlValueSource(a->get_value()) { } - }; + explicit XmlValueTarget(xmlpp::Element * p, const std::string & n) : + apply([p, n](auto && PH1) { + p->set_attribute(n, PH1); + }) + { + } - class XmlValueTarget : public ValueTarget { - public: - explicit XmlValueTarget(std::function a) : apply(std::move(a)) { } + explicit XmlValueTarget(xmlpp::Element * p) : + apply([p](auto && PH1) { + p->set_first_child_text(PH1); + }) + { + } + + explicit XmlValueTarget(const CurrentElementCreator & cec) : + apply([&](auto && PH1) { + cec->set_first_child_text(PH1); + }) + { + } void get(const bool & value) const override @@ -200,34 +217,7 @@ namespace Slicer { } private: - const std::function apply; - }; - - class XmlAttributeValueTarget : public XmlValueTarget { - public: - explicit XmlAttributeValueTarget(xmlpp::Element * p, const std::string & n) : - XmlValueTarget([p, n](auto && PH1) { - p->set_attribute(n, PH1); - }) - { - } - }; - - class XmlContentValueTarget : public XmlValueTarget { - public: - explicit XmlContentValueTarget(xmlpp::Element * p) : - XmlValueTarget([p](auto && PH1) { - p->set_first_child_text(PH1); - }) - { - } - - explicit XmlContentValueTarget(const CurrentElementCreator & cec) : - XmlValueTarget([&](auto && PH1) { - cec->set_first_child_text(PH1); - }) - { - } + const ApplyFunction apply; }; void DocumentTreeIterate(const xmlpp::Node * node, ModelPartParam mp); @@ -295,7 +285,7 @@ namespace Slicer { DocumentTreeIterate(firstChild, lmp); } else { - lmp->SetValue(XmlContentValueSource()); + lmp->SetValue(XmlValueSource()); } } lmp->Complete(); @@ -333,7 +323,7 @@ namespace Slicer { }); if (smp) { smp->Create(); - smp->SetValue(XmlAttributeValueSource(attribute)); + smp->SetValue(XmlValueSource(attribute)); smp->Complete(); } } @@ -345,10 +335,10 @@ namespace Slicer { }); } if (smp) { - smp->SetValue(XmlContentValueSource(content)); + smp->SetValue(XmlValueSource(content)); } else { - mp->SetValue(XmlContentValueSource(content)); + mp->SetValue(XmlValueSource(content)); } } node = node->get_next_sibling(); @@ -376,10 +366,10 @@ namespace Slicer { return; } if (hp && hp->GetMetadata().flagSet(md_attribute)) { - mp->GetValue(XmlAttributeValueTarget(n, name)); + mp->GetValue(XmlValueTarget(n, name)); } else if (hp && hp->GetMetadata().flagSet(md_text)) { - mp->GetValue(XmlContentValueTarget(n)); + mp->GetValue(XmlValueTarget(n)); } else if (hp && hp->GetMetadata().flagSet(md_attributes)) { ModelTreeIterateDictAttrs(n->add_child_element(name), mp); @@ -408,7 +398,7 @@ namespace Slicer { dict->OnEachChild([element](const auto &, const auto & mp, const auto &) { if (mp->HasValue()) { mp->GetChild(keyName)->GetValue(XmlValueTarget([&mp, element](const auto & name) { - mp->GetChild(valueName)->GetValue(XmlAttributeValueTarget(element, name)); + mp->GetChild(valueName)->GetValue(XmlValueTarget(element, name)); })); } }); @@ -433,7 +423,7 @@ namespace Slicer { ModelTreeProcessElement(const CurrentElementCreator & cec, ModelPartParam mp, const ElementCreator & ec) { if (mp->GetType() == ModelPartType::Simple) { - mp->GetValue(XmlContentValueTarget(cec)); + mp->GetValue(XmlValueTarget(cec)); } else if (mp->HasValue()) { auto oec = [element = cec.get(), &ec](const auto & lmp) { -- cgit v1.2.3 From 4a28376403620736ad49f8bc886609154c51498b Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 11 Aug 2023 00:31:25 +0100 Subject: Bit of dedupe in DocumentTreeIterateDictAttrs --- slicer/xml/serializer.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp index cb0b0e4..369394e 100644 --- a/slicer/xml/serializer.cpp +++ b/slicer/xml/serializer.cpp @@ -229,15 +229,17 @@ namespace Slicer { void DocumentTreeIterateDictAttrs(const xmlpp::Element::const_AttributeList & attrs, ModelPartParam dict) { + using AttrMember = Glib::ustring (xmlpp::Attribute::*)() const; for (const auto & attr : attrs) { auto emp = dict->GetAnonChild(); emp->Create(); - auto key = emp->GetChild(keyName); - auto value = emp->GetChild(valueName); - key->SetValue(XmlValueSource(attr->get_name())); - key->Complete(); - value->SetValue(XmlValueSource(attr->get_value())); - value->Complete(); + const auto setChild = [&emp, &attr](const auto & childName, AttrMember attrMember) { + auto child = emp->GetChild(childName); + child->SetValue(XmlValueSource((attr->*attrMember)())); + child->Complete(); + }; + setChild(keyName, &xmlpp::Attribute::get_name); + setChild(valueName, &xmlpp::Attribute::get_value); emp->Complete(); } } -- cgit v1.2.3 From e3f5ba35db040913c15f561c40bbadcf51d0892f Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 11 Aug 2023 00:58:34 +0100 Subject: Fix weird bracing --- slicer/xml/serializer.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp index 369394e..5eab4be 100644 --- a/slicer/xml/serializer.cpp +++ b/slicer/xml/serializer.cpp @@ -379,18 +379,16 @@ namespace Slicer { else if (hp && hp->GetMetadata().flagSet(md_elements)) { ModelTreeIterateDictElements(n->add_child_element(name), mp); } + else if (hp && hp->GetMetadata().flagSet(md_bare)) { + ModelTreeProcessElement(n, mp, [name](auto && PH1, auto &&) { + return PH1->add_child_element(name); + }); + } else { - if (hp && hp->GetMetadata().flagSet(md_bare)) { - ModelTreeProcessElement(n, mp, [name](auto && PH1, auto &&) { - return PH1->add_child_element(name); - }); - } - else { - CurrentElementCreator cec([ec, n, name] { - return ec(n, name); - }); - ModelTreeProcessElement(cec, mp, defaultElementCreator); - } + CurrentElementCreator cec([ec, n, name] { + return ec(n, name); + }); + ModelTreeProcessElement(cec, mp, defaultElementCreator); } } -- cgit v1.2.3 From 8f796ba6400e65143ac49b895e46a7a26de7992b Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 11 Aug 2023 01:40:49 +0100 Subject: Misc tidy up in db module --- slicer/db/sqlBinder.h | 2 -- slicer/db/sqlCommon.cpp | 10 +++++----- slicer/db/sqlCommon.h | 10 +++++----- slicer/db/sqlInsertSerializer.cpp | 2 -- slicer/db/sqlInsertSerializer.h | 10 ++-------- slicer/db/sqlSource.cpp | 33 +++++++++++++++++---------------- slicer/db/sqlSource.h | 4 +--- slicer/db/sqlTablePatchSerializer.cpp | 2 -- 8 files changed, 30 insertions(+), 43 deletions(-) diff --git a/slicer/db/sqlBinder.h b/slicer/db/sqlBinder.h index 71f23ea..a4a9a93 100644 --- a/slicer/db/sqlBinder.h +++ b/slicer/db/sqlBinder.h @@ -34,8 +34,6 @@ namespace Slicer { DB::Command & command; const unsigned int idx; }; - - typedef std::shared_ptr SqlBinderPtr; } #endif diff --git a/slicer/db/sqlCommon.cpp b/slicer/db/sqlCommon.cpp index 21fb9e5..0516f45 100644 --- a/slicer/db/sqlCommon.cpp +++ b/slicer/db/sqlCommon.cpp @@ -11,31 +11,31 @@ namespace Slicer { constexpr std::string_view md_global_ignore {"ignore"}; bool - isPKey(const HookCommon * h) + isPKey(const HookCommon * h) noexcept { return h->GetMetadata().flagSet(md_pkey) && isBind(h); } bool - isAuto(const HookCommon * h) + isAuto(const HookCommon * h) noexcept { return h->GetMetadata().flagSet(md_auto) && isBind(h); } bool - isNotAuto(const HookCommon * h) + isNotAuto(const HookCommon * h) noexcept { return h->GetMetadata().flagNotSet(md_auto) && isBind(h); } bool - isBind(const HookCommon * h) + isBind(const HookCommon * h) noexcept { return h->GetMetadata().flagNotSet(md_global_ignore) && h->GetMetadata().flagNotSet(md_ignore); } bool - isValue(const HookCommon * h) + isValue(const HookCommon * h) noexcept { return h->GetMetadata().flagNotSet(md_auto) && h->GetMetadata().flagNotSet(md_pkey) && isBind(h); } diff --git a/slicer/db/sqlCommon.h b/slicer/db/sqlCommon.h index acabc51..16cefac 100644 --- a/slicer/db/sqlCommon.h +++ b/slicer/db/sqlCommon.h @@ -4,11 +4,11 @@ namespace Slicer { class HookCommon; - bool isPKey(const HookCommon *); - bool isAuto(const HookCommon *); - bool isNotAuto(const HookCommon *); - bool isBind(const HookCommon *); - bool isValue(const HookCommon *); + [[nodiscard]] bool isPKey(const HookCommon *) noexcept; + [[nodiscard]] bool isAuto(const HookCommon *) noexcept; + [[nodiscard]] bool isNotAuto(const HookCommon *) noexcept; + [[nodiscard]] bool isBind(const HookCommon *) noexcept; + [[nodiscard]] bool isValue(const HookCommon *) noexcept; } #endif diff --git a/slicer/db/sqlInsertSerializer.cpp b/slicer/db/sqlInsertSerializer.cpp index ff30c7c..c99df57 100644 --- a/slicer/db/sqlInsertSerializer.cpp +++ b/slicer/db/sqlInsertSerializer.cpp @@ -15,8 +15,6 @@ #include namespace Slicer { - using namespace std::placeholders; - SqlInsertSerializer::SqlInsertSerializer(DB::Connection * const c, std::string t) : connection(c), tableName(std::move(t)) { diff --git a/slicer/db/sqlInsertSerializer.h b/slicer/db/sqlInsertSerializer.h index f9f4fdf..36ecac3 100644 --- a/slicer/db/sqlInsertSerializer.h +++ b/slicer/db/sqlInsertSerializer.h @@ -36,10 +36,7 @@ namespace Slicer { class DLL_PUBLIC SqlAutoIdInsertSerializer : public SqlInsertSerializer { public: - template - explicit SqlAutoIdInsertSerializer(P &&... p) : SqlInsertSerializer(std::forward

(p)...) - { - } + using SqlInsertSerializer::SqlInsertSerializer; protected: void createInsertField(unsigned int & fieldNo, std::ostream & insert, const std::string & name, @@ -50,10 +47,7 @@ namespace Slicer { class DLL_PUBLIC SqlFetchIdInsertSerializer : public SqlAutoIdInsertSerializer { public: - template - explicit SqlFetchIdInsertSerializer(P &&... p) : SqlAutoIdInsertSerializer(std::forward

(p)...) - { - } + using SqlAutoIdInsertSerializer::SqlAutoIdInsertSerializer; protected: void bindObjectAndExecute(ModelPartParam, DB::ModifyCommand *) const override; diff --git a/slicer/db/sqlSource.cpp b/slicer/db/sqlSource.cpp index 41b9c1c..ed14b3a 100644 --- a/slicer/db/sqlSource.cpp +++ b/slicer/db/sqlSource.cpp @@ -7,6 +7,17 @@ namespace Slicer { SqlSource::SqlSource(const DB::Column & c) : column(c) { } + namespace { + template + void + numericSet(const DB::Column & column, T & b) + { + C cb {}; + column >> cb; + b = boost::numeric_cast(cb); + } + } + bool SqlSource::isNull() const { @@ -34,47 +45,37 @@ namespace Slicer { void SqlSource::set(Ice::Byte & b) const { - int64_t cb; - column >> cb; - b = boost::numeric_cast(cb); + numericSet(column, b); } void SqlSource::set(Ice::Short & b) const { - int64_t cb; - column >> cb; - b = boost::numeric_cast(cb); + numericSet(column, b); } void SqlSource::set(Ice::Int & b) const { - int64_t cb; - column >> cb; - b = boost::numeric_cast(cb); + numericSet(column, b); } void SqlSource::set(Ice::Long & b) const { - int64_t cb; - column >> cb; - b = boost::numeric_cast(cb); + numericSet(column, b); } void SqlSource::set(Ice::Float & b) const { - double cb; - column >> cb; - b = boost::numeric_cast(cb); + numericSet(column, b); } void SqlSource::set(Ice::Double & b) const { - column >> b; + numericSet(column, b); } void diff --git a/slicer/db/sqlSource.h b/slicer/db/sqlSource.h index 70a0122..78d9909 100644 --- a/slicer/db/sqlSource.h +++ b/slicer/db/sqlSource.h @@ -23,7 +23,7 @@ namespace Slicer { public: explicit SqlSource(const DB::Column & c); - bool isNull() const; + [[nodiscard]] bool isNull() const; void set(boost::posix_time::ptime & b) const override; void set(boost::posix_time::time_duration & b) const override; void set(bool & b) const override; @@ -38,8 +38,6 @@ namespace Slicer { private: const DB::Column & column; }; - - typedef std::shared_ptr SqlSourcePtr; } #endif diff --git a/slicer/db/sqlTablePatchSerializer.cpp b/slicer/db/sqlTablePatchSerializer.cpp index 69acb16..da5b0b2 100644 --- a/slicer/db/sqlTablePatchSerializer.cpp +++ b/slicer/db/sqlTablePatchSerializer.cpp @@ -37,8 +37,6 @@ namespace Slicer { if (isPKey(h)) { tablePatch.pk.insert(name); } - }); - mp->OnEachChild([this](const auto & name, const auto &, const auto & h) { if (isBind(h)) { tablePatch.cols.insert(name); } -- cgit v1.2.3 From ebfc6845660c082a61f32b60903808910e39251c Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 5 Aug 2023 18:48:59 +0100 Subject: WIP perf tests --- slicer/test/Jamfile.jam | 29 ++++++++++++++++++ slicer/test/perf.cpp | 81 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 slicer/test/perf.cpp diff --git a/slicer/test/Jamfile.jam b/slicer/test/Jamfile.jam index 8fd70a5..6fcffa0 100644 --- a/slicer/test/Jamfile.jam +++ b/slicer/test/Jamfile.jam @@ -3,6 +3,7 @@ import ./slicer.jam ; lib dl ; lib stdc++fs ; lib boost_date_time ; +lib benchmark ; lib icetypes : [ glob *.ice ] @@ -111,3 +112,31 @@ run streams.cpp ../json//slicer-json ; +run + [ obj perf : perf.cpp : + pure + ROOT=\"$(me)\" + types + types + benchmark + stdc++fs + ..//adhocutil + common + ../slicer//slicer + ../slicer//slicer + ../xml//slicer-xml + ../json//slicer-json + ] + : : : + benchmark + stdc++fs + common + types + ../slicer//slicer + ../slicer//slicer + ../xml//slicer-xml + ../json//slicer-json + ..//adhocutil + profile:on + off + : perf ; diff --git a/slicer/test/perf.cpp b/slicer/test/perf.cpp new file mode 100644 index 0000000..0ea775b --- /dev/null +++ b/slicer/test/perf.cpp @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// Must go last +#include + +class CoreFixture : public benchmark::Fixture { +protected: + template + void + runDeserialize(benchmark::State & state, Args &&... args) + { + for (auto _ : state) { + benchmark::DoNotOptimize(Slicer::DeserializeAny(std::forward(args)...)); + } + } +}; + +struct JsonValueFromFile : public json::Value { + explicit JsonValueFromFile(const std::filesystem::path & path) : + json::Value {[&path] { + std::ifstream in {path}; + return json::parseValue(in); + }()} + { + } +}; + +#define DESERIALIZE_TEST(name, type, ds, ext, obj, suf) \ + BENCHMARK_F(CoreFixture, name##_##ext)(benchmark::State & state) \ + { \ + obj dom {rootDir / "initial/" #name "." #ext}; \ + runDeserialize(state, dom suf); \ + } + +#define XML_DESERIALIZE_TEST(name, type) \ + DESERIALIZE_TEST(name, type, Slicer::XmlDocumentDeserializer, xml, xmlpp::DomParser, .get_document()) +XML_DESERIALIZE_TEST(attributemap, TestXml::Maps); +XML_DESERIALIZE_TEST(bare, TestXml::BareContainers); +XML_DESERIALIZE_TEST(someenums, TestModule::SomeEnumsPtr); +XML_DESERIALIZE_TEST(enum, TestModule::SomeNumbers); +XML_DESERIALIZE_TEST(elementmap, TestXml::Maps); +XML_DESERIALIZE_TEST(builtins, TestModule::BuiltInsPtr); +XML_DESERIALIZE_TEST(entityref, TestXml::EntityRef); +XML_DESERIALIZE_TEST(int, int); +XML_DESERIALIZE_TEST(isodate, TestModule::IsoDate); +XML_DESERIALIZE_TEST(seqOfClass, TestModule::Classes); +XML_DESERIALIZE_TEST(simpleArray2, TestModule::SimpleSeq); +XML_DESERIALIZE_TEST(string, std::string); +XML_DESERIALIZE_TEST(struct, TestModule::StructType); +XML_DESERIALIZE_TEST(xmlattr, TestModule::ClassClassPtr); +#undef XML_DESERIALIZE_TEST + +#define JSON_DESERIALIZE_TEST(name, type) \ + DESERIALIZE_TEST(name, type, Slicer::JsonValueDeserializer, json, JsonValueFromFile, ) +JSON_DESERIALIZE_TEST(builtins2, TestModule::BuiltInsPtr); +JSON_DESERIALIZE_TEST(builtins3, TestModule::BuiltInsPtr); +JSON_DESERIALIZE_TEST(localClass, Locals::LocalClassPtr); +JSON_DESERIALIZE_TEST(localSubClass, Locals::LocalSubClassPtr); +JSON_DESERIALIZE_TEST(localSub2Class, Locals::LocalSub2ClassPtr); +JSON_DESERIALIZE_TEST(objectmap, TestJson::Properties); +JSON_DESERIALIZE_TEST(objectmapMember, TestJson::HasProperitiesPtr); +JSON_DESERIALIZE_TEST(optionals2, TestModule::Optionals2Ptr); +JSON_DESERIALIZE_TEST(optionals3, TestModule::Optionals2Ptr); +JSON_DESERIALIZE_TEST(optionals5, TestModule::Optionals2Ptr); +JSON_DESERIALIZE_TEST(seqOfClass2, TestModule::Classes); +JSON_DESERIALIZE_TEST(simpleArray1, TestModule::SimpleSeq); +JSON_DESERIALIZE_TEST(string2, std::string); +JSON_DESERIALIZE_TEST(struct2, TestModule::StructType); +#undef JSON_DESERIALIZE_TEST + +#undef DESERIALIZE_TEST + +BENCHMARK_MAIN(); -- cgit v1.2.3 From c0d2a75e235ce22c2835dd2485e5e15f3602c3cb Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 11 Aug 2023 22:30:08 +0100 Subject: Add perf test over DB SQL select complex --- slicer/db/Jamfile.jam | 35 +++++++++++++++++++++++++++++++++++ slicer/db/testPerf.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 slicer/db/testPerf.cpp diff --git a/slicer/db/Jamfile.jam b/slicer/db/Jamfile.jam index 73c05e5..a304b9e 100644 --- a/slicer/db/Jamfile.jam +++ b/slicer/db/Jamfile.jam @@ -4,6 +4,7 @@ import ../test/slicer.jam ; lib dbppcore : : : : /usr/include/dbpp ; lib dbpp-postgresql : : : : /usr/include/dbpp-postgresql ; lib stdc++fs ; +lib benchmark ; obj sqlExceptions : sqlExceptions.ice : ../slicer//slicer tidy:none ; lib slicer-db : @@ -137,6 +138,40 @@ run testUpdate.cpp testUpdate ; +run + [ obj perf : testPerf.cpp : + pure + ../test//types + ../test//types + benchmark + stdc++fs + dbpp-postgresql + dbppcore + ..//adhocutil + ../test//common + ../slicer//slicer + ../slicer//slicer + testCommon + testCommon + slicer-db + ] + : : : + benchmark + stdc++fs + dbpp-postgresql + dbppcore + ../test//common + ../test//types + ../slicer//slicer + ../slicer//slicer + slicer-db + ..//adhocutil + testCommon + testCommon + profile:on + off + : testPerf ; + alias install : install-lib install-slice ; explicit install ; explicit install-lib ; diff --git a/slicer/db/testPerf.cpp b/slicer/db/testPerf.cpp new file mode 100644 index 0000000..2f98cd2 --- /dev/null +++ b/slicer/db/testPerf.cpp @@ -0,0 +1,24 @@ +#include "sqlSelectDeserializer.h" +#include "testMockCommon.h" +#include +#include +#include +#include +#include + +const StandardMockDatabase db; + +class CoreFixture : public benchmark::Fixture, public ConnectionFixture { }; + +BENCHMARK_F(CoreFixture, bulk_select_complex)(benchmark::State & state) +{ + auto sel = db->select(R"SQL( + SELECT s mint, CAST(s AS NUMERIC(7,1)) mdouble, CAST(s as text) mstring, s % 2 = 0 mbool + FROM GENERATE_SERIES(1, 10000) s)SQL"); + for (auto _ : state) { + benchmark::DoNotOptimize( + Slicer::DeserializeAny(sel.get())); + } +} + +BENCHMARK_MAIN(); -- cgit v1.2.3 From 42d39040eeba1839d2e8ff1cdb09b4a5970cfe69 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 11 Aug 2023 23:40:54 +0100 Subject: Fix to_lower so actually lowers the string --- slicer/slicer/hookMap.cpp | 2 +- slicer/slicer/hookMap.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/slicer/slicer/hookMap.cpp b/slicer/slicer/hookMap.cpp index 6e17a38..3192d6c 100644 --- a/slicer/slicer/hookMap.cpp +++ b/slicer/slicer/hookMap.cpp @@ -3,7 +3,7 @@ namespace Slicer { void - to_lower(std::string s) + to_lower(std::string & s) { boost::algorithm::to_lower(s); } diff --git a/slicer/slicer/hookMap.h b/slicer/slicer/hookMap.h index 5f71e17..fe8e646 100644 --- a/slicer/slicer/hookMap.h +++ b/slicer/slicer/hookMap.h @@ -10,7 +10,7 @@ #include namespace Slicer { - void DLL_PUBLIC to_lower(std::string s); + void DLL_PUBLIC to_lower(std::string & s); template class ModelPartForComplex; // IWYU pragma: keep -- cgit v1.2.3 From 2ead069b2e0bdaa6c11a0d4a3158cc12e01bcd26 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 12 Aug 2023 00:00:30 +0100 Subject: Simply Sequence get anon child with emplace --- slicer/slicer/modelPartsTypes.impl.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h index 5f5acf5..0924de6 100644 --- a/slicer/slicer/modelPartsTypes.impl.h +++ b/slicer/slicer/modelPartsTypes.impl.h @@ -607,8 +607,7 @@ namespace Slicer { ModelPartForSequence::GetAnonChildRef(const HookFilter &) { BOOST_ASSERT(this->Model); - this->Model->push_back(typename element_type::value_type()); - return ChildRef(ModelPart::CreateFor(this->Model->back())); + return ChildRef(ModelPart::CreateFor(this->Model->emplace_back())); } template -- cgit v1.2.3 From 12316c9ca2702ec06cda3ef113521e17a756dcce Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 12 Aug 2023 12:34:14 +0100 Subject: Pass ModelPartParam by value, it's just a pointer --- slicer/slicer/modelParts.cpp | 2 +- slicer/slicer/modelParts.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/slicer/slicer/modelParts.cpp b/slicer/slicer/modelParts.cpp index e46d3f7..1b40773 100644 --- a/slicer/slicer/modelParts.cpp +++ b/slicer/slicer/modelParts.cpp @@ -79,7 +79,7 @@ namespace Slicer { } void - HookCommon::apply(const ChildHandler & ch, const ModelPartParam & modelPart) const + HookCommon::apply(const ChildHandler & ch, ModelPartParam modelPart) const { ch(*this->nameStr, modelPart, this); } diff --git a/slicer/slicer/modelParts.h b/slicer/slicer/modelParts.h index 6514c69..979b9f7 100644 --- a/slicer/slicer/modelParts.h +++ b/slicer/slicer/modelParts.h @@ -83,7 +83,7 @@ namespace Slicer { using ModelPartParam = any_ptr; using ModelPartForRootParam = any_ptr; using TypeId = std::optional; - using ChildHandler = std::function; + using ChildHandler = std::function; using ClassRef = std::function; using HookFilter = std::function; using Metadata = MetaData<>; @@ -129,7 +129,7 @@ namespace Slicer { SPECIAL_MEMBERS_DEFAULT(HookCommon); [[nodiscard]] bool filter(const HookFilter & flt) const; - void apply(const ChildHandler & ch, const ModelPartParam & modelPart) const; + void apply(const ChildHandler & ch, ModelPartParam modelPart) const; [[nodiscard]] virtual const Metadata & GetMetadata() const = 0; -- cgit v1.2.3 From 2d5894b9c5cf442528d52ad1845752731ff276f8 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 12 Aug 2023 15:14:26 +0100 Subject: Hook range iter constructor which doesn't call moveMatch for end --- slicer/slicer/hookMap.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/slicer/slicer/hookMap.h b/slicer/slicer/hookMap.h index fe8e646..daef5b0 100644 --- a/slicer/slicer/hookMap.h +++ b/slicer/slicer/hookMap.h @@ -28,6 +28,8 @@ namespace Slicer { using pointer = HookPtr *; using reference = HookPtr &; + [[nodiscard]] constexpr inline explicit iter(const eq * const r) : range(r), cur(r->e) { } + [[nodiscard]] constexpr inline iter(const eq * const r, const HookPtr * c) : range(r), cur(c) { moveMatch(); @@ -93,13 +95,13 @@ namespace Slicer { [[nodiscard]] constexpr inline iter begin() const { - return {this, b}; + return iter {this, b}; } [[nodiscard]] constexpr inline iter end() const { - return {this, e}; + return iter {this}; } std::string_view key {}; -- cgit v1.2.3 From ecebc3ac7c34adc1f40dc3532e6d5998bc05bf88 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 14 Aug 2023 23:31:46 +0100 Subject: Don't support operations that don't make sense GetSubclassModelPart and GetContainedModelPart throw if called on ModelParts which don't support them. This should remove the need for shared_from_this. --- slicer/slicer/modelParts.cpp | 4 ++-- slicer/test/compilation.cpp | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/slicer/slicer/modelParts.cpp b/slicer/slicer/modelParts.cpp index 1b40773..abe94d8 100644 --- a/slicer/slicer/modelParts.cpp +++ b/slicer/slicer/modelParts.cpp @@ -14,7 +14,7 @@ namespace Slicer { ModelPartPtr ModelPart::GetSubclassModelPart(const std::string &) { - return shared_from_this(); + throw std::logic_error {"GetSubclassModelPart not supported on this ModelPart"}; } TypeId @@ -69,7 +69,7 @@ namespace Slicer { ModelPartPtr ModelPart::GetContainedModelPart() { - return shared_from_this(); + throw std::logic_error {"GetContainedModelPart not supported on this ModelPart"}; } bool diff --git a/slicer/test/compilation.cpp b/slicer/test/compilation.cpp index 6bc6993..fbbbb5f 100644 --- a/slicer/test/compilation.cpp +++ b/slicer/test/compilation.cpp @@ -44,7 +44,7 @@ BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_class) { TypeTest(TestModule::BuiltInsPtr, std::make_shared(), ModelPartForClass, ModelPartType::Complex); - BOOST_REQUIRE_EQUAL(mpp.get(), mpp->GetContainedModelPart().get()); + BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); } static void @@ -53,7 +53,7 @@ hookHandler(std::vector * names, const std::string & name, Slicer:: { names->push_back(name); BOOST_REQUIRE(mpp); - BOOST_REQUIRE(mpp->GetContainedModelPart()); + BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); BOOST_REQUIRE(h); BOOST_REQUIRE_EQUAL(h->name, name); } @@ -104,61 +104,61 @@ BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_mapstructs) BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_string) { StackTypeTest(std::string, ModelPartForSimple, ModelPartType::Simple); - BOOST_REQUIRE_EQUAL(mpp.get(), mpp->GetContainedModelPart().get()); + BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_bool) { StackTypeTest(bool, ModelPartForSimple, ModelPartType::Simple); - BOOST_REQUIRE_EQUAL(mpp.get(), mpp->GetContainedModelPart().get()); + BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_float) { StackTypeTest(Ice::Float, ModelPartForSimple, ModelPartType::Simple); - BOOST_REQUIRE_EQUAL(mpp.get(), mpp->GetContainedModelPart().get()); + BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_double) { StackTypeTest(Ice::Double, ModelPartForSimple, ModelPartType::Simple); - BOOST_REQUIRE_EQUAL(mpp.get(), mpp->GetContainedModelPart().get()); + BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_byte) { StackTypeTest(Ice::Byte, ModelPartForSimple, ModelPartType::Simple); - BOOST_REQUIRE_EQUAL(mpp.get(), mpp->GetContainedModelPart().get()); + BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_short) { StackTypeTest(Ice::Short, ModelPartForSimple, ModelPartType::Simple); - BOOST_REQUIRE_EQUAL(mpp.get(), mpp->GetContainedModelPart().get()); + BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_int) { StackTypeTest(Ice::Int, ModelPartForSimple, ModelPartType::Simple); - BOOST_REQUIRE_EQUAL(mpp.get(), mpp->GetContainedModelPart().get()); + BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_long) { StackTypeTest(Ice::Long, ModelPartForSimple, ModelPartType::Simple); - BOOST_REQUIRE_EQUAL(mpp.get(), mpp->GetContainedModelPart().get()); + BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_struct) { StackTypeTest(TestModule::StructType, ModelPartForStruct, ModelPartType::Complex); - BOOST_REQUIRE_EQUAL(mpp.get(), mpp->GetContainedModelPart().get()); + BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_enum) { StackTypeTest(TestModule::SomeNumbers, ModelPartForEnum, ModelPartType::Simple); - BOOST_REQUIRE_EQUAL(mpp.get(), mpp->GetContainedModelPart().get()); + BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); } BOOST_AUTO_TEST_CASE(normalClassTypeId) -- cgit v1.2.3 From 4fda17d01c68d47de2d8e865bf9f0a2c45517e5f Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 14 Aug 2023 23:33:32 +0100 Subject: Remove enable_shared_from_this from ModelPart --- slicer/slicer/modelParts.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slicer/slicer/modelParts.h b/slicer/slicer/modelParts.h index 979b9f7..1f1a50e 100644 --- a/slicer/slicer/modelParts.h +++ b/slicer/slicer/modelParts.h @@ -140,7 +140,7 @@ namespace Slicer { template struct DLL_PUBLIC Default { }; - class DLL_PUBLIC ModelPart : public std::enable_shared_from_this { + class DLL_PUBLIC ModelPart { public: ModelPart() = default; ModelPart(const ModelPart &) = delete; -- cgit v1.2.3 From 876e40db376ae5cb0bc3c97c5fd70b2b1bee4d46 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 20 Aug 2023 01:35:19 +0100 Subject: Logical inversion Removes ChildRef and changes ModelPart returning ModelPart functions with functions accepting a callback. Removes the need to maintain and pass around ModelPart pointers. ~30% performance increase processing large DB datasets. --- slicer/db/sqlInsertSerializer.cpp | 7 +- slicer/db/sqlSelectDeserializer.cpp | 58 ++++++------ slicer/db/sqlTablePatchSerializer.cpp | 17 ++-- slicer/db/sqlUpdateSerializer.cpp | 7 +- slicer/json/serializer.cpp | 121 ++++++++++++++++--------- slicer/slicer/modelParts.cpp | 33 +++---- slicer/slicer/modelParts.h | 42 +++------ slicer/slicer/modelPartsTypes.cpp | 113 ++++++----------------- slicer/slicer/modelPartsTypes.h | 47 ++++------ slicer/slicer/modelPartsTypes.impl.h | 85 +++++++++--------- slicer/slicer/slicer.cpp | 23 ----- slicer/test/compilation.cpp | 73 ++++++++------- slicer/xml/serializer.cpp | 165 ++++++++++++++++++++-------------- 13 files changed, 385 insertions(+), 406 deletions(-) diff --git a/slicer/db/sqlInsertSerializer.cpp b/slicer/db/sqlInsertSerializer.cpp index c99df57..0881a1b 100644 --- a/slicer/db/sqlInsertSerializer.cpp +++ b/slicer/db/sqlInsertSerializer.cpp @@ -49,9 +49,10 @@ namespace Slicer { void SqlInsertSerializer::SerializeSequence(ModelPartParam mp) const { - auto ins = createInsert(mp->GetContainedModelPart()); - mp->OnEachChild([&ins, this](auto &&, auto && cmp, auto &&) { - bindObjectAndExecute(cmp, ins.get()); + mp->OnContained([this, mp](auto && cmp) { + mp->OnEachChild([ins = createInsert(cmp), this](auto &&, auto && chmp, auto &&) { + bindObjectAndExecute(chmp, ins.get()); + }); }); } diff --git a/slicer/db/sqlSelectDeserializer.cpp b/slicer/db/sqlSelectDeserializer.cpp index 526f4b7..e11493e 100644 --- a/slicer/db/sqlSelectDeserializer.cpp +++ b/slicer/db/sqlSelectDeserializer.cpp @@ -47,10 +47,11 @@ namespace Slicer { return; } if (!(*cmd)[0].isNull()) { - auto fmp = mp->GetAnonChild(); - fmp->Create(); - fmp->SetValue(SqlSource((*cmd)[0])); - fmp->Complete(); + mp->OnAnonChild([this](auto && fmp, auto &&) { + fmp->Create(); + fmp->SetValue(SqlSource((*cmd)[0])); + fmp->Complete(); + }); } if (cmd->fetch()) { throw TooManyRowsReturned(); @@ -60,10 +61,11 @@ namespace Slicer { void SqlSelectDeserializer::DeserializeSequence(ModelPartParam omp) { - auto mp = omp->GetAnonChild(); - while (cmd->fetch()) { - DeserializeRow(mp); - } + omp->OnAnonChild([this](auto && mp, auto &&) { + while (cmd->fetch()) { + DeserializeRow(mp); + } + }); } void @@ -85,29 +87,33 @@ namespace Slicer { void SqlSelectDeserializer::DeserializeRow(ModelPartParam mp) { - auto rmp = mp->GetAnonChild(); - if (rmp) { + mp->OnAnonChild([this](auto && rmp, auto &&) { switch (rmp->GetType()) { case Slicer::ModelPartType::Complex: { + auto apply = [this](auto && rcmp) { + rcmp->Create(); + for (auto col = 0U; col < columnCount; col += 1) { + const DB::Column & c = (*cmd)[col]; + if (!c.isNull()) { + rcmp->OnChild( + [&c](auto && fmp, auto &&) { + if (fmp) { + fmp->Create(); + fmp->SetValue(SqlSource(c)); + fmp->Complete(); + } + }, + c.name, nullptr, false); + } + } + rcmp->Complete(); + }; if (typeIdColIdx) { std::string subclass; (*cmd)[*typeIdColIdx] >> subclass; - rmp = rmp->GetSubclassModelPart(subclass); - } - rmp->Create(); - for (auto col = 0U; col < columnCount; col += 1) { - const DB::Column & c = (*cmd)[col]; - if (!c.isNull()) { - auto fmpr = rmp->GetChildRef(c.name, nullptr, false); - if (fmpr) { - auto fmp = fmpr.Child(); - fmp->Create(); - fmp->SetValue(SqlSource(c)); - fmp->Complete(); - } - } + return rmp->OnSubclass(apply, subclass); } - rmp->Complete(); + apply(rmp); } break; case Slicer::ModelPartType::Simple: { rmp->Create(); @@ -120,6 +126,6 @@ namespace Slicer { default: throw UnsupportedModelType(); } - } + }); } } diff --git a/slicer/db/sqlTablePatchSerializer.cpp b/slicer/db/sqlTablePatchSerializer.cpp index da5b0b2..ec0e344 100644 --- a/slicer/db/sqlTablePatchSerializer.cpp +++ b/slicer/db/sqlTablePatchSerializer.cpp @@ -32,14 +32,15 @@ namespace Slicer { SqlInsertSerializer ins(db, tablePatch.src); ins.Serialize(mpr); - auto mp = mpr->GetContainedModelPart(); - mp->OnEachChild([this](const auto & name, const auto &, const auto & h) { - if (isPKey(h)) { - tablePatch.pk.insert(name); - } - if (isBind(h)) { - tablePatch.cols.insert(name); - } + mpr->OnContained([this](auto && mp) { + mp->OnEachChild([this](const auto & name, const auto &, const auto & h) { + if (isPKey(h)) { + tablePatch.pk.insert(name); + } + if (isBind(h)) { + tablePatch.cols.insert(name); + } + }); }); db->patchTable(&tablePatch); diff --git a/slicer/db/sqlUpdateSerializer.cpp b/slicer/db/sqlUpdateSerializer.cpp index c054764..152c923 100644 --- a/slicer/db/sqlUpdateSerializer.cpp +++ b/slicer/db/sqlUpdateSerializer.cpp @@ -49,9 +49,10 @@ namespace Slicer { void SqlUpdateSerializer::SerializeSequence(ModelPartParam mp) const { - auto ins = createUpdate(mp->GetContainedModelPart()); - mp->OnEachChild([&ins](auto &&, auto && cmp, auto &&) { - bindObjectAndExecute(cmp, ins.get()); + mp->OnContained([this, mp](auto && cmp) { + mp->OnEachChild([upd = createUpdate(cmp)](auto &&, auto && chmp, auto &&) { + bindObjectAndExecute(chmp, upd.get()); + }); }); } diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp index 9bbd508..5b2725b 100644 --- a/slicer/json/serializer.cpp +++ b/slicer/json/serializer.cpp @@ -151,9 +151,9 @@ namespace Slicer { class DocumentTreeIterate { public: static void - visit(ModelPartPtr && mp, const json::Value & v) + visit(ModelPartParam mp, const json::Value & v) { - std::visit(DocumentTreeIterate {std::move(mp)}, v); + std::visit(DocumentTreeIterate {mp}, v); } template @@ -174,34 +174,47 @@ namespace Slicer { void operator()(const json::Object & o) const { + auto apply = [&o](auto && objectModelPart) { + objectModelPart->Create(); + if (objectModelPart->GetMetadata().flagSet(md_object)) { + for (const auto & element : o) { + objectModelPart->OnAnonChild([&element](auto && emp, auto &&) { + emp->Create(); + emp->OnChild( + [&element](auto && key, auto &&) { + key->Create(); + key->SetValue(JsonValueSource(element.first)); + key->Complete(); + }, + keyName); + emp->OnChild( + [&element](auto && value, auto &&) { + visit(value, element.second); + }, + valueName); + emp->Complete(); + }); + } + } + else { + for (const auto & element : o) { + objectModelPart->OnChild( + [&element](auto && emp, auto &&) { + visit(emp, element.second); + emp->Complete(); + }, + element.first); + } + objectModelPart->Complete(); + } + }; if (auto typeIdName = modelPart->GetTypeIdProperty()) { auto typeAttrItr = o.find(*typeIdName); if (typeAttrItr != o.end() && std::holds_alternative(typeAttrItr->second)) { - modelPart = modelPart->GetSubclassModelPart(std::get(typeAttrItr->second)); - } - } - modelPart->Create(); - if (modelPart->GetMetadata().flagSet(md_object)) { - for (const auto & element : o) { - auto emp = modelPart->GetAnonChild(); - emp->Create(); - auto key = emp->GetChild(keyName); - key->Create(); - key->SetValue(JsonValueSource(element.first)); - key->Complete(); - visit(emp->GetChild(valueName), element.second); - emp->Complete(); + return modelPart->OnSubclass(apply, std::get(typeAttrItr->second)); } } - else { - for (const auto & element : o) { - if (auto emp = modelPart->GetChild(element.first)) { - visit(std::move(emp), element.second); - emp->Complete(); - } - } - modelPart->Complete(); - } + apply(modelPart); } void @@ -209,16 +222,15 @@ namespace Slicer { { modelPart->Create(); for (const auto & element : a) { - if (auto emp = modelPart->GetAnonChild()) { - emp->Create(); - visit(std::move(emp), element); + modelPart->OnAnonChild([&element](auto && emp, auto &&) { + visit(emp, element); emp->Complete(); - } + }); } modelPart->Complete(); } - ModelPartPtr && modelPart; + ModelPartParam modelPart; }; void ModelTreeIterateTo(const std::function &, ModelPartParam mp); @@ -243,15 +255,23 @@ namespace Slicer { if (!mp->HasValue()) { return; } - ModelTreeIterateTo( - [&d, mp]() -> json::Value & { - json::Object::key_type k; - json::Value kv; - mp->GetChild(keyName)->GetValue(JsonValueTarget(kv)); - JsonValueSource(kv).set(k); - return d[std::move(k)]; + mp->OnChild( + [&d, mp](auto && cmp, auto &&) { + ModelTreeIterateTo( + [&d, mp]() -> json::Value & { + json::Object::key_type k; + json::Value kv; + mp->OnChild( + [&kv](auto && emp, auto &&) { + emp->GetValue(JsonValueTarget(kv)); + }, + keyName); + JsonValueSource(kv).set(k); + return d[std::move(k)]; + }, + cmp); }, - mp->GetChild(valueName)); + valueName); } void @@ -291,8 +311,11 @@ namespace Slicer { }; if (auto typeIdName = mp->GetTypeIdProperty()) { if (auto typeId = mp->GetTypeId()) { - oec(mp->GetSubclassModelPart(*typeId))->emplace(*typeIdName, *typeId); - return; + return mp->OnSubclass( + [&oec, &typeIdName, &typeId](auto && lmp) { + oec(lmp)->emplace(*typeIdName, *typeId); + }, + *typeId); } } oec(mp); @@ -331,7 +354,11 @@ namespace Slicer { void JsonStreamDeserializer::Deserialize(ModelPartForRootParam modelRoot) { - DocumentTreeIterate::visit(modelRoot->GetAnonChild(), json::parseValue(strm)); + modelRoot->OnAnonChild( + [this](auto && mp, auto &&) { + DocumentTreeIterate::visit(mp, json::parseValue(strm)); + }, + {}); } void @@ -349,7 +376,11 @@ namespace Slicer { JsonFileDeserializer::Deserialize(ModelPartForRootParam modelRoot) { std::ifstream inFile(path); - DocumentTreeIterate::visit(modelRoot->GetAnonChild(), json::parseValue(inFile)); + modelRoot->OnAnonChild( + [&inFile](auto && mp, auto &&) { + DocumentTreeIterate::visit(mp, json::parseValue(inFile)); + }, + {}); } JsonValueDeserializer::JsonValueDeserializer(const json::Value & v) : value(v) { } @@ -357,7 +388,11 @@ namespace Slicer { void JsonValueDeserializer::Deserialize(ModelPartForRootParam modelRoot) { - DocumentTreeIterate::visit(modelRoot->GetAnonChild(), value); + modelRoot->OnAnonChild( + [this](auto && mp, auto &&) { + DocumentTreeIterate::visit(mp, value); + }, + {}); } void diff --git a/slicer/slicer/modelParts.cpp b/slicer/slicer/modelParts.cpp index abe94d8..07b4095 100644 --- a/slicer/slicer/modelParts.cpp +++ b/slicer/slicer/modelParts.cpp @@ -11,10 +11,10 @@ namespace Slicer { { } - ModelPartPtr - ModelPart::GetSubclassModelPart(const std::string &) + void + ModelPart::OnSubclass(const ModelPartHandler &, const std::string &) { - throw std::logic_error {"GetSubclassModelPart not supported on this ModelPart"}; + throw std::logic_error {"OnSubclass not supported on this ModelPart"}; } TypeId @@ -46,30 +46,33 @@ namespace Slicer { return emptyMetadata; } - ModelPartPtr - ModelPart::GetAnonChild(const HookFilter & flt) + bool + ModelPart::IsOptional() const { - auto ref = GetAnonChildRef(flt); - return ref ? ref.Child() : ModelPartPtr(nullptr); + return false; } - ModelPartPtr - ModelPart::GetChild(std::string_view memberName, const HookFilter & flt) + void + ModelPart::OnEachChild(const ChildHandler &) { - auto ref = GetChildRef(memberName, flt); - return ref ? ref.Child() : ModelPartPtr(nullptr); } bool - ModelPart::IsOptional() const + ModelPart::OnAnonChild(const SubPartHandler &, const HookFilter &) { return false; } - ModelPartPtr - ModelPart::GetContainedModelPart() + bool + ModelPart::OnChild(const SubPartHandler &, const std::string_view, const HookFilter &, bool) + { + return false; + } + + void + ModelPart::OnContained(const ModelPartHandler &) { - throw std::logic_error {"GetContainedModelPart not supported on this ModelPart"}; + throw std::logic_error {"OnContained not supported on this ModelPart"}; } bool diff --git a/slicer/slicer/modelParts.h b/slicer/slicer/modelParts.h index 1f1a50e..39149fd 100644 --- a/slicer/slicer/modelParts.h +++ b/slicer/slicer/modelParts.h @@ -83,10 +83,12 @@ namespace Slicer { using ModelPartParam = any_ptr; using ModelPartForRootParam = any_ptr; using TypeId = std::optional; + using Metadata = MetaData<>; using ChildHandler = std::function; - using ClassRef = std::function; + using ModelPartHandler = std::function; + using SubPartHandler = std::function; + using ClassRef = std::function; using HookFilter = std::function; - using Metadata = MetaData<>; constexpr Metadata emptyMetadata; enum class ModelPartType { @@ -103,21 +105,6 @@ namespace Slicer { Value, }; - class DLL_PUBLIC ChildRef { - public: - explicit ChildRef(); - explicit ChildRef(ModelPartPtr); - explicit ChildRef(ModelPartPtr, const Metadata &); - - [[nodiscard]] ModelPartPtr Child() const; - [[nodiscard]] const Metadata & ChildMetaData() const; - explicit operator bool() const; - - private: - ModelPartPtr mpp; - const Metadata & mdr; - }; - class DLL_PUBLIC HookCommon { public: constexpr HookCommon(std::string_view n, std::string_view nl, const std::string * ns) : @@ -156,14 +143,11 @@ namespace Slicer { template static ModelPartPtr CreateFor(Default &&); template static ModelPartForRootPtr CreateRootFor(T & t); - virtual void OnEachChild(const ChildHandler &) = 0; - ModelPartPtr GetAnonChild(const HookFilter & = HookFilter()); - ModelPartPtr GetChild(std::string_view memberName, const HookFilter & = HookFilter()); - virtual ChildRef GetAnonChildRef(const HookFilter & = HookFilter()) = 0; - virtual ChildRef GetChildRef( - std::string_view memberName, const HookFilter & = HookFilter(), bool matchCase = true) - = 0; - virtual ModelPartPtr GetSubclassModelPart(const std::string &); + virtual void OnEachChild(const ChildHandler &); + virtual bool OnAnonChild(const SubPartHandler &, const HookFilter & = HookFilter()); + virtual bool OnChild(const SubPartHandler &, std::string_view memberName, const HookFilter & = HookFilter(), + bool matchCase = true); + virtual void OnSubclass(const ModelPartHandler &, const std::string &); virtual TypeId GetTypeId() const; virtual std::optional GetTypeIdProperty() const; virtual ModelPartType GetType() const = 0; @@ -174,7 +158,7 @@ namespace Slicer { virtual bool HasValue() const = 0; virtual const Metadata & GetMetadata() const; virtual bool IsOptional() const; - virtual ModelPartPtr GetContainedModelPart(); + virtual void OnContained(const ModelPartHandler &); }; template class DLL_PUBLIC ModelPartModel { @@ -189,14 +173,14 @@ namespace Slicer { explicit ModelPartForRootBase(ModelPartPtr mp); virtual const std::string & GetRootName() const = 0; - ChildRef GetAnonChildRef(const HookFilter &) override; - ChildRef GetChildRef(std::string_view name, const HookFilter &, bool matchCase = true) override; + bool OnAnonChild(const SubPartHandler &, const HookFilter &) override; + bool OnChild(const SubPartHandler &, std::string_view name, const HookFilter &, bool matchCase = true) override; void OnEachChild(const ChildHandler & ch) override; ModelPartType GetType() const override; bool IsOptional() const override; virtual void Write(::Ice::OutputStream &) const = 0; virtual void Read(::Ice::InputStream &) = 0; - ModelPartPtr GetContainedModelPart() override; + void OnContained(const ModelPartHandler &) override; ModelPartPtr mp; }; diff --git a/slicer/slicer/modelPartsTypes.cpp b/slicer/slicer/modelPartsTypes.cpp index bd130bf..da38efe 100644 --- a/slicer/slicer/modelPartsTypes.cpp +++ b/slicer/slicer/modelPartsTypes.cpp @@ -110,20 +110,22 @@ namespace Slicer { // ModelPartForRootBase ModelPartForRootBase::ModelPartForRootBase(ModelPartPtr m) : mp(std::move(m)) { } - ChildRef - ModelPartForRootBase::GetAnonChildRef(const HookFilter &) + bool + ModelPartForRootBase::OnAnonChild(const SubPartHandler & h, const HookFilter &) { mp->Create(); - return ChildRef(mp); + h(mp, emptyMetadata); + return true; } - ChildRef - ModelPartForRootBase::GetChildRef(std::string_view name, const HookFilter & hf, bool matchCase) + bool + ModelPartForRootBase::OnChild( + const SubPartHandler & h, std::string_view name, const HookFilter & hf, bool matchCase) { if (!optionalCaseEq(name, GetRootName(), matchCase)) { throw IncorrectElementName(std::string {name}); } - return GetAnonChildRef(hf); + return OnAnonChild(h, hf); } void @@ -144,27 +146,10 @@ namespace Slicer { return mp->IsOptional(); } - ModelPartPtr - ModelPartForRootBase::GetContainedModelPart() - { - return mp->GetContainedModelPart(); - } - void - ModelPartForSimpleBase::OnEachChild(const ChildHandler &) - { - } - - ChildRef - ModelPartForSimpleBase::GetAnonChildRef(const HookFilter &) - { - return ChildRef(); - } - - ChildRef - ModelPartForSimpleBase::GetChildRef(std::string_view, const HookFilter &, bool) + ModelPartForRootBase::OnContained(const ModelPartHandler & h) { - return ChildRef(); + return mp->OnContained(h); } bool @@ -181,23 +166,6 @@ namespace Slicer { const ModelPartType ModelPartForSimpleBase::type = ModelPartType::Simple; - void - ModelPartForConvertedBase::OnEachChild(const ChildHandler &) - { - } - - ChildRef - ModelPartForConvertedBase::GetAnonChildRef(const HookFilter &) - { - return ChildRef(); - } - - ChildRef - ModelPartForConvertedBase::GetChildRef(std::string_view, const HookFilter &, bool) - { - return ChildRef(); - } - bool ModelPartForConvertedBase::HasValue() const { @@ -245,11 +213,11 @@ namespace Slicer { } } - ModelPartPtr - ModelPartForComplexBase::getSubclassModelPart(const std::string & name, void * m) + void + ModelPartForComplexBase::onSubclass(const std::string & name, void * m, const ModelPartHandler & h) { if (const auto ref = refs->find(ToModelTypeName(name)); ref != refs->end()) { - return ref->second(m); + return ref->second(m, h); } throw UnknownType(name); } @@ -284,22 +252,23 @@ namespace Slicer { } } - ChildRef - ModelPartForOptionalBase::GetAnonChildRef(const HookFilter & flt) + bool + ModelPartForOptionalBase::OnAnonChild(const SubPartHandler & h, const HookFilter & flt) { if (this->hasModel()) { - return modelPart->GetAnonChildRef(flt); + return modelPart->OnAnonChild(h, flt); } - return ChildRef(); + return false; } - ChildRef - ModelPartForOptionalBase::GetChildRef(std::string_view name, const HookFilter & flt, bool matchCase) + bool + ModelPartForOptionalBase::OnChild( + const SubPartHandler & h, std::string_view name, const HookFilter & flt, bool matchCase) { if (this->hasModel()) { - return modelPart->GetChildRef(name, flt, matchCase); + return modelPart->OnChild(h, name, flt, matchCase); } - return ChildRef(); + return false; } void @@ -328,23 +297,6 @@ namespace Slicer { return modelPart->GetMetadata(); } - void - ModelPartForEnumBase::OnEachChild(const ChildHandler &) - { - } - - ChildRef - ModelPartForEnumBase::GetAnonChildRef(const HookFilter &) - { - return ChildRef(); - } - - ChildRef - ModelPartForEnumBase::GetChildRef(std::string_view, const HookFilter &, bool) - { - return ChildRef(); - } - bool ModelPartForEnumBase::HasValue() const { @@ -371,13 +323,14 @@ namespace Slicer { return type; } - ChildRef - ModelPartForSequenceBase::GetChildRef(std::string_view name, const HookFilter & flt, bool matchCase) + bool + ModelPartForSequenceBase::OnChild( + const SubPartHandler & h, std::string_view name, const HookFilter & flt, bool matchCase) { if (!name.empty() && !optionalCaseEq(name, GetElementName(), matchCase)) { throw IncorrectElementName(std::string {name}); } - return GetAnonChildRef(flt); + return OnAnonChild(h, flt); } const ModelPartType ModelPartForSequenceBase::type = ModelPartType::Sequence; @@ -397,20 +350,6 @@ namespace Slicer { const ModelPartType ModelPartForDictionaryBase::type = ModelPartType::Dictionary; // Streams - // NOLINTNEXTLINE(hicpp-no-array-decay) - ChildRef - ModelPartForStreamBase::GetAnonChildRef(const Slicer::HookFilter &) - { - throw InvalidStreamOperation(__FUNCTION__); - } - - // NOLINTNEXTLINE(hicpp-no-array-decay) - ChildRef - ModelPartForStreamBase::GetChildRef(std::string_view, const Slicer::HookFilter &, bool) - { - throw InvalidStreamOperation(__FUNCTION__); - } - ModelPartType ModelPartForStreamBase::GetType() const { diff --git a/slicer/slicer/modelPartsTypes.h b/slicer/slicer/modelPartsTypes.h index b6e7b3c..ab262f3 100644 --- a/slicer/slicer/modelPartsTypes.h +++ b/slicer/slicer/modelPartsTypes.h @@ -41,9 +41,6 @@ namespace Slicer { class DLL_PUBLIC ModelPartForSimpleBase : public ModelPart { public: - void OnEachChild(const ChildHandler &) override; - ChildRef GetAnonChildRef(const HookFilter &) override; - ChildRef GetChildRef(std::string_view, const HookFilter &, bool matchCase = true) override; bool HasValue() const override; ModelPartType GetType() const override; static const ModelPartType type; @@ -62,9 +59,6 @@ namespace Slicer { class DLL_PUBLIC ModelPartForConvertedBase : public ModelPart { public: - void OnEachChild(const ChildHandler &) override; - ChildRef GetAnonChildRef(const HookFilter &) override; - ChildRef GetChildRef(std::string_view, const HookFilter &, bool matchCase = true) override; bool HasValue() const override; ModelPartType GetType() const override; static const ModelPartType type; @@ -109,8 +103,9 @@ namespace Slicer { public: void OnEachChild(const ChildHandler & ch) override; void Complete() override; - ChildRef GetAnonChildRef(const HookFilter & flt) override; - ChildRef GetChildRef(std::string_view name, const HookFilter & flt, bool matchCase = true) override; + bool OnAnonChild(const SubPartHandler &, const HookFilter & flt) override; + bool OnChild( + const SubPartHandler &, std::string_view name, const HookFilter & flt, bool matchCase = true) override; void SetValue(ValueSource && s) override; bool HasValue() const override; bool IsOptional() const override; @@ -142,7 +137,7 @@ namespace Slicer { static const ModelPartType type; protected: - ModelPartPtr getSubclassModelPart(const std::string & name, void * m); + void onSubclass(const std::string & name, void * m, const ModelPartHandler &); static void registerClass(const std::string & className, const std::string * typeName, const ClassRef &); static void unregisterClass(const std::string & className, const std::string * typeName); @@ -163,15 +158,16 @@ namespace Slicer { void OnEachChild(const ChildHandler & ch) override; - ChildRef GetAnonChildRef(const HookFilter & flt) override; - ChildRef GetChildRef(std::string_view name, const HookFilter & flt, bool matchCase = true) override; + bool OnAnonChild(const SubPartHandler &, const HookFilter & flt) override; + bool OnChild( + const SubPartHandler &, std::string_view name, const HookFilter & flt, bool matchCase = true) override; const Metadata & GetMetadata() const override; virtual T * GetModel() = 0; protected: - template ChildRef GetChildRefFromRange(const R & range, const HookFilter & flt); + template bool OnChildFromRange(const SubPartHandler &, const R & range, const HookFilter & flt); static const Hooks & hooks(); }; @@ -187,7 +183,7 @@ namespace Slicer { T * GetModel() override; - ModelPartPtr GetSubclassModelPart(const std::string & name) override; + void OnSubclass(const ModelPartHandler &, const std::string & name) override; [[nodiscard]] bool HasValue() const override; @@ -199,7 +195,7 @@ namespace Slicer { static const std::string * className; static const std::string * typeName; - static ModelPartPtr CreateModelPart(void *); + static void CreateModelPart(void *, const ModelPartHandler &); private: static void initClassName(); @@ -221,9 +217,6 @@ namespace Slicer { class DLL_PUBLIC ModelPartForEnumBase : public ModelPart { public: - void OnEachChild(const ChildHandler &) override; - ChildRef GetAnonChildRef(const HookFilter &) override; - ChildRef GetChildRef(std::string_view, const HookFilter &, bool matchCase = true) override; bool HasValue() const override; ModelPartType GetType() const override; static const ModelPartType type; @@ -252,7 +245,7 @@ namespace Slicer { public: bool HasValue() const override; ModelPartType GetType() const override; - ChildRef GetChildRef(std::string_view, const HookFilter &, bool matchCase = true) override; + bool OnChild(const SubPartHandler &, std::string_view, const HookFilter &, bool matchCase = true) override; virtual const std::string & GetElementName() const = 0; static const ModelPartType type; @@ -266,19 +259,19 @@ namespace Slicer { void OnEachChild(const ChildHandler & ch) override; - ChildRef GetAnonChildRef(const HookFilter &) override; + bool OnAnonChild(const SubPartHandler &, const HookFilter &) override; const std::string & GetElementName() const override; const Metadata & GetMetadata() const override; - ModelPartPtr GetContainedModelPart() override; + void OnContained(const ModelPartHandler &) override; static const Metadata metadata; static const std::string elementName; private: - ModelPartPtr elementModelPart(typename T::value_type &) const; + // ModelPartPtr elementModelPart(typename T::value_type &) const; }; template @@ -309,13 +302,13 @@ namespace Slicer { void OnEachChild(const ChildHandler & ch) override; - ChildRef GetAnonChildRef(const HookFilter &) override; + bool OnAnonChild(const SubPartHandler &, const HookFilter &) override; - ChildRef GetChildRef(std::string_view name, const HookFilter &, bool matchCase = true) override; + bool OnChild(const SubPartHandler &, std::string_view name, const HookFilter &, bool matchCase = true) override; const Metadata & GetMetadata() const override; - ModelPartPtr GetContainedModelPart() override; + void OnContained(const ModelPartHandler &) override; static const Metadata metadata; static const std::string pairName; @@ -337,10 +330,8 @@ namespace Slicer { public: ModelPartType GetType() const override; bool HasValue() const override; - ChildRef GetAnonChildRef(const HookFilter &) override; - ChildRef GetChildRef(std::string_view, const HookFilter &, bool matchCase = true) override; - ModelPartPtr GetContainedModelPart() override = 0; + void OnContained(const ModelPartHandler &) override = 0; void OnEachChild(const ChildHandler & ch) override = 0; }; @@ -348,7 +339,7 @@ namespace Slicer { public: using ModelPartModel>::ModelPartModel; - ModelPartPtr GetContainedModelPart() override; + void OnContained(const ModelPartHandler &) override; void OnEachChild(const ChildHandler & ch) override; }; diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h index 0924de6..9cdbe47 100644 --- a/slicer/slicer/modelPartsTypes.impl.h +++ b/slicer/slicer/modelPartsTypes.impl.h @@ -354,8 +354,8 @@ namespace Slicer { template template - ChildRef - ModelPartForComplex::GetChildRefFromRange(const R & range, const HookFilter & flt) + bool + ModelPartForComplex::OnChildFromRange(const SubPartHandler & ch, const R & range, const HookFilter & flt) { const auto itr = std::find_if(range.begin(), range.end(), [&flt](auto && h) { return h->filter(flt); @@ -363,29 +363,31 @@ namespace Slicer { if (itr != range.end()) { const auto & h = *itr; auto model = GetModel(); - return ChildRef(h->Get(model), h->GetMetadata()); + ch(h->Get(model), h->GetMetadata()); + return true; } - return ChildRef(); + return false; } template - ChildRef - ModelPartForComplex::GetAnonChildRef(const HookFilter & flt) + bool + ModelPartForComplex::OnAnonChild(const SubPartHandler & ch, const HookFilter & flt) { - return GetChildRefFromRange(hooks(), flt); + return OnChildFromRange(ch, hooks(), flt); } template - ChildRef - ModelPartForComplex::GetChildRef(std::string_view name, const HookFilter & flt, bool matchCase) + bool + ModelPartForComplex::OnChild( + const SubPartHandler & ch, std::string_view name, const HookFilter & flt, bool matchCase) { if (matchCase) { - return GetChildRefFromRange(hooks().equal_range(name), flt); + return OnChildFromRange(ch, hooks().equal_range(name), flt); } else { std::string i {name}; to_lower(i); - return GetChildRefFromRange(hooks().equal_range_lower(i), flt); + return OnChildFromRange(ch, hooks().equal_range_lower(i), flt); } } @@ -453,11 +455,11 @@ namespace Slicer { } template - ModelPartPtr - ModelPartForClass::GetSubclassModelPart(const std::string & name) + void + ModelPartForClass::OnSubclass(const ModelPartHandler & h, const std::string & name) { BOOST_ASSERT(this->Model); - return ModelPartForComplexBase::getSubclassModelPart(name, this->Model); + return ModelPartForComplexBase::onSubclass(name, this->Model, h); } template @@ -476,10 +478,10 @@ namespace Slicer { } template - ModelPartPtr - ModelPartForClass::CreateModelPart(void * p) + void + ModelPartForClass::CreateModelPart(void * p, const ModelPartHandler & h) { - return ::Slicer::ModelPart::CreateFor(*static_cast(p)); + return h(::Slicer::ModelPart::CreateFor(*static_cast(p))); } template @@ -598,16 +600,17 @@ namespace Slicer { { BOOST_ASSERT(this->Model); for (auto & element : *this->Model) { - ch(elementName, elementModelPart(element), NULL); + ch(elementName, ModelPart::CreateFor(element), NULL); } } template - ChildRef - ModelPartForSequence::GetAnonChildRef(const HookFilter &) + bool + ModelPartForSequence::OnAnonChild(const SubPartHandler & ch, const HookFilter &) { BOOST_ASSERT(this->Model); - return ChildRef(ModelPart::CreateFor(this->Model->emplace_back())); + ch(ModelPart::CreateFor(this->Model->emplace_back()), emptyMetadata); + return true; } template @@ -625,17 +628,10 @@ namespace Slicer { } template - ModelPartPtr - ModelPartForSequence::elementModelPart(typename T::value_type & e) const - { - return ModelPart::CreateFor(e); - } - - template - ModelPartPtr - ModelPartForSequence::GetContainedModelPart() + void + ModelPartForSequence::OnContained(const ModelPartHandler & h) { - return ModelPart::CreateFor(Default {}); + return h(ModelPart::CreateFor(Default {})); } // ModelPartForDictionaryElementInserter @@ -664,22 +660,25 @@ namespace Slicer { } template - ChildRef - ModelPartForDictionary::GetAnonChildRef(const HookFilter &) + bool + ModelPartForDictionary::OnAnonChild(const SubPartHandler & ch, const HookFilter &) { BOOST_ASSERT(this->Model); - return ChildRef(std::make_shared>(this->Model)); + ch(std::make_shared>(this->Model), emptyMetadata); + return true; } template - ChildRef - ModelPartForDictionary::GetChildRef(std::string_view name, const HookFilter &, bool matchCase) + bool + ModelPartForDictionary::OnChild( + const SubPartHandler & ch, std::string_view name, const HookFilter &, bool matchCase) { BOOST_ASSERT(this->Model); if (!optionalCaseEq(name, pairName, matchCase)) { throw IncorrectElementName(std::string {name}); } - return ChildRef(std::make_shared>(this->Model)); + ch(std::make_shared>(this->Model), emptyMetadata); + return true; } template @@ -690,18 +689,18 @@ namespace Slicer { } template - ModelPartPtr - ModelPartForDictionary::GetContainedModelPart() + void + ModelPartForDictionary::OnContained(const ModelPartHandler & h) { - return std::make_shared>(nullptr); + return h(std::make_shared>(nullptr)); } // ModelPartForStream template - ModelPartPtr - ModelPartForStream::GetContainedModelPart() + void + ModelPartForStream::OnContained(const ModelPartHandler & h) { - return ModelPart::CreateFor(Default {}); + return h(ModelPart::CreateFor(Default {})); } template diff --git a/slicer/slicer/slicer.cpp b/slicer/slicer/slicer.cpp index 2eda740..ff9a948 100644 --- a/slicer/slicer/slicer.cpp +++ b/slicer/slicer/slicer.cpp @@ -5,29 +5,6 @@ #include namespace Slicer { - Slicer::ChildRef::ChildRef() : mpp(), mdr(emptyMetadata) { } - - Slicer::ChildRef::ChildRef(ModelPartPtr m) : mpp(std::move(m)), mdr(emptyMetadata) { } - - Slicer::ChildRef::ChildRef(ModelPartPtr mp, const Slicer::Metadata & md) : mpp(std::move(mp)), mdr(md) { } - - ModelPartPtr - Slicer::ChildRef::Child() const - { - return mpp; - } - - Slicer::ChildRef::operator bool() const - { - return !!mpp; - } - - const Metadata & - Slicer::ChildRef::ChildMetaData() const - { - return mdr; - } - AdHocFormatter(InvalidEnumerationSymbolMsg, "Invalid enumeration symbol [%?] for type [%?]"); void diff --git a/slicer/test/compilation.cpp b/slicer/test/compilation.cpp index fbbbb5f..ba7c568 100644 --- a/slicer/test/compilation.cpp +++ b/slicer/test/compilation.cpp @@ -40,11 +40,15 @@ BOOST_TEST_DONT_PRINT_LOG_VALUE(Slicer::ModelPartType) #define StackTypeTest(Var, Explicit, Expected) TypeTest(Var, Var(), Explicit, Expected) +constexpr auto DontCall = [](auto &&...) { + BOOST_ERROR("Shouldn't be called"); +}; + BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_class) { TypeTest(TestModule::BuiltInsPtr, std::make_shared(), ModelPartForClass, ModelPartType::Complex); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } static void @@ -53,7 +57,7 @@ hookHandler(std::vector * names, const std::string & name, Slicer:: { names->push_back(name); BOOST_REQUIRE(mpp); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); BOOST_REQUIRE(h); BOOST_REQUIRE_EQUAL(h->name, name); } @@ -61,39 +65,42 @@ hookHandler(std::vector * names, const std::string & name, Slicer:: BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_sequenceclasses) { StackTypeTest(TestModule::Classes, ModelPartForSequence, ModelPartType::Sequence); - auto cmpp = mpp->GetContainedModelPart(); - BOOST_REQUIRE(cmpp); - BOOST_REQUIRE_EQUAL(Slicer::ModelPartType::Complex, cmpp->GetType()); - std::vector names; - cmpp->OnEachChild([&](auto && PH1, auto && PH2, auto && PH3) { - hookHandler(&names, PH1, PH2, PH3); + mpp->OnContained([](auto && cmpp) { + BOOST_REQUIRE(cmpp); + BOOST_REQUIRE_EQUAL(Slicer::ModelPartType::Complex, cmpp->GetType()); + std::vector names; + cmpp->OnEachChild([&](auto && PH1, auto && PH2, auto && PH3) { + hookHandler(&names, PH1, PH2, PH3); + }); + BOOST_REQUIRE_EQUAL(2, names.size()); + BOOST_REQUIRE_EQUAL("a", names.front()); + BOOST_REQUIRE_EQUAL("b", names.back()); }); - BOOST_REQUIRE_EQUAL(2, names.size()); - BOOST_REQUIRE_EQUAL("a", names.front()); - BOOST_REQUIRE_EQUAL("b", names.back()); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_sequencestructs) { StackTypeTest(TestModule::Structs, ModelPartForSequence, ModelPartType::Sequence); - auto cmpp = mpp->GetContainedModelPart(); - BOOST_REQUIRE(cmpp); - BOOST_REQUIRE_EQUAL(Slicer::ModelPartType::Complex, cmpp->GetType()); - std::vector names; - cmpp->OnEachChild([&](auto && PH1, auto && PH2, auto && PH3) { - hookHandler(&names, PH1, PH2, PH3); + mpp->OnContained([](auto && cmpp) { + BOOST_REQUIRE(cmpp); + BOOST_REQUIRE_EQUAL(Slicer::ModelPartType::Complex, cmpp->GetType()); + std::vector names; + cmpp->OnEachChild([&](auto && PH1, auto && PH2, auto && PH3) { + hookHandler(&names, PH1, PH2, PH3); + }); + BOOST_REQUIRE_EQUAL(2, names.size()); + BOOST_REQUIRE_EQUAL("a", names.front()); + BOOST_REQUIRE_EQUAL("b", names.back()); }); - BOOST_REQUIRE_EQUAL(2, names.size()); - BOOST_REQUIRE_EQUAL("a", names.front()); - BOOST_REQUIRE_EQUAL("b", names.back()); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_mapclasses) { StackTypeTest(TestModule::ClassMap, ModelPartForDictionary, ModelPartType::Dictionary); - auto cmpp = mpp->GetContainedModelPart(); - BOOST_REQUIRE(cmpp); - BOOST_REQUIRE_EQUAL(Slicer::ModelPartType::Complex, cmpp->GetType()); + mpp->OnContained([](auto && cmpp) { + BOOST_REQUIRE(cmpp); + BOOST_REQUIRE_EQUAL(Slicer::ModelPartType::Complex, cmpp->GetType()); + }); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_mapstructs) @@ -104,61 +111,61 @@ BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_mapstructs) BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_string) { StackTypeTest(std::string, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_bool) { StackTypeTest(bool, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_float) { StackTypeTest(Ice::Float, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_double) { StackTypeTest(Ice::Double, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_byte) { StackTypeTest(Ice::Byte, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_short) { StackTypeTest(Ice::Short, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_int) { StackTypeTest(Ice::Int, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_long) { StackTypeTest(Ice::Long, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_struct) { StackTypeTest(TestModule::StructType, ModelPartForStruct, ModelPartType::Complex); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_enum) { StackTypeTest(TestModule::SomeNumbers, ModelPartForEnum, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->GetContainedModelPart(), std::logic_error); + BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); } BOOST_AUTO_TEST_CASE(normalClassTypeId) diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp index 5eab4be..8e351b6 100644 --- a/slicer/xml/serializer.cpp +++ b/slicer/xml/serializer.cpp @@ -221,7 +221,7 @@ namespace Slicer { }; void DocumentTreeIterate(const xmlpp::Node * node, ModelPartParam mp); - void DocumentTreeIterateElement(const xmlpp::Element * element, ModelPartParam mp, const ChildRef & c); + void DocumentTreeIterateElement(const xmlpp::Element * element, ModelPartParam mp, const Metadata & md); void DocumentTreeIterate(const xmlpp::Document * doc, ModelPartParam mp); void DocumentTreeIterateDictAttrs(const xmlpp::Element::const_AttributeList & attrs, ModelPartParam dict); void DocumentTreeIterateDictElements(const xmlpp::Element * parent, ModelPartParam dict); @@ -229,18 +229,23 @@ namespace Slicer { void DocumentTreeIterateDictAttrs(const xmlpp::Element::const_AttributeList & attrs, ModelPartParam dict) { - using AttrMember = Glib::ustring (xmlpp::Attribute::*)() const; for (const auto & attr : attrs) { - auto emp = dict->GetAnonChild(); - emp->Create(); - const auto setChild = [&emp, &attr](const auto & childName, AttrMember attrMember) { - auto child = emp->GetChild(childName); - child->SetValue(XmlValueSource((attr->*attrMember)())); - child->Complete(); - }; - setChild(keyName, &xmlpp::Attribute::get_name); - setChild(valueName, &xmlpp::Attribute::get_value); - emp->Complete(); + dict->OnAnonChild([&attr](auto && emp, auto &&) { + emp->Create(); + emp->OnChild( + [&attr](auto && child, auto &&) { + child->SetValue(XmlValueSource(attr->get_name())); + child->Complete(); + }, + keyName); + emp->OnChild( + [&attr](auto && value, auto &&) { + value->SetValue(XmlValueSource(attr->get_value())); + value->Complete(); + }, + valueName); + emp->Complete(); + }); } } @@ -250,31 +255,38 @@ namespace Slicer { auto node = element->get_first_child(); while (node) { if (auto childElement = dynamic_cast(node)) { - auto emp = dict->GetAnonChild(); - emp->Create(); - auto key = emp->GetChild(keyName); - auto value = emp->GetChildRef(valueName); - key->SetValue(XmlValueSource(childElement->get_name())); - key->Complete(); - DocumentTreeIterateElement(childElement, value.Child(), value); - emp->Complete(); + dict->OnAnonChild([childElement](auto && emp, auto &&) { + emp->Create(); + emp->OnChild( + [childElement](auto && child, auto &&) { + child->SetValue(XmlValueSource(childElement->get_name())); + child->Complete(); + }, + keyName); + emp->OnChild( + [childElement](auto && value, auto && md) { + DocumentTreeIterateElement(childElement, value, md); + }, + valueName); + emp->Complete(); + }); } node = node->get_next_sibling(); } } void - DocumentTreeIterateElement(const xmlpp::Element * element, ModelPartParam smp, const ChildRef & smpr) + DocumentTreeIterateElement(const xmlpp::Element * element, ModelPartParam smp, const Metadata & md) { - auto oec = [&smpr, element](const auto & lmp) { + auto oec = [&md, element](const auto & lmp) { lmp->Create(); - if (smpr.ChildMetaData().flagSet(md_attributes)) { + if (md.flagSet(md_attributes)) { auto attrs(element->get_attributes()); if (!attrs.empty()) { DocumentTreeIterateDictAttrs(attrs, lmp); } } - else if (smpr.ChildMetaData().flagSet(md_elements)) { + else if (md.flagSet(md_elements)) { DocumentTreeIterateDictElements(element, lmp); } else { @@ -294,8 +306,7 @@ namespace Slicer { }; if (auto typeIdPropName = smp->GetTypeIdProperty()) { if (auto typeAttr = element->get_attribute(*typeIdPropName)) { - oec(smp->GetSubclassModelPart(typeAttr->get_value())); - return; + return smp->OnSubclass(oec, typeAttr->get_value()); } } oec(smp); @@ -306,40 +317,45 @@ namespace Slicer { { while (node) { if (auto element = dynamic_cast(node)) { - auto smpr = mp->GetChildRef(element->get_name().raw(), [](const auto & h) { - return h->GetMetadata().flagNotSet(md_attribute); - }); - if (smpr) { - auto smp = smpr.Child(); - if (smpr.ChildMetaData().flagSet(md_bare)) { - smp = smp->GetAnonChild(); - } - if (smp) { - DocumentTreeIterateElement(element, smp, smpr); - } - } + mp->OnChild( + [element](auto && smp, auto && md) { + if (md.flagSet(md_bare)) { + smp->OnAnonChild([element](auto && bmp, auto && bmd) { + DocumentTreeIterateElement(element, bmp, bmd); + }); + return; + } + DocumentTreeIterateElement(element, smp, md); + }, + element->get_name().raw(), + [](const auto & h) { + return h->GetMetadata().flagNotSet(md_attribute); + }); } else if (auto attribute = dynamic_cast(node)) { - auto smp = mp->GetChild(attribute->get_name().raw(), [](const auto & h) { - return h->GetMetadata().flagSet(md_attribute); - }); - if (smp) { - smp->Create(); - smp->SetValue(XmlValueSource(attribute)); - smp->Complete(); - } + mp->OnChild( + [attribute](auto && smp, auto &&) { + smp->Create(); + smp->SetValue(XmlValueSource(attribute)); + smp->Complete(); + }, + attribute->get_name().raw(), + [](const auto & h) { + return h->GetMetadata().flagSet(md_attribute); + }); } else if (auto content = dynamic_cast(node)) { - ModelPartPtr smp; + bool bare = false; if (!content->is_white_space()) { - smp = mp->GetAnonChild([](const auto & h) { - return h->GetMetadata().flagSet(md_text); - }); - } - if (smp) { - smp->SetValue(XmlValueSource(content)); + bare = (mp->OnAnonChild( + [content](auto && smp, auto &&) { + smp->SetValue(XmlValueSource(content)); + }, + [](const auto & h) { + return h->GetMetadata().flagSet(md_text); + })); } - else { + if (!bare) { mp->SetValue(XmlValueSource(content)); } } @@ -397,9 +413,17 @@ namespace Slicer { { dict->OnEachChild([element](const auto &, const auto & mp, const auto &) { if (mp->HasValue()) { - mp->GetChild(keyName)->GetValue(XmlValueTarget([&mp, element](const auto & name) { - mp->GetChild(valueName)->GetValue(XmlValueTarget(element, name)); - })); + mp->OnChild( + [mp, element](auto && key, auto &&) { + key->GetValue(XmlValueTarget([mp, element](const auto & name) { + mp->OnChild( + [element, &name](auto && value, auto &&) { + value->GetValue(XmlValueTarget(element, name)); + }, + valueName); + })); + }, + keyName); } }); } @@ -409,12 +433,20 @@ namespace Slicer { { dict->OnEachChild([element](const auto &, const auto & mp, const auto &) { if (mp->HasValue()) { - mp->GetChild(keyName)->GetValue(XmlValueTarget([&mp, element](const auto & name) { - CurrentElementCreator cec([&element, &name]() { - return element->add_child_element(name); - }); - ModelTreeProcessElement(cec, mp->GetChild(valueName), defaultElementCreator); - })); + mp->OnChild( + [mp, element](auto && key, auto &&) { + key->GetValue(XmlValueTarget([mp, element](const auto & name) { + CurrentElementCreator cec([&element, &name]() { + return element->add_child_element(name); + }); + mp->OnChild( + [&cec](auto && value, auto &&) { + ModelTreeProcessElement(cec, value, defaultElementCreator); + }, + valueName); + })); + }, + keyName); } }); } @@ -434,8 +466,11 @@ namespace Slicer { }; if (auto typeIdPropName = mp->GetTypeIdProperty()) { if (auto typeId = mp->GetTypeId()) { - oec(mp->GetSubclassModelPart(*typeId))->set_attribute(*typeIdPropName, *typeId); - return; + return mp->OnSubclass( + [oec, &typeIdPropName, &typeId](auto && smp) { + oec(smp)->set_attribute(*typeIdPropName, *typeId); + }, + *typeId); } } oec(mp); -- cgit v1.2.3 From d485e880cba753d9783309be1dbb9da57d6ce634 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 20 Aug 2023 01:46:36 +0100 Subject: Create dictionary container/children ModelParts on the stack No longer uses make_shared. --- slicer/slicer/modelPartsTypes.impl.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h index 9cdbe47..7884a02 100644 --- a/slicer/slicer/modelPartsTypes.impl.h +++ b/slicer/slicer/modelPartsTypes.impl.h @@ -664,7 +664,7 @@ namespace Slicer { ModelPartForDictionary::OnAnonChild(const SubPartHandler & ch, const HookFilter &) { BOOST_ASSERT(this->Model); - ch(std::make_shared>(this->Model), emptyMetadata); + ch(ModelPartForDictionaryElementInserter(this->Model), emptyMetadata); return true; } @@ -677,7 +677,7 @@ namespace Slicer { if (!optionalCaseEq(name, pairName, matchCase)) { throw IncorrectElementName(std::string {name}); } - ch(std::make_shared>(this->Model), emptyMetadata); + ch(ModelPartForDictionaryElementInserter(this->Model), emptyMetadata); return true; } @@ -692,7 +692,7 @@ namespace Slicer { void ModelPartForDictionary::OnContained(const ModelPartHandler & h) { - return h(std::make_shared>(nullptr)); + return h(ModelPartForStruct(nullptr)); } // ModelPartForStream -- cgit v1.2.3 From 07e61f5e729884f8bdc19cf213c919ea6a98369c Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 20 Aug 2023 01:52:30 +0100 Subject: Create Optional ModelParts as unique_ptrs --- slicer/slicer/modelParts.h | 1 + slicer/slicer/modelPartsTypes.h | 2 +- slicer/slicer/modelPartsTypes.impl.h | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/slicer/slicer/modelParts.h b/slicer/slicer/modelParts.h index 39149fd..f521257 100644 --- a/slicer/slicer/modelParts.h +++ b/slicer/slicer/modelParts.h @@ -79,6 +79,7 @@ namespace Slicer { class HookCommon; using ModelPartPtr = std::shared_ptr; + using ModelPartUPtr = std::unique_ptr; using ModelPartForRootPtr = std::unique_ptr; using ModelPartParam = any_ptr; using ModelPartForRootParam = any_ptr; diff --git a/slicer/slicer/modelPartsTypes.h b/slicer/slicer/modelPartsTypes.h index ab262f3..838bbd0 100644 --- a/slicer/slicer/modelPartsTypes.h +++ b/slicer/slicer/modelPartsTypes.h @@ -113,7 +113,7 @@ namespace Slicer { protected: virtual bool hasModel() const = 0; - ModelPartPtr modelPart; + ModelPartUPtr modelPart; }; template diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h index 7884a02..3a4076e 100644 --- a/slicer/slicer/modelPartsTypes.impl.h +++ b/slicer/slicer/modelPartsTypes.impl.h @@ -300,7 +300,7 @@ namespace Slicer { ModelPartModel>(h) { if (this->Model && *this->Model) { - modelPart = std::make_shared(&**this->Model); + modelPart = std::make_unique(&**this->Model); } } @@ -319,7 +319,7 @@ namespace Slicer { BOOST_ASSERT(this->Model); if (!*this->Model) { *this->Model = typename T::element_type(); - modelPart = std::make_shared(&**this->Model); + modelPart = std::make_unique(&**this->Model); modelPart->Create(); } } -- cgit v1.2.3 From 041637576884a1ad08c4e11912099d1d47510952 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 20 Aug 2023 13:30:49 +0100 Subject: Make ModelPartRoots on stack --- slicer/slicer/modelParts.h | 4 ++-- slicer/slicer/modelPartsTypes.impl.h | 23 +++++++++++------------ slicer/slicer/slicer.h | 8 ++++++-- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/slicer/slicer/modelParts.h b/slicer/slicer/modelParts.h index f521257..da929ba 100644 --- a/slicer/slicer/modelParts.h +++ b/slicer/slicer/modelParts.h @@ -80,13 +80,13 @@ namespace Slicer { using ModelPartPtr = std::shared_ptr; using ModelPartUPtr = std::unique_ptr; - using ModelPartForRootPtr = std::unique_ptr; using ModelPartParam = any_ptr; using ModelPartForRootParam = any_ptr; using TypeId = std::optional; using Metadata = MetaData<>; using ChildHandler = std::function; using ModelPartHandler = std::function; + using ModelPartRootHandler = std::function; using SubPartHandler = std::function; using ClassRef = std::function; using HookFilter = std::function; @@ -142,7 +142,7 @@ namespace Slicer { template static ModelPartPtr Make(typename MP::element_type * t); template static ModelPartPtr CreateFor(T & t); template static ModelPartPtr CreateFor(Default &&); - template static ModelPartForRootPtr CreateRootFor(T & t); + template static void OnRootFor(T & t, const ModelPartRootHandler &); virtual void OnEachChild(const ChildHandler &); virtual bool OnAnonChild(const SubPartHandler &, const HookFilter & = HookFilter()); diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h index 3a4076e..393809f 100644 --- a/slicer/slicer/modelPartsTypes.impl.h +++ b/slicer/slicer/modelPartsTypes.impl.h @@ -67,21 +67,21 @@ namespace Ice { { \ return CreateFor(const_cast &>(s)); \ } \ - template<> DLL_PUBLIC ModelPartForRootPtr ModelPart::CreateRootFor(Type & s) \ + template<> DLL_PUBLIC void ModelPart::OnRootFor(Type & s, const ModelPartRootHandler & h) \ { \ - return std::make_unique>(&s); \ + h(ModelPartForRoot(&s)); \ } \ - template<> DLL_PUBLIC ModelPartForRootPtr ModelPart::CreateRootFor(Ice::optional & s) \ + template<> DLL_PUBLIC void ModelPart::OnRootFor(Ice::optional & s, const ModelPartRootHandler & h) \ { \ - return std::make_unique>>(&s); \ + h(ModelPartForRoot>(&s)); \ } \ - template<> DLL_PUBLIC ModelPartForRootPtr ModelPart::CreateRootFor(const Type & s) \ + template<> DLL_PUBLIC void ModelPart::OnRootFor(const Type & s, const ModelPartRootHandler & h) \ { \ - return CreateRootFor(const_cast(s)); \ + return OnRootFor(const_cast(s), h); \ } \ - template<> DLL_PUBLIC ModelPartForRootPtr ModelPart::CreateRootFor(const Ice::optional & s) \ + template<> DLL_PUBLIC void ModelPart::OnRootFor(const Ice::optional & s, const ModelPartRootHandler & h) \ { \ - return CreateRootFor(const_cast &>(s)); \ + return OnRootFor(const_cast &>(s), h); \ } \ template class BaseModelPart; \ template class ModelPartForRoot; \ @@ -91,11 +91,10 @@ namespace Ice { #define MODELPARTFORSTREAM(StreamImpl) \ namespace Slicer { \ template<> \ - DLL_PUBLIC ModelPartForRootPtr \ - ModelPart::CreateRootFor(const StreamImpl & stream) \ + DLL_PUBLIC void \ + ModelPart::OnRootFor(const StreamImpl & stream, const ModelPartRootHandler & h) \ { \ - return std::make_unique>( \ - const_cast(&stream)); \ + h(ModelPartForStreamRoot(const_cast(&stream))); \ } \ } diff --git a/slicer/slicer/slicer.h b/slicer/slicer/slicer.h index 66e4537..cb15af2 100644 --- a/slicer/slicer/slicer.h +++ b/slicer/slicer/slicer.h @@ -11,7 +11,9 @@ namespace Slicer { DeserializeAnyWith(any_ptr deserializer) { Object object {}; - deserializer->Deserialize(ModelPart::CreateRootFor(object)); + ModelPart::OnRootFor(object, [deserializer](auto && mp) { + deserializer->Deserialize(mp); + }); return object; } @@ -26,7 +28,9 @@ namespace Slicer { void SerializeAnyWith(const Object & object, any_ptr serializer) { - serializer->Serialize(ModelPart::CreateRootFor(object)); + ModelPart::OnRootFor(object, [serializer](auto && mp) { + serializer->Serialize(mp); + }); } template -- cgit v1.2.3 From 248b83144ab7facb9a124a1f5c2d1806412cc27e Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 21 Aug 2023 01:19:46 +0100 Subject: Make remaining non-root ModelParts on the stack --- slicer/slicer/modelParts.h | 11 +-- slicer/slicer/modelPartsTypes.cpp | 2 +- slicer/slicer/modelPartsTypes.h | 7 +- slicer/slicer/modelPartsTypes.impl.h | 92 ++++++++++-------- slicer/test/compilation.cpp | 182 ++++++++++++++++++----------------- slicer/test/conversions.cpp | 6 +- slicer/test/serializers.cpp | 6 +- slicer/tool/parser.cpp | 14 +-- 8 files changed, 169 insertions(+), 151 deletions(-) diff --git a/slicer/slicer/modelParts.h b/slicer/slicer/modelParts.h index da929ba..de6e89f 100644 --- a/slicer/slicer/modelParts.h +++ b/slicer/slicer/modelParts.h @@ -78,7 +78,6 @@ namespace Slicer { class ModelPartForRootBase; class HookCommon; - using ModelPartPtr = std::shared_ptr; using ModelPartUPtr = std::unique_ptr; using ModelPartParam = any_ptr; using ModelPartForRootParam = any_ptr; @@ -139,9 +138,9 @@ namespace Slicer { ModelPart & operator=(const ModelPart &) = delete; ModelPart & operator=(ModelPart &&) = delete; - template static ModelPartPtr Make(typename MP::element_type * t); - template static ModelPartPtr CreateFor(T & t); - template static ModelPartPtr CreateFor(Default &&); + template static void Make(typename MP::element_type * t, const ModelPartHandler &); + template static void CreateFor(T & t, const ModelPartHandler &); + template static void CreateFor(Default &&, const ModelPartHandler &); template static void OnRootFor(T & t, const ModelPartRootHandler &); virtual void OnEachChild(const ChildHandler &); @@ -171,7 +170,7 @@ namespace Slicer { class DLL_PUBLIC ModelPartForRootBase : public ModelPart { public: - explicit ModelPartForRootBase(ModelPartPtr mp); + explicit ModelPartForRootBase(ModelPartParam mp); virtual const std::string & GetRootName() const = 0; bool OnAnonChild(const SubPartHandler &, const HookFilter &) override; @@ -183,7 +182,7 @@ namespace Slicer { virtual void Read(::Ice::InputStream &) = 0; void OnContained(const ModelPartHandler &) override; - ModelPartPtr mp; + ModelPartParam mp; }; } diff --git a/slicer/slicer/modelPartsTypes.cpp b/slicer/slicer/modelPartsTypes.cpp index da38efe..673265e 100644 --- a/slicer/slicer/modelPartsTypes.cpp +++ b/slicer/slicer/modelPartsTypes.cpp @@ -108,7 +108,7 @@ namespace Slicer { } // ModelPartForRootBase - ModelPartForRootBase::ModelPartForRootBase(ModelPartPtr m) : mp(std::move(m)) { } + ModelPartForRootBase::ModelPartForRootBase(ModelPartParam m) : mp(m) { } bool ModelPartForRootBase::OnAnonChild(const SubPartHandler & h, const HookFilter &) diff --git a/slicer/slicer/modelPartsTypes.h b/slicer/slicer/modelPartsTypes.h index 838bbd0..f8a8814 100644 --- a/slicer/slicer/modelPartsTypes.h +++ b/slicer/slicer/modelPartsTypes.h @@ -26,7 +26,7 @@ namespace Slicer { template class ModelPartForRoot : public ModelPartForRootBase { public: - explicit ModelPartForRoot(T * o); + explicit ModelPartForRoot(T * o, ModelPartParam mp); const std::string & GetRootName() const override; bool HasValue() const override; @@ -269,9 +269,6 @@ namespace Slicer { static const Metadata metadata; static const std::string elementName; - - private: - // ModelPartPtr elementModelPart(typename T::value_type &) const; }; template @@ -356,7 +353,7 @@ namespace Slicer { template class ModelPartForStreamRoot : public ModelPartForStreamRootBase { public: - explicit ModelPartForStreamRoot(Stream * s); + using ModelPartForStreamRootBase::ModelPartForStreamRootBase; const std::string & GetRootName() const override; }; diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h index 393809f..dc6ff07 100644 --- a/slicer/slicer/modelPartsTypes.impl.h +++ b/slicer/slicer/modelPartsTypes.impl.h @@ -33,47 +33,53 @@ namespace Ice { } #define CUSTOMMODELPARTFOR(Type, BaseModelPart, ModelPartType) \ - template<> DLL_PUBLIC ModelPartPtr ModelPart::Make(typename ModelPartType::element_type * t) \ + template<> \ + DLL_PUBLIC void ModelPart::Make( \ + typename ModelPartType::element_type * t, const ModelPartHandler & h) \ { \ - return std::make_shared(t); \ + h(ModelPartType(t)); \ } \ template<> \ - DLL_PUBLIC ModelPartPtr ModelPart::Make>( \ - Ice::optional * t) \ + DLL_PUBLIC void ModelPart::Make>( \ + Ice::optional * t, const ModelPartHandler & h) \ { \ - return std::make_shared>(t); \ + h(ModelPartForOptional(t)); \ } \ - template<> DLL_PUBLIC ModelPartPtr ModelPart::CreateFor(Default &&) \ + template<> DLL_PUBLIC void ModelPart::CreateFor(Default &&, const ModelPartHandler & h) \ { \ - return Make(nullptr); \ + return Make(nullptr, h); \ } \ - template<> DLL_PUBLIC ModelPartPtr ModelPart::CreateFor(Default> &&) \ + template<> DLL_PUBLIC void ModelPart::CreateFor(Default> &&, const ModelPartHandler & h) \ { \ - return Make>(nullptr); \ + return Make>(nullptr, h); \ } \ - template<> DLL_PUBLIC ModelPartPtr ModelPart::CreateFor(Type & s) \ + template<> DLL_PUBLIC void ModelPart::CreateFor(Type & s, const ModelPartHandler & h) \ { \ - return Make(&s); \ + return Make(&s, h); \ } \ - template<> DLL_PUBLIC ModelPartPtr ModelPart::CreateFor(const Type & s) \ + template<> DLL_PUBLIC void ModelPart::CreateFor(const Type & s, const ModelPartHandler & h) \ { \ - return CreateFor(const_cast(s)); \ + return CreateFor(const_cast(s), h); \ } \ - template<> DLL_PUBLIC ModelPartPtr ModelPart::CreateFor(Ice::optional & s) \ + template<> DLL_PUBLIC void ModelPart::CreateFor(Ice::optional & s, const ModelPartHandler & h) \ { \ - return Make>(&s); \ + return Make>(&s, h); \ } \ - template<> DLL_PUBLIC ModelPartPtr ModelPart::CreateFor(const Ice::optional & s) \ + template<> DLL_PUBLIC void ModelPart::CreateFor(const Ice::optional & s, const ModelPartHandler & h) \ { \ - return CreateFor(const_cast &>(s)); \ + return CreateFor(const_cast &>(s), h); \ } \ template<> DLL_PUBLIC void ModelPart::OnRootFor(Type & s, const ModelPartRootHandler & h) \ { \ - h(ModelPartForRoot(&s)); \ + return CreateFor(s, [&s, &h](auto && mp) { \ + h(ModelPartForRoot(&s, mp)); \ + }); \ } \ template<> DLL_PUBLIC void ModelPart::OnRootFor(Ice::optional & s, const ModelPartRootHandler & h) \ { \ - h(ModelPartForRoot>(&s)); \ + return CreateFor(s, [&s, &h](auto && mp) { \ + h(ModelPartForRoot>(&s, mp)); \ + }); \ } \ template<> DLL_PUBLIC void ModelPart::OnRootFor(const Type & s, const ModelPartRootHandler & h) \ { \ @@ -94,7 +100,8 @@ namespace Ice { DLL_PUBLIC void \ ModelPart::OnRootFor(const StreamImpl & stream, const ModelPartRootHandler & h) \ { \ - h(ModelPartForStreamRoot(const_cast(&stream))); \ + ModelPartForStream strm(const_cast(&stream)); \ + h(ModelPartForStreamRoot(strm)); \ } \ } @@ -111,7 +118,7 @@ namespace Ice { namespace Slicer { // ModelPartForRoot template - ModelPartForRoot::ModelPartForRoot(T * o) : ModelPartForRootBase(ModelPart::CreateFor(*o)), ModelObject(o) + ModelPartForRoot::ModelPartForRoot(T * o, ModelPartParam omp) : ModelPartForRootBase(omp), ModelObject(o) { } @@ -347,7 +354,9 @@ namespace Slicer { ModelPartForComplex::OnEachChild(const ChildHandler & ch) { for (const auto & h : hooks()) { - h->apply(ch, h->Get(GetModel())); + h->On(GetModel(), [h, &ch](auto && mp) { + h->apply(ch, mp); + }); } } @@ -361,8 +370,9 @@ namespace Slicer { }); if (itr != range.end()) { const auto & h = *itr; - auto model = GetModel(); - ch(h->Get(model), h->GetMetadata()); + h->On(GetModel(), [h, &ch](auto && mp) { + ch(mp, h->GetMetadata()); + }); return true; } return false; @@ -394,7 +404,7 @@ namespace Slicer { public: using HookCommon::HookCommon; - virtual ModelPartPtr Get(T * t) const = 0; + virtual void On(T * t, const ModelPartHandler &) const = 0; }; template @@ -417,13 +427,13 @@ namespace Slicer { return hookMetadata; } - ModelPartPtr - Get(T * t) const override + void + On(T * t, const ModelPartHandler & h) const override { if (t) { - return Make(&(t->*member)); + return Make(&(t->*member), h); } - return Make(nullptr); + return Make(nullptr, h); } private: @@ -480,7 +490,7 @@ namespace Slicer { void ModelPartForClass::CreateModelPart(void * p, const ModelPartHandler & h) { - return h(::Slicer::ModelPart::CreateFor(*static_cast(p))); + return ::Slicer::ModelPart::CreateFor(*static_cast(p), h); } template @@ -599,7 +609,9 @@ namespace Slicer { { BOOST_ASSERT(this->Model); for (auto & element : *this->Model) { - ch(elementName, ModelPart::CreateFor(element), NULL); + ModelPart::CreateFor(element, [&ch](auto && mp) { + ch(elementName, mp, nullptr); + }); } } @@ -608,7 +620,9 @@ namespace Slicer { ModelPartForSequence::OnAnonChild(const SubPartHandler & ch, const HookFilter &) { BOOST_ASSERT(this->Model); - ch(ModelPart::CreateFor(this->Model->emplace_back()), emptyMetadata); + ModelPart::CreateFor(this->Model->emplace_back(), [&ch](auto && mp) { + ch(mp, emptyMetadata); + }); return true; } @@ -630,7 +644,7 @@ namespace Slicer { void ModelPartForSequence::OnContained(const ModelPartHandler & h) { - return h(ModelPart::CreateFor(Default {})); + return ModelPart::CreateFor(Default {}, h); } // ModelPartForDictionaryElementInserter @@ -699,7 +713,7 @@ namespace Slicer { void ModelPartForStream::OnContained(const ModelPartHandler & h) { - return h(ModelPart::CreateFor(Default {})); + ModelPart::CreateFor(Default {}, h); } template @@ -708,16 +722,12 @@ namespace Slicer { { BOOST_ASSERT(this->Model); this->Model->Produce([&ch](const T & element) { - ch(ModelPartForSequence>::elementName, ModelPart::CreateFor(element), NULL); + ModelPart::CreateFor(element, [&ch](auto && mp) { + ch(ModelPartForSequence>::elementName, mp, nullptr); + }); }); } - template - ModelPartForStreamRoot::ModelPartForStreamRoot(Stream * s) : - ModelPartForStreamRootBase(std::make_shared>(s)) - { - } - template const std::string & ModelPartForStreamRoot::GetRootName() const diff --git a/slicer/test/compilation.cpp b/slicer/test/compilation.cpp index ba7c568..14bf1d9 100644 --- a/slicer/test/compilation.cpp +++ b/slicer/test/compilation.cpp @@ -23,22 +23,24 @@ BOOST_TEST_DONT_PRINT_LOG_VALUE(std::type_info) BOOST_TEST_DONT_PRINT_LOG_VALUE(Slicer::ModelPartType) // LCOV_EXCL_STOP -#define TypeTest(Var, Expr, Explicit, Expected) \ +#define TypeTest(Var, Expr, Explicit, Expected, ...) \ Var obj = Expr; \ - Slicer::ModelPartPtr mpp = Slicer::ModelPart::CreateFor(obj); \ - BOOST_REQUIRE_EQUAL(Slicer::Expected, mpp->GetType()); \ + Slicer::ModelPart::CreateFor(obj, [](auto && mpp) { \ + BOOST_REQUIRE_EQUAL(Slicer::Expected, mpp->GetType()); \ \ - BOOST_TEST_CONTEXT(#Var) { \ - auto mppvalue = mpp.get(); \ - auto amppvalue = mpp.get(); \ - auto apmppvalue = mpp.get(); \ - BOOST_TEST_CONTEXT(typeid(*mppvalue).name()) { \ - BOOST_REQUIRE_EQUAL(typeid(*mppvalue), typeid(*amppvalue)); \ - BOOST_REQUIRE_EQUAL(typeid(*mppvalue), typeid(*apmppvalue)); \ + BOOST_TEST_CONTEXT(#Var) { \ + auto mppvalue = mpp.get(); \ + auto amppvalue = mpp.get(); \ + auto apmppvalue = mpp.get(); \ + BOOST_TEST_CONTEXT(typeid(*mppvalue).name()) { \ + BOOST_REQUIRE_EQUAL(typeid(*mppvalue), typeid(*amppvalue)); \ + BOOST_REQUIRE_EQUAL(typeid(*mppvalue), typeid(*apmppvalue)); \ + } \ } \ - } + __VA_ARGS__ \ + }); -#define StackTypeTest(Var, Explicit, Expected) TypeTest(Var, Var(), Explicit, Expected) +#define StackTypeTest(Var, Explicit, Expected, ...) TypeTest(Var, Var(), Explicit, Expected, __VA_ARGS__) constexpr auto DontCall = [](auto &&...) { BOOST_ERROR("Shouldn't be called"); @@ -47,8 +49,7 @@ constexpr auto DontCall = [](auto &&...) { BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_class) { TypeTest(TestModule::BuiltInsPtr, std::make_shared(), ModelPartForClass, - ModelPartType::Complex); - BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); + ModelPartType::Complex, { BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); }); } static void @@ -64,42 +65,45 @@ hookHandler(std::vector * names, const std::string & name, Slicer:: BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_sequenceclasses) { - StackTypeTest(TestModule::Classes, ModelPartForSequence, ModelPartType::Sequence); - mpp->OnContained([](auto && cmpp) { - BOOST_REQUIRE(cmpp); - BOOST_REQUIRE_EQUAL(Slicer::ModelPartType::Complex, cmpp->GetType()); - std::vector names; - cmpp->OnEachChild([&](auto && PH1, auto && PH2, auto && PH3) { - hookHandler(&names, PH1, PH2, PH3); + StackTypeTest(TestModule::Classes, ModelPartForSequence, ModelPartType::Sequence, { + mpp->OnContained([](auto && cmpp) { + BOOST_REQUIRE(cmpp); + BOOST_REQUIRE_EQUAL(Slicer::ModelPartType::Complex, cmpp->GetType()); + std::vector names; + cmpp->OnEachChild([&](auto && PH1, auto && PH2, auto && PH3) { + hookHandler(&names, PH1, PH2, PH3); + }); + BOOST_REQUIRE_EQUAL(2, names.size()); + BOOST_REQUIRE_EQUAL("a", names.front()); + BOOST_REQUIRE_EQUAL("b", names.back()); }); - BOOST_REQUIRE_EQUAL(2, names.size()); - BOOST_REQUIRE_EQUAL("a", names.front()); - BOOST_REQUIRE_EQUAL("b", names.back()); }); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_sequencestructs) { - StackTypeTest(TestModule::Structs, ModelPartForSequence, ModelPartType::Sequence); - mpp->OnContained([](auto && cmpp) { - BOOST_REQUIRE(cmpp); - BOOST_REQUIRE_EQUAL(Slicer::ModelPartType::Complex, cmpp->GetType()); - std::vector names; - cmpp->OnEachChild([&](auto && PH1, auto && PH2, auto && PH3) { - hookHandler(&names, PH1, PH2, PH3); + StackTypeTest(TestModule::Structs, ModelPartForSequence, ModelPartType::Sequence, { + mpp->OnContained([](auto && cmpp) { + BOOST_REQUIRE(cmpp); + BOOST_REQUIRE_EQUAL(Slicer::ModelPartType::Complex, cmpp->GetType()); + std::vector names; + cmpp->OnEachChild([&](auto && PH1, auto && PH2, auto && PH3) { + hookHandler(&names, PH1, PH2, PH3); + }); + BOOST_REQUIRE_EQUAL(2, names.size()); + BOOST_REQUIRE_EQUAL("a", names.front()); + BOOST_REQUIRE_EQUAL("b", names.back()); }); - BOOST_REQUIRE_EQUAL(2, names.size()); - BOOST_REQUIRE_EQUAL("a", names.front()); - BOOST_REQUIRE_EQUAL("b", names.back()); }); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_mapclasses) { - StackTypeTest(TestModule::ClassMap, ModelPartForDictionary, ModelPartType::Dictionary); - mpp->OnContained([](auto && cmpp) { - BOOST_REQUIRE(cmpp); - BOOST_REQUIRE_EQUAL(Slicer::ModelPartType::Complex, cmpp->GetType()); + StackTypeTest(TestModule::ClassMap, ModelPartForDictionary, ModelPartType::Dictionary, { + mpp->OnContained([](auto && cmpp) { + BOOST_REQUIRE(cmpp); + BOOST_REQUIRE_EQUAL(Slicer::ModelPartType::Complex, cmpp->GetType()); + }); }); } @@ -110,124 +114,130 @@ BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_mapstructs) BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_string) { - StackTypeTest(std::string, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); + StackTypeTest(std::string, ModelPartForSimple, ModelPartType::Simple, + { BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); }); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_bool) { - StackTypeTest(bool, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); + StackTypeTest(bool, ModelPartForSimple, ModelPartType::Simple, + { BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); }); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_float) { - StackTypeTest(Ice::Float, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); + StackTypeTest(Ice::Float, ModelPartForSimple, ModelPartType::Simple, + { BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); }); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_double) { - StackTypeTest(Ice::Double, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); + StackTypeTest(Ice::Double, ModelPartForSimple, ModelPartType::Simple, + { BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); }); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_byte) { - StackTypeTest(Ice::Byte, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); + StackTypeTest(Ice::Byte, ModelPartForSimple, ModelPartType::Simple, + { BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); }); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_short) { - StackTypeTest(Ice::Short, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); + StackTypeTest(Ice::Short, ModelPartForSimple, ModelPartType::Simple, + { BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); }); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_int) { - StackTypeTest(Ice::Int, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); + StackTypeTest(Ice::Int, ModelPartForSimple, ModelPartType::Simple, + { BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); }); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_bi_long) { - StackTypeTest(Ice::Long, ModelPartForSimple, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); + StackTypeTest(Ice::Long, ModelPartForSimple, ModelPartType::Simple, + { BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); }); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_struct) { - StackTypeTest(TestModule::StructType, ModelPartForStruct, ModelPartType::Complex); - BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); + StackTypeTest(TestModule::StructType, ModelPartForStruct, ModelPartType::Complex, + { BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); }); } BOOST_AUTO_TEST_CASE(compile_auto_modelpart_type_enum) { - StackTypeTest(TestModule::SomeNumbers, ModelPartForEnum, ModelPartType::Simple); - BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); + StackTypeTest(TestModule::SomeNumbers, ModelPartForEnum, ModelPartType::Simple, + { BOOST_CHECK_THROW(mpp->OnContained(DontCall), std::logic_error); }); } BOOST_AUTO_TEST_CASE(normalClassTypeId) { TestModule::BasePtr base = std::make_shared(1); BOOST_REQUIRE(base); - auto a = Slicer::ModelPart::CreateFor(base); - BOOST_REQUIRE(a); - auto baseType = a->GetTypeId(); - BOOST_REQUIRE(!baseType); + Slicer::ModelPart::CreateFor(base, [](auto && a) { + BOOST_REQUIRE(a); + auto baseType = a->GetTypeId(); + BOOST_REQUIRE(!baseType); + }); } BOOST_AUTO_TEST_CASE(normalSubClassTypeId) { TestModule::BasePtr base = std::make_shared(1, 2); BOOST_REQUIRE(base); - auto a = Slicer::ModelPart::CreateFor(base); - BOOST_REQUIRE(a); - auto baseType = a->GetTypeId(); - BOOST_REQUIRE(baseType); - BOOST_REQUIRE_EQUAL(*baseType, "::TestModule::D1"); + Slicer::ModelPart::CreateFor(base, [](auto && a) { + BOOST_REQUIRE(a); + auto baseType = a->GetTypeId(); + BOOST_REQUIRE(baseType); + BOOST_REQUIRE_EQUAL(*baseType, "::TestModule::D1"); + }); } BOOST_AUTO_TEST_CASE(normalSubSubClassTypeId) { TestModule::BasePtr base = std::make_shared(1, 2, 3); BOOST_REQUIRE(base); - auto a = Slicer::ModelPart::CreateFor(base); - BOOST_REQUIRE(a); - auto baseType = a->GetTypeId(); - BOOST_REQUIRE(baseType); - BOOST_REQUIRE_EQUAL(*baseType, "::TestModule::D3"); + Slicer::ModelPart::CreateFor(base, [](auto && a) { + BOOST_REQUIRE(a); + auto baseType = a->GetTypeId(); + BOOST_REQUIRE(baseType); + BOOST_REQUIRE_EQUAL(*baseType, "::TestModule::D3"); + }); } BOOST_AUTO_TEST_CASE(localClassTypeId) { Locals::LocalClassPtr base = std::make_shared(1, "One"); BOOST_REQUIRE(base); - auto a = Slicer::ModelPart::CreateFor(base); - BOOST_REQUIRE(a); - auto baseType = a->GetTypeId(); - BOOST_REQUIRE(!baseType); + Slicer::ModelPart::CreateFor(base, [](auto && a) { + BOOST_REQUIRE(a); + auto baseType = a->GetTypeId(); + BOOST_REQUIRE(!baseType); + }); } BOOST_AUTO_TEST_CASE(localSubClassTypeId) { Locals::LocalClassPtr base = std::make_shared(1, "One", 3.1); BOOST_REQUIRE(base); - auto a = Slicer::ModelPart::CreateFor(base); - BOOST_REQUIRE(a); - auto baseType = a->GetTypeId(); - BOOST_REQUIRE(baseType); - BOOST_REQUIRE_EQUAL(*baseType, "::Locals::LocalSubClass"); + Slicer::ModelPart::CreateFor(base, [](auto && a) { + BOOST_REQUIRE(a); + auto baseType = a->GetTypeId(); + BOOST_REQUIRE(baseType); + BOOST_REQUIRE_EQUAL(*baseType, "::Locals::LocalSubClass"); + }); } BOOST_AUTO_TEST_CASE(localSubSubClassTypeId) { Locals::LocalClassPtr base = std::make_shared(1, "One", 3.1, 1); BOOST_REQUIRE(base); - auto a = Slicer::ModelPart::CreateFor(base); - BOOST_REQUIRE(a); - auto baseType = a->GetTypeId(); - BOOST_REQUIRE(baseType); - BOOST_REQUIRE_EQUAL(*baseType, "::Locals::LocalSub2Class"); + Slicer::ModelPart::CreateFor(base, [](auto && a) { + BOOST_REQUIRE(a); + auto baseType = a->GetTypeId(); + BOOST_REQUIRE(baseType); + BOOST_REQUIRE_EQUAL(*baseType, "::Locals::LocalSub2Class"); + }); } diff --git a/slicer/test/conversions.cpp b/slicer/test/conversions.cpp index a296197..193cd4f 100644 --- a/slicer/test/conversions.cpp +++ b/slicer/test/conversions.cpp @@ -175,9 +175,9 @@ namespace TestModule { namespace Slicer { template<> - DLL_PUBLIC ModelPartPtr - ModelPart::Make(::Ice::Short * m) + DLL_PUBLIC void + ModelPart::Make(::Ice::Short * m, const ModelPartHandler & h) { - return std::make_shared(m); + return h(TestModule::MonthValidator(m)); } } diff --git a/slicer/test/serializers.cpp b/slicer/test/serializers.cpp index 6a41cdd..f02dbaf 100644 --- a/slicer/test/serializers.cpp +++ b/slicer/test/serializers.cpp @@ -710,6 +710,8 @@ BOOST_AUTO_TEST_CASE(enum_lookups) BOOST_AUTO_TEST_CASE(sequence_element_in_same_slice_link_bug) { // Link error when sequence element type defined in same slice. - BOOST_CHECK(Slicer::ModelPart::Make>(nullptr)); - BOOST_CHECK(Slicer::ModelPart::Make>(nullptr)); + BOOST_CHECK_NO_THROW( + Slicer::ModelPart::Make>(nullptr, [](auto &&) {})); + BOOST_CHECK_NO_THROW( + Slicer::ModelPart::Make>(nullptr, [](auto &&) {})); } diff --git a/slicer/tool/parser.cpp b/slicer/tool/parser.cpp index 28252b5..55a06fe 100644 --- a/slicer/tool/parser.cpp +++ b/slicer/tool/parser.cpp @@ -238,13 +238,13 @@ namespace Slicer { fprintbf(cpp, "\tconversion_fail(\"%s\");\n", Slice::typeToString(type)); fprintbf(cpp, "}\n\n"); - fprintbf(cpp, "\ttemplate<> DLL_PUBLIC ModelPartPtr ModelPart::Make<"); + fprintbf(cpp, "\ttemplate<> DLL_PUBLIC void ModelPart::Make<"); createModelPartForConverted(type, c->scoped(), dm); fprintbf(cpp, ">(typename "); createModelPartForConverted(type, c->scoped(), dm); - fprintbf(cpp, "::element_type * t) { return std::make_shared<"); + fprintbf(cpp, "::element_type * t, const ModelPartHandler & h) { return h("); createModelPartForConverted(type, c->scoped(), dm); - fprintbf(cpp, ">(t); } \n"); + fprintbf(cpp, "(t)); } \n"); } } @@ -444,9 +444,9 @@ namespace Slicer { if (auto cmp = md.value("slicer:custommodelpart:")) { fprintbf(cpp, "CUSTOMMODELPARTFOR(%s, %s< %s >, %s)\n\n", Slice::typeToString(decl), getBasicModelPart(decl), c->scoped(), CppName {*cmp}); - fprintbf(cpp, "\ttemplate<> DLL_PUBLIC ModelPartPtr ModelPart::Make<%s<%s> >(%s * t)", + fprintbf(cpp, "\ttemplate<> DLL_PUBLIC void ModelPart::Make<%s<%s> >(%s * t, const ModelPartHandler & h)", getBasicModelPart(decl), c->scoped(), Slice::typeToString(decl)); - fprintbf(cpp, "{ return std::make_shared<%s>(t); } \n", CppName {*cmp}); + fprintbf(cpp, "{ return h(%s(t)); } \n", CppName {*cmp}); } else { fprintbf(cpp, "CUSTOMMODELPARTFOR(%s, ModelPartForClass<%s>, ModelPartForClass<%s>)\n\n", @@ -764,9 +764,9 @@ namespace Slicer { if (auto cmp = metadata.value("slicer:custommodelpart:")) { fprintbf(cpp, "CUSTOMMODELPARTFOR(%s, %s< %s >, %s)\n\n", type, getBasicModelPart(stype), type, CppName {*cmp}); - fprintbf(cpp, "\ttemplate<> DLL_PUBLIC ModelPartPtr ModelPart::Make<%s<%s>>(%s * t)", + fprintbf(cpp, "\ttemplate<> DLL_PUBLIC void ModelPart::Make<%s<%s>>(%s * t, const ModelPartHandler & h)", getBasicModelPart(stype), type, type); - fprintbf(cpp, "{ return std::make_shared<%s>(t); } \n", CppName {*cmp}); + fprintbf(cpp, "{ return h(%s(t)); } \n", CppName {*cmp}); } else { fprintbf(cpp, "MODELPARTFOR(%s, %s)\n\n", type, getBasicModelPart(stype)); -- cgit v1.2.3 From 9128c51c7315375515a104b1bea2cfe8ca966881 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 21 Aug 2023 21:38:03 +0100 Subject: Add a DB perf case for a complex with non-optional members --- slicer/db/testPerf.cpp | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/slicer/db/testPerf.cpp b/slicer/db/testPerf.cpp index 2f98cd2..bb2a4c3 100644 --- a/slicer/db/testPerf.cpp +++ b/slicer/db/testPerf.cpp @@ -1,6 +1,7 @@ #include "sqlSelectDeserializer.h" #include "testMockCommon.h" #include +#include #include #include #include @@ -8,17 +9,29 @@ const StandardMockDatabase db; -class CoreFixture : public benchmark::Fixture, public ConnectionFixture { }; - -BENCHMARK_F(CoreFixture, bulk_select_complex)(benchmark::State & state) -{ - auto sel = db->select(R"SQL( +class CoreFixture : public benchmark::Fixture, public ConnectionFixture { +protected: + template + void + do_bulk_select_complex(benchmark::State & state) + { + auto sel = db->select(R"SQL( SELECT s mint, CAST(s AS NUMERIC(7,1)) mdouble, CAST(s as text) mstring, s % 2 = 0 mbool FROM GENERATE_SERIES(1, 10000) s)SQL"); - for (auto _ : state) { - benchmark::DoNotOptimize( - Slicer::DeserializeAny(sel.get())); + for (auto _ : state) { + benchmark::DoNotOptimize(Slicer::DeserializeAny(sel.get())); + } } +}; + +BENCHMARK_F(CoreFixture, bulk_select_complex)(benchmark::State & state) +{ + do_bulk_select_complex(state); +} + +BENCHMARK_F(CoreFixture, bulk_select_complex_non_optional)(benchmark::State & state) +{ + do_bulk_select_complex(state); } BENCHMARK_MAIN(); -- cgit v1.2.3 From ca9a42002d4d7ac82cc48f8afd3748df5db7ccd4 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 21 Aug 2023 21:43:33 +0100 Subject: Create Optional ModelParts on the stack with std::optional Supercedes the previous change to unique_ptr and now all ModelParts are on the stack. --- slicer/slicer/modelParts.h | 1 - slicer/slicer/modelPartsTypes.h | 3 ++- slicer/slicer/modelPartsTypes.impl.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/slicer/slicer/modelParts.h b/slicer/slicer/modelParts.h index de6e89f..8adc8f2 100644 --- a/slicer/slicer/modelParts.h +++ b/slicer/slicer/modelParts.h @@ -78,7 +78,6 @@ namespace Slicer { class ModelPartForRootBase; class HookCommon; - using ModelPartUPtr = std::unique_ptr; using ModelPartParam = any_ptr; using ModelPartForRootParam = any_ptr; using TypeId = std::optional; diff --git a/slicer/slicer/modelPartsTypes.h b/slicer/slicer/modelPartsTypes.h index f8a8814..2079195 100644 --- a/slicer/slicer/modelPartsTypes.h +++ b/slicer/slicer/modelPartsTypes.h @@ -113,7 +113,7 @@ namespace Slicer { protected: virtual bool hasModel() const = 0; - ModelPartUPtr modelPart; + ModelPart * modelPart; }; template @@ -129,6 +129,7 @@ namespace Slicer { protected: bool hasModel() const override; + std::optional modelPartOwner; }; class DLL_PUBLIC ModelPartForComplexBase : public ModelPart { diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h index dc6ff07..ad1a90f 100644 --- a/slicer/slicer/modelPartsTypes.impl.h +++ b/slicer/slicer/modelPartsTypes.impl.h @@ -306,7 +306,7 @@ namespace Slicer { ModelPartModel>(h) { if (this->Model && *this->Model) { - modelPart = std::make_unique(&**this->Model); + modelPart = &modelPartOwner.emplace(&**this->Model); } } @@ -325,7 +325,7 @@ namespace Slicer { BOOST_ASSERT(this->Model); if (!*this->Model) { *this->Model = typename T::element_type(); - modelPart = std::make_unique(&**this->Model); + modelPart = &modelPartOwner.emplace(&**this->Model); modelPart->Create(); } } -- cgit v1.2.3 From 4653a46e8208436baa7fea871c3948b1186bcd2c Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Tue, 22 Aug 2023 19:50:28 +0100 Subject: Add a copying to_lower wrapper --- slicer/slicer/hookMap.cpp | 6 ++++++ slicer/slicer/hookMap.h | 1 + 2 files changed, 7 insertions(+) diff --git a/slicer/slicer/hookMap.cpp b/slicer/slicer/hookMap.cpp index 3192d6c..c32db2d 100644 --- a/slicer/slicer/hookMap.cpp +++ b/slicer/slicer/hookMap.cpp @@ -7,4 +7,10 @@ namespace Slicer { { boost::algorithm::to_lower(s); } + + std::string + to_lower_copy(const std::string & s) + { + return boost::algorithm::to_lower_copy(s); + } } diff --git a/slicer/slicer/hookMap.h b/slicer/slicer/hookMap.h index daef5b0..3328ddd 100644 --- a/slicer/slicer/hookMap.h +++ b/slicer/slicer/hookMap.h @@ -11,6 +11,7 @@ namespace Slicer { void DLL_PUBLIC to_lower(std::string & s); + [[nodiscard]] std::string DLL_PUBLIC to_lower_copy(const std::string & s); template class ModelPartForComplex; // IWYU pragma: keep -- cgit v1.2.3 From bbae6d83c6d7ea25f17965fd68062f0cab3da5e4 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Wed, 23 Aug 2023 00:26:20 +0100 Subject: Cache the Hook name/column relation for non-subclass multi-row selects --- slicer/db/sqlSelectDeserializer.cpp | 78 ++++++++++++++++++++++++++++++------- slicer/db/sqlSelectDeserializer.h | 13 +++++-- 2 files changed, 72 insertions(+), 19 deletions(-) diff --git a/slicer/db/sqlSelectDeserializer.cpp b/slicer/db/sqlSelectDeserializer.cpp index e11493e..8081d76 100644 --- a/slicer/db/sqlSelectDeserializer.cpp +++ b/slicer/db/sqlSelectDeserializer.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -58,10 +59,53 @@ namespace Slicer { } } + void + SqlSelectDeserializer::fillLowerColumnNameCache() + { + BOOST_ASSERT(lowerColumnNames.empty()); + lowerColumnNames.reserve(columnCount); + orderedColumns.reserve(columnCount); + for (auto col = 0U; col < columnCount; col += 1) { + const DB::Column & c = (*cmd)[col]; + lowerColumnNames.emplace_back(to_lower_copy(c.name)); + } + } + + const DB::Column * + SqlSelectDeserializer::searchOrFilleColumnCache(size_t idx, const HookCommon * hook) + { + if (idx < orderedColumns.size()) { + return orderedColumns[idx]; + } + BOOST_ASSERT(idx == orderedColumns.size()); + if (const auto itr = std::find(lowerColumnNames.begin(), lowerColumnNames.end(), hook->nameLower); + itr != lowerColumnNames.end()) { + return orderedColumns.emplace_back(&(*cmd)[static_cast(itr - lowerColumnNames.begin())]); + } + else { + return orderedColumns.emplace_back(nullptr); + } + } + + namespace { + void + assignFromColumn(ModelPartParam fmp, const DB::Column & c) + { + BOOST_ASSERT(fmp); + BOOST_ASSERT(!c.isNull()); + fmp->Create(); + fmp->SetValue(SqlSource(c)); + fmp->Complete(); + } + } + void SqlSelectDeserializer::DeserializeSequence(ModelPartParam omp) { omp->OnAnonChild([this](auto && mp, auto &&) { + if (!typeIdColIdx && lowerColumnNames.empty()) { + fillLowerColumnNameCache(); + } while (cmd->fetch()) { DeserializeRow(mp); } @@ -92,20 +136,26 @@ namespace Slicer { case Slicer::ModelPartType::Complex: { auto apply = [this](auto && rcmp) { rcmp->Create(); - for (auto col = 0U; col < columnCount; col += 1) { - const DB::Column & c = (*cmd)[col]; - if (!c.isNull()) { - rcmp->OnChild( - [&c](auto && fmp, auto &&) { - if (fmp) { - fmp->Create(); - fmp->SetValue(SqlSource(c)); - fmp->Complete(); - } - }, - c.name, nullptr, false); + if (typeIdColIdx || lowerColumnNames.empty()) { + for (auto col = 0U; col < columnCount; col += 1) { + const DB::Column & c = (*cmd)[col]; + if (!c.isNull()) { + rcmp->OnChild( + [&c](auto && fmp, auto &&) { + assignFromColumn(fmp, c); + }, + c.name, nullptr, false); + } } } + else { + rcmp->OnEachChild([idx = 0U, this](auto &&, auto && fmp, auto && hook) mutable { + if (auto c = searchOrFilleColumnCache(idx, hook); c && !c->isNull()) { + assignFromColumn(fmp, *c); + } + ++idx; + }); + } rcmp->Complete(); }; if (typeIdColIdx) { @@ -116,12 +166,10 @@ namespace Slicer { apply(rmp); } break; case Slicer::ModelPartType::Simple: { - rmp->Create(); const DB::Column & c = (*cmd)[0]; if (!c.isNull()) { - rmp->SetValue(SqlSource(c)); + assignFromColumn(rmp, c); } - rmp->Complete(); } break; default: throw UnsupportedModelType(); diff --git a/slicer/db/sqlSelectDeserializer.h b/slicer/db/sqlSelectDeserializer.h index f8fce08..b911fb1 100644 --- a/slicer/db/sqlSelectDeserializer.h +++ b/slicer/db/sqlSelectDeserializer.h @@ -9,6 +9,7 @@ namespace DB { class SelectCommand; + class Column; } namespace Slicer { @@ -20,15 +21,19 @@ namespace Slicer { void Deserialize(ModelPartForRootParam) override; protected: - void DLL_PRIVATE DeserializeSimple(ModelPartParam); - void DLL_PRIVATE DeserializeObject(ModelPartParam); - void DLL_PRIVATE DeserializeSequence(ModelPartParam); - void DLL_PRIVATE DeserializeRow(ModelPartParam); + DLL_PRIVATE void DeserializeSimple(ModelPartParam); + DLL_PRIVATE void DeserializeObject(ModelPartParam); + DLL_PRIVATE void DeserializeSequence(ModelPartParam); + DLL_PRIVATE void DeserializeRow(ModelPartParam); + DLL_PRIVATE void fillLowerColumnNameCache(); + DLL_PRIVATE inline const DB::Column * searchOrFilleColumnCache(size_t idx, const HookCommon * hook); DB::SelectCommand * cmd; unsigned int columnCount; std::optional typeIdColName; std::optional typeIdColIdx; + std::vector lowerColumnNames; + std::vector orderedColumns; }; } -- cgit v1.2.3 From 65aab79e40e5e74cde61517dbc3c2e8a661beb9d Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Wed, 23 Aug 2023 02:03:02 +0100 Subject: Prevent multiple inline copies of json::Value destructor --- slicer/json/serializer.cpp | 2 ++ slicer/json/serializer.h | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp index 5b2725b..4070231 100644 --- a/slicer/json/serializer.cpp +++ b/slicer/json/serializer.cpp @@ -395,6 +395,8 @@ namespace Slicer { {}); } + JsonValueSerializer::~JsonValueSerializer() = default; + void JsonValueSerializer::Serialize(ModelPartForRootParam modelRoot) { diff --git a/slicer/json/serializer.h b/slicer/json/serializer.h index bba1486..682ec27 100644 --- a/slicer/json/serializer.h +++ b/slicer/json/serializer.h @@ -13,6 +13,10 @@ namespace Slicer { class DLL_PUBLIC JsonValueSerializer : public Serializer { public: + JsonValueSerializer() = default; + ~JsonValueSerializer() override; + SPECIAL_MEMBERS_DEFAULT(JsonValueSerializer); + void Serialize(ModelPartForRootParam) override; protected: -- cgit v1.2.3