From 8f105dc162fcc64f13b03e692fe73d6da0790843 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Sat, 4 Nov 2023 10:24:17 -0500 Subject: [PATCH 1/5] App/Toponaming: ComplexGeoData serialization Direct copy from TopoNaming branch with only modifications needed to compile against API changes. --- src/App/ComplexGeoData.cpp | 207 +++++++++++++++++++++++++++++++++++++ src/App/ComplexGeoData.h | 19 ++++ 2 files changed, 226 insertions(+) diff --git a/src/App/ComplexGeoData.cpp b/src/App/ComplexGeoData.cpp index fcf7977e46..d805daaa11 100644 --- a/src/App/ComplexGeoData.cpp +++ b/src/App/ComplexGeoData.cpp @@ -38,9 +38,12 @@ #include #include +#include #include +#include #include +#include using namespace Data; @@ -386,4 +389,208 @@ char ComplexGeoData::elementType(const char *name) const { return 0; } +void ComplexGeoData::setPersistenceFileName(const char *filename) const { + if(!filename) + filename = ""; + _PersistenceName = filename; +} + +void ComplexGeoData::Save(Base::Writer &writer) const { + + if(!getElementMapSize()) { + writer.Stream() << writer.ind() << "\n"; + return; + } + + // Store some dummy map entry to trigger recompute in older version. + writer.Stream() << writer.ind() + << "" + << "" + << "\n"; + + // New layout of element map, so we use new xml tag, ElementMap2 + writer.Stream() << writer.ind() << "\n"; + return; + } + writer.Stream() << " count=\"" << _elementMap->size() << "\">\n"; + _elementMap->save(writer.beginCharStream(Base::CharStreamFormat::Raw) << '\n'); + writer.endCharStream() << '\n'; + writer.Stream() << writer.ind() << "\n" ; +} + +void ComplexGeoData::Restore(Base::XMLReader &reader) { + resetElementMap(); + + reader.readElement("ElementMap"); + bool newtag = false; + if (reader.hasAttribute("new") && reader.getAttributeAsInteger("new") > 0) { + reader.readEndElement("ElementMap"); + reader.readElement("ElementMap2"); + newtag = true; + } + + const char *file = ""; + if (reader.hasAttribute("file")) { + reader.getAttribute("file"); + } + if(*file) { + reader.addFile(file,this); + return; + } + + std::size_t count = 0; + if (reader.hasAttribute("count")) { + reader.getAttributeAsUnsigned("count"); + } + if(!count) + return; + + if (newtag) { + resetElementMap(std::make_shared()); + _elementMap = _elementMap->restore(Hasher, reader.beginCharStream(Base::CharStreamFormat::Raw)); + reader.endCharStream(); + reader.readEndElement("ElementMap2"); + return; + } + + if(reader.FileVersion>1) { + restoreStream(reader.beginCharStream(Base::CharStreamFormat::Raw), count); + reader.endCharStream(); + return; + } + + size_t invalid_count = 0; + bool warned = false; + + const auto & types = getElementTypes(); + + for(size_t i=0;i iss(attr, std::strlen(attr)); + long id; + while((iss >> id)) { + if (id == 0) + continue; + auto sid = Hasher->getID(id); + if(!sid) + ++invalid_count; + else + sids.push_back(sid); + char sep; + iss >> sep; + } + } + } + _elementMap->setElementName(IndexedName(reader.getAttribute("value"), types), + MappedName(reader.getAttribute("key")), + Tag, + &sids); + } + if(invalid_count) + FC_ERR("Found " << invalid_count << " invalid string id"); + reader.readEndElement("ElementMap"); +} + +void ComplexGeoData::restoreStream(std::istream &s, std::size_t count) { + resetElementMap(); + + size_t invalid_count = 0; + std::string key,value,sid; + bool warned = false; + + const auto & types = getElementTypes(); + try { + for(size_t i=0;i> value >> key >> scount)) + FC_THROWM(Base::RuntimeError, + "Failed to restore element map " << _PersistenceName); + sids.reserve(scount); + for(std::size_t j=0;j> id)) + FC_THROWM(Base::RuntimeError, + "Failed to restore element map " << _PersistenceName); + if (Hasher) { + auto sid = Hasher->getID(id); + if(!sid) + ++invalid_count; + else + sids.push_back(sid); + } + } + if(scount && !Hasher) { + sids.clear(); + if(!warned) { + warned = true; + FC_ERR("missing hasher"); + } + } + _elementMap->setElementName(IndexedName(value.c_str(), types), MappedName(key), Tag, &sids); + } + } catch (Base::Exception &e) { + e.ReportException(); + _restoreFailed = true; + _elementMap.reset(); + } + if(invalid_count) + FC_ERR("Found " << invalid_count << " invalid string id"); +} + +void ComplexGeoData::SaveDocFile(Base::Writer &writer) const { + flushElementMap(); + if (_elementMap) { + writer.Stream() << "BeginElementMap v1\n"; + _elementMap->save(writer.Stream()); + } +} + +void ComplexGeoData::RestoreDocFile(Base::Reader &reader) { + std::string marker, ver; + reader >> marker; + if (boost::equals(marker, "BeginElementMap")) { + resetElementMap(); + reader >> ver; + if (ver != "v1") + FC_WARN("Unknown element map format"); + else { + resetElementMap(std::make_shared()); + _elementMap = _elementMap->restore(Hasher, reader); + return; + } + } + std::size_t count = atoi(marker.c_str()); + restoreStream(reader,count); +} + +unsigned int ComplexGeoData::getMemSize(void) const { + flushElementMap(); + if(_elementMap) + return _elementMap->size()*10; + return 0; +} + +void ComplexGeoData::beforeSave() const +{ + flushElementMap(); + if (this->_elementMap) + this->_elementMap->beforeSave(Hasher); +} + + // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic) diff --git a/src/App/ComplexGeoData.h b/src/App/ComplexGeoData.h index 52cbb29580..1706551eed 100644 --- a/src/App/ComplexGeoData.h +++ b/src/App/ComplexGeoData.h @@ -280,6 +280,19 @@ public: virtual void flushElementMap() const; //@} + /** @name Save/restore */ + //@{ + void Save (Base::Writer &writer) const; + void Restore(Base::XMLReader &reader); + void SaveDocFile(Base::Writer &writer) const; + void RestoreDocFile(Base::Reader &reader); + unsigned int getMemSize (void) const; + void setPersistenceFileName(const char *name) const; + virtual void beforeSave() const; + bool isRestoreFailed() const { return _restoreFailed; } + void resetRestoreFailure() const { _restoreFailed = true; } + //@} + protected: /// from local to outside @@ -347,6 +360,8 @@ public: protected: + void restoreStream(std::istream &s, std::size_t count); + /// from local to outside inline Base::Vector3d transformToOutside(const Base::Vector3f& vec) const { @@ -370,6 +385,10 @@ protected: private: ElementMapPtr _elementMap; + +protected: + mutable std::string _PersistenceName; + mutable bool _restoreFailed = false; }; } //namespace App From cd1b85500cde9417a696b1677bf27d0cc70fa520 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Sat, 4 Nov 2023 11:07:22 -0500 Subject: [PATCH 2/5] App/Toponaming: ComplexGeoData clang-tidy cleanup --- src/App/ComplexGeoData.cpp | 323 ++++++++++++++++++++----------------- src/App/ComplexGeoData.h | 14 +- 2 files changed, 185 insertions(+), 152 deletions(-) diff --git a/src/App/ComplexGeoData.cpp b/src/App/ComplexGeoData.cpp index d805daaa11..7c9d3b07e6 100644 --- a/src/App/ComplexGeoData.cpp +++ b/src/App/ComplexGeoData.cpp @@ -24,10 +24,10 @@ ***************************************************************************/ -#include "PreCompiled.h"// NOLINT +#include "PreCompiled.h" // NOLINT #ifndef _PreComp_ -# include +#include #endif #include @@ -48,10 +48,10 @@ using namespace Data; -TYPESYSTEM_SOURCE_ABSTRACT(Data::Segment , Base::BaseClass)// NOLINT -TYPESYSTEM_SOURCE_ABSTRACT(Data::ComplexGeoData , Base::Persistence)// NOLINT +TYPESYSTEM_SOURCE_ABSTRACT(Data::Segment, Base::BaseClass) // NOLINT +TYPESYSTEM_SOURCE_ABSTRACT(Data::ComplexGeoData, Base::Persistence) // NOLINT -FC_LOG_LEVEL_INIT("ComplexGeoData", true,true)// NOLINT +FC_LOG_LEVEL_INIT("ComplexGeoData", true, true) // NOLINT namespace bio = boost::iostreams; using namespace Data; @@ -78,7 +78,7 @@ std::pair ComplexGeoData::getTypeAndIndex(const char Data::Segment* ComplexGeoData::getSubElementByName(const char* name) const { auto type = getTypeAndIndex(name); - return getSubElement(type.first.c_str(),type.second); + return getSubElement(type.first.c_str(), type.second); } void ComplexGeoData::applyTransform(const Base::Matrix4D& rclTrf) @@ -109,10 +109,7 @@ Base::Placement ComplexGeoData::getPlacement() const { Base::Matrix4D mat = getTransform(); - return {Base::Vector3d(mat[0][3], - mat[1][3], - mat[2][3]), - Base::Rotation(mat)}; + return {Base::Vector3d(mat[0][3], mat[1][3], mat[2][3]), Base::Rotation(mat)}; } double ComplexGeoData::getAccuracy() const @@ -121,8 +118,8 @@ double ComplexGeoData::getAccuracy() const } void ComplexGeoData::getLinesFromSubElement(const Segment* segment, - std::vector &Points, - std::vector &lines) const + std::vector& Points, + std::vector& lines) const { (void)segment; (void)Points; @@ -130,9 +127,9 @@ void ComplexGeoData::getLinesFromSubElement(const Segment* segment, } void ComplexGeoData::getFacesFromSubElement(const Segment* segment, - std::vector &Points, - std::vector &PointNormals, - std::vector &faces) const + std::vector& Points, + std::vector& PointNormals, + std::vector& faces) const { (void)segment; (void)Points; @@ -148,9 +145,10 @@ Base::Vector3d ComplexGeoData::getPointFromLineIntersection(const Base::Vector3f return Base::Vector3d(); } -void ComplexGeoData::getPoints(std::vector &Points, - std::vector &Normals, - double Accuracy, uint16_t flags) const +void ComplexGeoData::getPoints(std::vector& Points, + std::vector& Normals, + double Accuracy, + uint16_t flags) const { (void)Points; (void)Normals; @@ -158,9 +156,10 @@ void ComplexGeoData::getPoints(std::vector &Points, (void)flags; } -void ComplexGeoData::getLines(std::vector &Points, - std::vector &lines, - double Accuracy, uint16_t flags) const +void ComplexGeoData::getLines(std::vector& Points, + std::vector& lines, + double Accuracy, + uint16_t flags) const { (void)Points; (void)lines; @@ -168,9 +167,10 @@ void ComplexGeoData::getLines(std::vector &Points, (void)flags; } -void ComplexGeoData::getFaces(std::vector &Points, - std::vector &faces, - double Accuracy, uint16_t flags) const +void ComplexGeoData::getFaces(std::vector& Points, + std::vector& faces, + double Accuracy, + uint16_t flags) const { (void)Points; (void)faces; @@ -184,27 +184,30 @@ bool ComplexGeoData::getCenterOfGravity(Base::Vector3d& unused) const return false; } -size_t ComplexGeoData::getElementMapSize(bool flush) const { +size_t ComplexGeoData::getElementMapSize(bool flush) const +{ if (flush) { flushElementMap(); #ifdef _FC_MEM_TRACE - FC_MSG("memory size " << (_MemSize/1024/1024) << "MB, " << (_MemMaxSize/1024/1024)); - for (auto &unit : _MemUnits) - FC_MSG("unit " << unit.first << ": " << unit.second.count << ", " << unit.second.maxcount); + FC_MSG("memory size " << (_MemSize / 1024 / 1024) << "MB, " << (_MemMaxSize / 1024 / 1024)); + for (auto& unit : _MemUnits) { + FC_MSG("unit " << unit.first << ": " << unit.second.count << ", " + << unit.second.maxcount); + } #endif } - return _elementMap ? _elementMap->size():0; + return _elementMap ? _elementMap->size() : 0; } -MappedName ComplexGeoData::getMappedName(const IndexedName & element, +MappedName ComplexGeoData::getMappedName(const IndexedName& element, bool allowUnmapped, - ElementIDRefs *sid) const + ElementIDRefs* sid) const { if (!element) { return {}; } flushElementMap(); - if(!_elementMap) { + if (!_elementMap) { if (allowUnmapped) { return MappedName(element); } @@ -218,8 +221,7 @@ MappedName ComplexGeoData::getMappedName(const IndexedName & element, return name; } -IndexedName ComplexGeoData::getIndexedName(const MappedName & name, - ElementIDRefs *sid) const +IndexedName ComplexGeoData::getIndexedName(const MappedName& name, ElementIDRefs* sid) const { flushElementMap(); if (!name) { @@ -233,25 +235,23 @@ IndexedName ComplexGeoData::getIndexedName(const MappedName & name, } Data::MappedElement -ComplexGeoData::getElementName(const char *name, - ElementIDRefs *sid, - bool copy) const +ComplexGeoData::getElementName(const char* name, ElementIDRefs* sid, bool copy) const { IndexedName element(name, getElementTypes()); if (element) { return {getMappedName(element, false, sid), element}; } - const char * mapped = isMappedElement(name); + const char* mapped = isMappedElement(name); if (mapped) { name = mapped; } MappedElement result; // Strip out the trailing '.XXXX' if any - const char *dot = strchr(name,'.'); - if(dot) { - result.name = MappedName(name, dot - name); + const char* dot = strchr(name, '.'); + if (dot) { + result.name = MappedName(name, static_cast(dot - name)); } else if (copy) { result.name = name; @@ -263,10 +263,11 @@ ComplexGeoData::getElementName(const char *name, return result; } -std::vector > -ComplexGeoData::getElementMappedNames(const IndexedName & element, bool needUnmapped) const { +std::vector> +ComplexGeoData::getElementMappedNames(const IndexedName& element, bool needUnmapped) const +{ flushElementMap(); - if(_elementMap) { + if (_elementMap) { auto res = _elementMap->findAll(element); if (!res.empty()) { return res; @@ -279,9 +280,10 @@ ComplexGeoData::getElementMappedNames(const IndexedName & element, bool needUnma return {std::make_pair(MappedName(element), ElementIDRefs())}; } -std::vector ComplexGeoData::getElementMap() const { +std::vector ComplexGeoData::getElementMap() const +{ flushElementMap(); - if(!_elementMap) { + if (!_elementMap) { return {}; } return _elementMap->getAll(); @@ -296,40 +298,40 @@ ElementMapPtr ComplexGeoData::elementMap(bool flush) const } void ComplexGeoData::flushElementMap() const -{ -} +{} -void ComplexGeoData::setElementMap(const std::vector &map) { - _elementMap = std::make_shared(); // Get rid of the old one, if any, but make - // sure the memory exists for the new data. - for(auto &element : map) { +void ComplexGeoData::setElementMap(const std::vector& map) +{ + _elementMap = std::make_shared(); // Get rid of the old one, if any, but make + // sure the memory exists for the new data. + for (auto& element : map) { _elementMap->setElementName(element.index, element.name, Tag); } } -char ComplexGeoData::elementType(const Data::MappedName &name) const +char ComplexGeoData::elementType(const Data::MappedName& name) const { - if(!name) { + if (!name) { return 0; } auto indexedName = getIndexedName(name); if (indexedName) { return elementType(indexedName); } - char element_type=0; - if (name.findTagInElementName(nullptr,nullptr,nullptr,&element_type) < 0) { + char element_type = 0; + if (name.findTagInElementName(nullptr, nullptr, nullptr, &element_type) < 0) { return elementType(name.toIndexedName()); } return element_type; } -char ComplexGeoData::elementType(const Data::IndexedName &element) const +char ComplexGeoData::elementType(const Data::IndexedName& element) const { - if(!element) { + if (!element) { return 0; } - for(auto &type : getElementTypes()) { - if(boost::equals(element.getType(), type)) { + for (auto& type : getElementTypes()) { + if (boost::equals(element.getType(), type)) { return type[0]; } } @@ -348,27 +350,28 @@ char ComplexGeoData::elementType(const Data::IndexedName &element) const // c) Try to get the elementType based on the MappedName. Return it if found // 3) Check to make sure the discovered type is in the list of types, and return its first // character if so. -char ComplexGeoData::elementType(const char *name) const { - if(!name) { +char ComplexGeoData::elementType(const char* name) const +{ + if (!name) { return 0; } - const char *type = nullptr; + const char* type = nullptr; IndexedName element(name, getElementTypes()); if (element) { type = element.getType(); } else { - const char * mapped = isMappedElement(name); + const char* mapped = isMappedElement(name); if (mapped) { name = mapped; } MappedName mappedName; - const char *dot = strchr(name,'.'); - if(dot) { - mappedName = MappedName(name, dot-name); - type = dot+1; + const char* dot = strchr(name, '.'); + if (dot) { + mappedName = MappedName(name, static_cast(dot - name)); + type = dot + 1; } else { mappedName = MappedName::fromRawData(name); @@ -379,9 +382,9 @@ char ComplexGeoData::elementType(const char *name) const { } } - if(type && type[0]) { - for(auto &elementTypes : getElementTypes()) { - if(boost::starts_with(type, elementTypes)) { + if (type && (type[0] != 0)) { + for (auto& elementTypes : getElementTypes()) { + if (boost::starts_with(type, elementTypes)) { return type[0]; } } @@ -389,76 +392,80 @@ char ComplexGeoData::elementType(const char *name) const { return 0; } -void ComplexGeoData::setPersistenceFileName(const char *filename) const { - if(!filename) +void ComplexGeoData::setPersistenceFileName(const char* filename) const +{ + if (!filename) { filename = ""; - _PersistenceName = filename; + } + _persistenceName = filename; } -void ComplexGeoData::Save(Base::Writer &writer) const { +void ComplexGeoData::Save(Base::Writer& writer) const +{ - if(!getElementMapSize()) { + if (getElementMapSize() == 0U) { writer.Stream() << writer.ind() << "\n"; return; } // Store some dummy map entry to trigger recompute in older version. - writer.Stream() << writer.ind() - << "" - << "" + writer.Stream() << writer.ind() << R"()" + << R"()" << "\n"; // New layout of element map, so we use new xml tag, ElementMap2 writer.Stream() << writer.ind() << "\n"; return; } writer.Stream() << " count=\"" << _elementMap->size() << "\">\n"; _elementMap->save(writer.beginCharStream(Base::CharStreamFormat::Raw) << '\n'); writer.endCharStream() << '\n'; - writer.Stream() << writer.ind() << "\n" ; + writer.Stream() << writer.ind() << "\n"; } -void ComplexGeoData::Restore(Base::XMLReader &reader) { +void ComplexGeoData::Restore(Base::XMLReader& reader) +{ resetElementMap(); reader.readElement("ElementMap"); - bool newtag = false; + bool newTag = false; if (reader.hasAttribute("new") && reader.getAttributeAsInteger("new") > 0) { reader.readEndElement("ElementMap"); reader.readElement("ElementMap2"); - newtag = true; + newTag = true; } - const char *file = ""; + const char* file = ""; if (reader.hasAttribute("file")) { - reader.getAttribute("file"); + reader.getAttribute("file"); } - if(*file) { - reader.addFile(file,this); + if (*file != 0) { + reader.addFile(file, this); return; } std::size_t count = 0; if (reader.hasAttribute("count")) { - reader.getAttributeAsUnsigned("count"); + count = reader.getAttributeAsUnsigned("count"); } - if(!count) + if (count == 0) { return; + } - if (newtag) { + if (newTag) { resetElementMap(std::make_shared()); - _elementMap = _elementMap->restore(Hasher, reader.beginCharStream(Base::CharStreamFormat::Raw)); + _elementMap = + _elementMap->restore(Hasher, reader.beginCharStream(Base::CharStreamFormat::Raw)); reader.endCharStream(); reader.readEndElement("ElementMap2"); return; } - if(reader.FileVersion>1) { + if (reader.FileVersion > 1) { restoreStream(reader.beginCharStream(Base::CharStreamFormat::Raw), count); reader.endCharStream(); return; @@ -467,30 +474,34 @@ void ComplexGeoData::Restore(Base::XMLReader &reader) { size_t invalid_count = 0; bool warned = false; - const auto & types = getElementTypes(); + const auto& types = getElementTypes(); - for(size_t i=0;i iss(attr, std::strlen(attr)); - long id; - while((iss >> id)) { - if (id == 0) + long id {}; + while ((iss >> id)) { + if (id == 0) { continue; + } auto sid = Hasher->getID(id); - if(!sid) + if (!sid) { ++invalid_count; - else + } + else { sids.push_back(sid); - char sep; + } + char sep {}; iss >> sep; } } @@ -500,59 +511,74 @@ void ComplexGeoData::Restore(Base::XMLReader &reader) { Tag, &sids); } - if(invalid_count) - FC_ERR("Found " << invalid_count << " invalid string id"); + if (invalid_count != 0) { + FC_ERR("Found " << invalid_count << " invalid string id"); // NOLINT + } reader.readEndElement("ElementMap"); } -void ComplexGeoData::restoreStream(std::istream &s, std::size_t count) { +void ComplexGeoData::restoreStream(std::istream& stream, std::size_t count) +{ resetElementMap(); size_t invalid_count = 0; - std::string key,value,sid; + std::string key; + std::string value; + std::string sid; bool warned = false; - const auto & types = getElementTypes(); + const auto& types = getElementTypes(); try { - for(size_t i=0;i> value >> key >> scount)) - FC_THROWM(Base::RuntimeError, - "Failed to restore element map " << _PersistenceName); - sids.reserve(scount); - for(std::size_t j=0;j> id)) + std::size_t scount = 0; + if (!(stream >> value >> key >> scount)) { + // NOLINTNEXTLINE + FC_THROWM(Base::RuntimeError, "Failed to restore element map " << _persistenceName); + } + sids.reserve(static_cast(scount)); + for (std::size_t j = 0; j < scount; ++j) { + long id = 0; + if (!(stream >> id)) { + // NOLINTNEXTLINE FC_THROWM(Base::RuntimeError, - "Failed to restore element map " << _PersistenceName); + "Failed to restore element map " << _persistenceName); + } if (Hasher) { - auto sid = Hasher->getID(id); - if(!sid) + auto hasherSID = Hasher->getID(id); + if (!hasherSID) { ++invalid_count; - else - sids.push_back(sid); + } + else { + sids.push_back(hasherSID); + } } } - if(scount && !Hasher) { + if (scount != 0 && !Hasher) { sids.clear(); - if(!warned) { + if (!warned) { warned = true; - FC_ERR("missing hasher"); + FC_ERR("missing hasher"); // NOLINT } } - _elementMap->setElementName(IndexedName(value.c_str(), types), MappedName(key), Tag, &sids); + _elementMap->setElementName(IndexedName(value.c_str(), types), + MappedName(key), + Tag, + &sids); } - } catch (Base::Exception &e) { + } + catch (Base::Exception& e) { e.ReportException(); _restoreFailed = true; _elementMap.reset(); } - if(invalid_count) - FC_ERR("Found " << invalid_count << " invalid string id"); + if (invalid_count != 0) { + FC_ERR("Found " << invalid_count << " invalid string id"); // NOLINT + } } -void ComplexGeoData::SaveDocFile(Base::Writer &writer) const { +void ComplexGeoData::SaveDocFile(Base::Writer& writer) const +{ flushElementMap(); if (_elementMap) { writer.Stream() << "BeginElementMap v1\n"; @@ -560,14 +586,17 @@ void ComplexGeoData::SaveDocFile(Base::Writer &writer) const { } } -void ComplexGeoData::RestoreDocFile(Base::Reader &reader) { - std::string marker, ver; +void ComplexGeoData::RestoreDocFile(Base::Reader& reader) +{ + std::string marker; + std::string ver; reader >> marker; if (boost::equals(marker, "BeginElementMap")) { resetElementMap(); reader >> ver; - if (ver != "v1") - FC_WARN("Unknown element map format"); + if (ver != "v1") { + FC_WARN("Unknown element map format"); // NOLINT + } else { resetElementMap(std::make_shared()); _elementMap = _elementMap->restore(Hasher, reader); @@ -575,21 +604,25 @@ void ComplexGeoData::RestoreDocFile(Base::Reader &reader) { } } std::size_t count = atoi(marker.c_str()); - restoreStream(reader,count); + restoreStream(reader, count); } -unsigned int ComplexGeoData::getMemSize(void) const { +unsigned int ComplexGeoData::getMemSize() const +{ flushElementMap(); - if(_elementMap) - return _elementMap->size()*10; + if (_elementMap) { + static const int multiplier {10}; + return _elementMap->size() * multiplier; + } return 0; } void ComplexGeoData::beforeSave() const { flushElementMap(); - if (this->_elementMap) + if (this->_elementMap) { this->_elementMap->beforeSave(Hasher); + } } diff --git a/src/App/ComplexGeoData.h b/src/App/ComplexGeoData.h index 1706551eed..2130d5cbd6 100644 --- a/src/App/ComplexGeoData.h +++ b/src/App/ComplexGeoData.h @@ -282,11 +282,11 @@ public: /** @name Save/restore */ //@{ - void Save (Base::Writer &writer) const; - void Restore(Base::XMLReader &reader); - void SaveDocFile(Base::Writer &writer) const; - void RestoreDocFile(Base::Reader &reader); - unsigned int getMemSize (void) const; + void Save (Base::Writer &writer) const override; + void Restore(Base::XMLReader &reader) override; + void SaveDocFile(Base::Writer &writer) const override; + void RestoreDocFile(Base::Reader &reader) override; + unsigned int getMemSize () const override; void setPersistenceFileName(const char *name) const; virtual void beforeSave() const; bool isRestoreFailed() const { return _restoreFailed; } @@ -360,7 +360,7 @@ public: protected: - void restoreStream(std::istream &s, std::size_t count); + void restoreStream(std::istream & stream, std::size_t count); /// from local to outside inline Base::Vector3d transformToOutside(const Base::Vector3f& vec) const @@ -387,7 +387,7 @@ private: ElementMapPtr _elementMap; protected: - mutable std::string _PersistenceName; + mutable std::string _persistenceName; mutable bool _restoreFailed = false; }; From 7db8cb373be6e10b6b98f5822f5f5354276d2fa5 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Sat, 4 Nov 2023 11:07:52 -0500 Subject: [PATCH 3/5] App/Toponaming: Add TNP code to PropertyComplexGeoData --- src/App/PropertyGeo.cpp | 17 +++++++++++++++++ src/App/PropertyGeo.h | 2 ++ 2 files changed, 19 insertions(+) diff --git a/src/App/PropertyGeo.cpp b/src/App/PropertyGeo.cpp index a72364f265..220aba8e9a 100644 --- a/src/App/PropertyGeo.cpp +++ b/src/App/PropertyGeo.cpp @@ -36,6 +36,8 @@ #include #include +#include "ComplexGeoData.h" +#include "Document.h" #include "PropertyGeo.h" #include "Placement.h" #include "ObjectIdentifier.h" @@ -1241,3 +1243,18 @@ TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyComplexGeoData , App::PropertyGeometry) PropertyComplexGeoData::PropertyComplexGeoData() = default; PropertyComplexGeoData::~PropertyComplexGeoData() = default; + +void PropertyComplexGeoData::afterRestore() +{ + auto data = getComplexData(); + if (data && data->isRestoreFailed()) { + data->resetRestoreFailure(); + auto owner = Base::freecad_dynamic_cast(getContainer()); + if (owner && + owner->getDocument() && + !owner->getDocument()->testStatus(App::Document::PartialDoc)) { + owner->getDocument()->addRecomputeObject(owner); + } + } + PropertyGeometry::afterRestore(); +} \ No newline at end of file diff --git a/src/App/PropertyGeo.h b/src/App/PropertyGeo.h index 829e251f98..c55339e63a 100644 --- a/src/App/PropertyGeo.h +++ b/src/App/PropertyGeo.h @@ -541,6 +541,8 @@ public: virtual const Data::ComplexGeoData* getComplexData() const = 0; Base::BoundBox3d getBoundingBox() const override = 0; //@} + + void afterRestore() override; }; } // namespace App From e2f4ec90a34eaf19cffa939195399c495cdceee6 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Sat, 4 Nov 2023 11:47:11 -0500 Subject: [PATCH 4/5] App/Toponaming: Minor refactor if read method --- src/App/ComplexGeoData.cpp | 16 ++++++++++------ src/App/ComplexGeoData.h | 1 + 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/App/ComplexGeoData.cpp b/src/App/ComplexGeoData.cpp index 7c9d3b07e6..32ece65915 100644 --- a/src/App/ComplexGeoData.cpp +++ b/src/App/ComplexGeoData.cpp @@ -470,7 +470,12 @@ void ComplexGeoData::Restore(Base::XMLReader& reader) reader.endCharStream(); return; } + readElements(reader, count); + reader.readEndElement("ElementMap"); +} +void ComplexGeoData::readElements(Base::XMLReader& reader, size_t count) +{ size_t invalid_count = 0; bool warned = false; @@ -514,7 +519,6 @@ void ComplexGeoData::Restore(Base::XMLReader& reader) if (invalid_count != 0) { FC_ERR("Found " << invalid_count << " invalid string id"); // NOLINT } - reader.readEndElement("ElementMap"); } void ComplexGeoData::restoreStream(std::istream& stream, std::size_t count) @@ -531,13 +535,13 @@ void ComplexGeoData::restoreStream(std::istream& stream, std::size_t count) try { for (size_t i = 0; i < count; ++i) { ElementIDRefs sids; - std::size_t scount = 0; - if (!(stream >> value >> key >> scount)) { + std::size_t sCount = 0; + if (!(stream >> value >> key >> sCount)) { // NOLINTNEXTLINE FC_THROWM(Base::RuntimeError, "Failed to restore element map " << _persistenceName); } - sids.reserve(static_cast(scount)); - for (std::size_t j = 0; j < scount; ++j) { + sids.reserve(static_cast(sCount)); + for (std::size_t j = 0; j < sCount; ++j) { long id = 0; if (!(stream >> id)) { // NOLINTNEXTLINE @@ -554,7 +558,7 @@ void ComplexGeoData::restoreStream(std::istream& stream, std::size_t count) } } } - if (scount != 0 && !Hasher) { + if (sCount != 0 && !Hasher) { sids.clear(); if (!warned) { warned = true; diff --git a/src/App/ComplexGeoData.h b/src/App/ComplexGeoData.h index 2130d5cbd6..8364dde4cd 100644 --- a/src/App/ComplexGeoData.h +++ b/src/App/ComplexGeoData.h @@ -361,6 +361,7 @@ public: protected: void restoreStream(std::istream & stream, std::size_t count); + void readElements(Base::XMLReader& reader, size_t count); /// from local to outside inline Base::Vector3d transformToOutside(const Base::Vector3f& vec) const From 2067470b2e5be7381bc2fef6d7ddbd89462ca7bd Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Wed, 8 Nov 2023 17:11:32 -0600 Subject: [PATCH 5/5] App/Toponaming: Add basic tests for CGD serialization --- tests/src/App/ComplexGeoData.cpp | 89 ++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 15 deletions(-) diff --git a/tests/src/App/ComplexGeoData.cpp b/tests/src/App/ComplexGeoData.cpp index 0f962c4d14..6eab5175d9 100644 --- a/tests/src/App/ComplexGeoData.cpp +++ b/tests/src/App/ComplexGeoData.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -32,21 +33,6 @@ public: return nullptr; } - unsigned int getMemSize() const override - { - return 0; - } - - void Save(Base::Writer& writer) const override - { - (void)writer; - } - - void Restore(Base::XMLReader& reader) override - { - (void)reader; - } - void setTransform(const Base::Matrix4D& rclTrf) override { (void)rclTrf; @@ -410,4 +396,77 @@ TEST_F(ComplexGeoDataTest, flushElementMap) // NOLINT // Does nothing in the base class } +TEST_F(ComplexGeoDataTest, saveWithNoElementMap) // NOLINT +{ + // Arrange + Base::StringWriter writer; + cgd().resetElementMap(); + + // Act + cgd().Save(writer); + + // Assert - With no element map, that element of the XML is empty + EXPECT_TRUE(writer.getString().find("") != std::string::npos); +} + +TEST_F(ComplexGeoDataTest, saveWithElementMap) +{ + // Arrange + Base::StringWriter writer; + auto map = createMappedName("SomeElement"); + + // Act + cgd().Save(writer); + + // Assert + EXPECT_TRUE(writer.getString().find("