diff --git a/api/c/indigo-renderer/src/indigo_render2d.cpp b/api/c/indigo-renderer/src/indigo_render2d.cpp index a684e285b5..39ef2468d5 100644 --- a/api/c/indigo-renderer/src/indigo_render2d.cpp +++ b/api/c/indigo-renderer/src/indigo_render2d.cpp @@ -523,7 +523,10 @@ CEXPORT int indigoRenderGrid(int objects, int* refAtoms, int nColumns, int outpu rp.mols.add(new Molecule()); Array& title = rp.titles.push(); if (objs[i]->getProperties().contains(rp.cnvOpt.titleProp.ptr())) - title.copy(objs[i]->getProperties().valueBuf(rp.cnvOpt.titleProp.ptr())); + { + const auto& val = objs[i]->getProperties().valueBuf(rp.cnvOpt.titleProp.ptr()); + title.copy(val.c_str(), val.size() + 1); + } if (rp.rOpt.mode == DINGO_MODE::MODE_CDXML) { @@ -560,7 +563,10 @@ CEXPORT int indigoRenderGrid(int objects, int* refAtoms, int nColumns, int outpu rp.rxns.add(new Reaction()); Array& title = rp.titles.push(); if (objs[i]->getProperties().contains(rp.cnvOpt.titleProp.ptr())) - title.copy(objs[i]->getProperties().valueBuf(rp.cnvOpt.titleProp.ptr())); + { + const auto& val = objs[i]->getProperties().valueBuf(rp.cnvOpt.titleProp.ptr()); + title.copy(val.c_str(), val.size() + 1); + } rp.rxns.top()->clone(objs[i]->getBaseReaction(), 0, 0, 0); rp.rmode = RENDER_RXN; diff --git a/core/indigo-core/common/base_cpp/properties_map.cpp b/core/indigo-core/common/base_cpp/properties_map.cpp index b64ae52679..f3006e69c8 100644 --- a/core/indigo-core/common/base_cpp/properties_map.cpp +++ b/core/indigo-core/common/base_cpp/properties_map.cpp @@ -17,13 +17,15 @@ ***************************************************************************/ #include +#include + #include "base_cpp/properties_map.h" using namespace indigo; IMPL_ERROR(PropertiesMap, "properties map"); -void PropertiesMap::copy(RedBlackStringObjMap>& other) +void PropertiesMap::copy(const RedBlackStringObjMap>& other) { clear(); for (int i = other.begin(); i != other.end(); i = other.next(i)) @@ -53,45 +55,34 @@ void PropertiesMap::insert(const char* key, const std::string& value) void PropertiesMap::insert(const char* key, const char* value) { - if (_properties.find(key)) + const auto it = _properties.find(key); + if (it != _properties.end()) { - auto& val = _properties.at(key); if (value != 0) - val.readString(value, true); + _properties.at(key) = value; } else { - auto& name = _propertyNames.push(); - name.readString(key, true); - int k = _properties.insert(key); - if (value != 0) - _properties.value(k).readString(value, true); + auto newIt = _properties.emplace(key, value).first; + _propertiesOrdered.push_back(std::move(newIt)); } } -Array& PropertiesMap::insert(const char* key) +std::string& PropertiesMap::insert(const char* key) { - insert(key, 0); + insert(key, ""); return valueBuf(key); } -const char* PropertiesMap::key(int i) +const char* PropertiesMap::key(int i) const { - return _propertyNames.at(i).ptr(); + return _propertiesOrdered.at(i)->first.c_str(); } -const char* PropertiesMap::value(int i) +const char* PropertiesMap::value(int i) const { - auto& buf = valueBuf(_propertyNames.at(i).ptr()); - if (buf.size() > 0) - { - return buf.ptr(); - } - else - { - return ""; - } + return _propertiesOrdered.at(i)->second.c_str(); } -Array& PropertiesMap::valueBuf(const char* key) +std::string& PropertiesMap::valueBuf(const char* key) { return _properties.at(key); } @@ -99,7 +90,7 @@ Array& PropertiesMap::valueBuf(const char* key) void PropertiesMap::clear() { _properties.clear(); - _propertyNames.clear(); + _propertiesOrdered.clear(); } bool PropertiesMap::is_empty() @@ -109,31 +100,24 @@ bool PropertiesMap::is_empty() bool PropertiesMap::contains(const char* key) const { - return _properties.find(key); + return _properties.find(key) != _properties.end(); } const char* PropertiesMap::at(const char* key) const { - return _properties.at(key).ptr(); + return _properties.at(key).c_str(); } void PropertiesMap::remove(const char* key) { - if (_properties.find(key)) + const auto it = _properties.find(key); + if (it != _properties.end()) { - _properties.remove(key); - int to_remove = -1; - for (auto i = 0; i < _propertyNames.size(); i++) + _properties.erase(it); + const auto orderedIt = std::find(_propertiesOrdered.begin(), _propertiesOrdered.end(), it); + if (orderedIt != _propertiesOrdered.end()) { - if (strcmp(_propertyNames.at(i).ptr(), key) == 0) - { - to_remove = i; - break; - } - } - if (to_remove >= 0) - { - _propertyNames.remove(to_remove); + _propertiesOrdered.erase(orderedIt); } else { @@ -168,5 +152,5 @@ int PropertiesMap::PrAuto::next(int k) } PropertiesMap::PrIter PropertiesMap::PrAuto::end() { - return PropertiesMap::PrIter(_owner, _owner._propertyNames.size()); -} \ No newline at end of file + return PropertiesMap::PrIter(_owner, static_cast(_owner._propertiesOrdered.size())); +} diff --git a/core/indigo-core/common/base_cpp/properties_map.h b/core/indigo-core/common/base_cpp/properties_map.h index 9953ed7e76..90b55b2f84 100644 --- a/core/indigo-core/common/base_cpp/properties_map.h +++ b/core/indigo-core/common/base_cpp/properties_map.h @@ -24,11 +24,12 @@ #pragma warning(disable : 4251) #endif -#include "base_cpp/array.h" #include "base_cpp/auto_iter.h" #include "base_cpp/exception.h" -#include "base_cpp/obj_array.h" #include "base_cpp/red_black.h" +#include +#include +#include namespace indigo { @@ -41,23 +42,17 @@ namespace indigo explicit PropertiesMap() { } - ~PropertiesMap() - { - } - // inline RedBlackStringObjMap< Array >& getProperties() { - // return _properties; - // } - void copy(RedBlackStringObjMap>& properties); + + void copy(const RedBlackStringObjMap>& properties); void copy(PropertiesMap&); void merge(PropertiesMap&); void insert(const char* key, const char* value); void insert(const char* key, const std::string& value); + std::string& insert(const char* key); - Array& insert(const char* key); - - const char* key(int); - const char* value(int); - Array& valueBuf(const char* key); + const char* key(int) const; + const char* value(int) const; + std::string& valueBuf(const char* key); bool contains(const char* key) const; const char* at(const char* key) const; @@ -92,9 +87,13 @@ namespace indigo PrAuto elements(); private: + // std::less<...> is used to avoid creation of temp string when searching by const char* index + using StorageType = std::map>; + PropertiesMap(const PropertiesMap&); - RedBlackStringObjMap> _properties; - ObjArray> _propertyNames; + + StorageType _properties; + std::vector _propertiesOrdered; }; } // namespace indigo diff --git a/core/indigo-core/molecule/src/multiple_cdx_loader.cpp b/core/indigo-core/molecule/src/multiple_cdx_loader.cpp index 69c7ac08f9..6936464cff 100644 --- a/core/indigo-core/molecule/src/multiple_cdx_loader.cpp +++ b/core/indigo-core/molecule/src/multiple_cdx_loader.cpp @@ -307,10 +307,10 @@ void MultipleCdxLoader::_getObject(int parent_tag) { auto& propVal = properties.insert(name.ptr()); if (value.size() > 0) - propVal.readString(value.ptr(), true); + propVal = value.ptr(); else if (_latest_text.size() > 0) { - propVal.readString(_latest_text.ptr(), true); + propVal = _latest_text.ptr(); _latest_text.clear(); } } diff --git a/core/indigo-core/molecule/src/rdf_loader.cpp b/core/indigo-core/molecule/src/rdf_loader.cpp index 1f194d05af..62dd6a0217 100644 --- a/core/indigo-core/molecule/src/rdf_loader.cpp +++ b/core/indigo-core/molecule/src/rdf_loader.cpp @@ -164,7 +164,7 @@ void RdfLoader::readNext() /* * Current value for property reading */ - Array* current_datum = 0; + std::string* current_datum = 0; /* * Read properties */ @@ -214,7 +214,9 @@ void RdfLoader::readNext() scanner.skip(6); scanner.skipSpace(); - _readLine(scanner, *current_datum); + Array buffer; + _readLine(scanner, buffer); + *current_datum = buffer.ptr(); continue; } @@ -224,8 +226,8 @@ void RdfLoader::readNext() */ if (_innerBuffer.size() && current_datum && current_datum->size()) { - current_datum->appendString("\n", true); - current_datum->appendString(_innerBuffer.ptr(), true); + (*current_datum) += '\n'; + (*current_datum) += _innerBuffer.ptr(); } } while (_readLine(_getScanner(), _innerBuffer)); @@ -253,30 +255,26 @@ bool RdfLoader::_readIdentifiers(bool from_begin) word.push(0); if (strcmp(word.ptr(), "$MIREG") == 0 || strcmp(word.ptr(), "$RIREG") == 0) { - /* - * Insert new property key - */ - Array& val = properties.insert("internal-regno"); scanner.skipSpace(); - /* - * Insert new property value - */ - scanner.readWord(val, 0); - val.push(0); + + Array buffer; + scanner.readWord(buffer, 0); + buffer.push(0); + + properties.insert("internal-regno", buffer.ptr()); + result = true; } else if (strcmp(word.ptr(), "$MEREG") == 0 || strcmp(word.ptr(), "$REREG") == 0) { - /* - * Insert new property key - */ - Array& val = properties.insert("external-regno"); scanner.skipSpace(); - /* - * Insert new property value - */ - scanner.readWord(val, 0); - val.push(0); + + Array buffer; + scanner.readWord(buffer, 0); + buffer.push(0); + + properties.insert("mexternal-regno", buffer.ptr()); + result = true; } else if (from_begin) diff --git a/core/indigo-core/molecule/src/sdf_loader.cpp b/core/indigo-core/molecule/src/sdf_loader.cpp index 7dc4209465..8675ba1d6f 100644 --- a/core/indigo-core/molecule/src/sdf_loader.cpp +++ b/core/indigo-core/molecule/src/sdf_loader.cpp @@ -192,7 +192,7 @@ void SdfLoader::readNext() auto& propBuf = properties.insert(word.ptr()); // auto& propBuf = properties.valueBuf(word.ptr()); // int idx = properties.findOrInsert(word.ptr()); - propBuf.copy(str); + propBuf = str.ptr(); output.writeStringCR(str.ptr()); if (str.size() > 1) { @@ -205,9 +205,8 @@ void SdfLoader::readNext() output.writeStringCR(str.ptr()); if (str.size() > 1) { - propBuf.pop(); // Remove string end marker (0) - propBuf.push('\n'); - propBuf.appendString(str.ptr(), true); + propBuf += '\n'; + propBuf += str.ptr(); } } while (str.size() > 1); }