Revert "Address the poor performance of the existing unique-name generation (#17944)"
This reverts commit 83202d8ad6.
# Conflicts:
# src/Base/Tools.cpp
# src/Base/Tools.h
This commit is contained in:
committed by
Yorik van Havre
parent
2493c37bac
commit
39402e2083
@@ -645,11 +645,8 @@ void Document::clearDocument()
|
||||
setStatus(Document::PartialDoc, false);
|
||||
|
||||
d->clearRecomputeLog();
|
||||
d->objectLabelCounts.clear();
|
||||
d->objectLabelManager.clear();
|
||||
d->objectArray.clear();
|
||||
d->objectMap.clear();
|
||||
d->objectNameManager.clear();
|
||||
d->objectIdMap.clear();
|
||||
d->lastObjectId = 0;
|
||||
}
|
||||
@@ -2253,59 +2250,6 @@ bool Document::saveToFile(const char* filename) const
|
||||
return true;
|
||||
}
|
||||
|
||||
void Document::registerLabel(const std::string& newLabel)
|
||||
{
|
||||
if (newLabel.empty()) {
|
||||
return;
|
||||
}
|
||||
if (!d->objectLabelManager.containsName(newLabel)) {
|
||||
// First occurrence of label. We make no entry in objectLabelCounts when the count is one.
|
||||
d->objectLabelManager.addExactName(newLabel);
|
||||
}
|
||||
else {
|
||||
auto it = d->objectLabelCounts.find(newLabel);
|
||||
if (it != d->objectLabelCounts.end()) {
|
||||
// There is a count already greater then one, so increment it
|
||||
it->second++;
|
||||
}
|
||||
else {
|
||||
// There is no count entry, which implies one, so register a count of two
|
||||
d->objectLabelCounts.insert(std::pair(newLabel, 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Document::unregisterLabel(const std::string& oldLabel)
|
||||
{
|
||||
if (oldLabel.empty()) {
|
||||
return;
|
||||
}
|
||||
auto it = d->objectLabelCounts.find(oldLabel);
|
||||
if (it == d->objectLabelCounts.end()) {
|
||||
// Missing count implies a count of one, or an unregistered name
|
||||
d->objectLabelManager.removeExactName(oldLabel);
|
||||
return;
|
||||
}
|
||||
if (--it->second == 1) {
|
||||
// Decremented to one, remove the count entry
|
||||
d->objectLabelCounts.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
bool Document::containsLabel(const std::string& label)
|
||||
{
|
||||
return d->objectLabelManager.containsName(label);
|
||||
}
|
||||
|
||||
std::string Document::makeUniqueLabel(const std::string& modelLabel)
|
||||
{
|
||||
if (modelLabel.empty()) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return d->objectLabelManager.makeUniqueName(modelLabel, 3);
|
||||
}
|
||||
|
||||
bool Document::isAnyRestoring()
|
||||
{
|
||||
return globalIsRestoring;
|
||||
@@ -2332,10 +2276,7 @@ void Document::restore(const char* filename,
|
||||
setStatus(Document::PartialDoc, false);
|
||||
|
||||
d->clearRecomputeLog();
|
||||
d->objectLabelCounts.clear();
|
||||
d->objectLabelManager.clear();
|
||||
d->objectArray.clear();
|
||||
d->objectNameManager.clear();
|
||||
d->objectMap.clear();
|
||||
d->objectIdMap.clear();
|
||||
d->lastObjectId = 0;
|
||||
@@ -3644,7 +3585,6 @@ DocumentObject* Document::addObject(const char* sType,
|
||||
|
||||
// insert in the name map
|
||||
d->objectMap[ObjectName] = pcObject;
|
||||
d->objectNameManager.addExactName(ObjectName);
|
||||
// generate object id and add to id map;
|
||||
pcObject->_Id = ++d->lastObjectId;
|
||||
d->objectIdMap[pcObject->_Id] = pcObject;
|
||||
@@ -3653,8 +3593,6 @@ DocumentObject* Document::addObject(const char* sType,
|
||||
pcObject->pcNameInDocument = &(d->objectMap.find(ObjectName)->first);
|
||||
// insert in the vector
|
||||
d->objectArray.push_back(pcObject);
|
||||
// Register the current Label even though it is (probably) about to change
|
||||
registerLabel(pcObject->Label.getStrValue());
|
||||
|
||||
// If we are restoring, don't set the Label object now; it will be restored later. This is to
|
||||
// avoid potential duplicate label conflicts later.
|
||||
@@ -3715,6 +3653,13 @@ Document::addObjects(const char* sType, const std::vector<std::string>& objectNa
|
||||
return objects;
|
||||
}
|
||||
|
||||
// get all existing object names
|
||||
std::vector<std::string> reservedNames;
|
||||
reservedNames.reserve(d->objectMap.size());
|
||||
for (const auto& pos : d->objectMap) {
|
||||
reservedNames.push_back(pos.first);
|
||||
}
|
||||
|
||||
for (auto it = objects.begin(); it != objects.end(); ++it) {
|
||||
auto index = std::distance(objects.begin(), it);
|
||||
App::DocumentObject* pcObject = *it;
|
||||
@@ -3729,19 +3674,29 @@ Document::addObjects(const char* sType, const std::vector<std::string>& objectNa
|
||||
}
|
||||
}
|
||||
|
||||
// get unique name. We don't use getUniqueObjectName because it takes a char* not a std::string
|
||||
// get unique name
|
||||
std::string ObjectName = objectNames[index];
|
||||
if (ObjectName.empty()) {
|
||||
ObjectName = sType;
|
||||
}
|
||||
ObjectName = Base::Tools::getIdentifier(ObjectName);
|
||||
if (d->objectNameManager.containsName(ObjectName)) {
|
||||
ObjectName = d->objectNameManager.makeUniqueName(ObjectName, 3);
|
||||
if (d->objectMap.find(ObjectName) != d->objectMap.end()) {
|
||||
// remove also trailing digits from clean name which is to avoid to create lengthy names
|
||||
// like 'Box001001'
|
||||
if (!testStatus(KeepTrailingDigits)) {
|
||||
std::string::size_type index = ObjectName.find_last_not_of("0123456789");
|
||||
if (index + 1 < ObjectName.size()) {
|
||||
ObjectName = ObjectName.substr(0, index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
ObjectName = Base::Tools::getUniqueName(ObjectName, reservedNames, 3);
|
||||
}
|
||||
|
||||
reservedNames.push_back(ObjectName);
|
||||
|
||||
// insert in the name map
|
||||
d->objectMap[ObjectName] = pcObject;
|
||||
d->objectNameManager.addExactName(ObjectName);
|
||||
// generate object id and add to id map;
|
||||
pcObject->_Id = ++d->lastObjectId;
|
||||
d->objectIdMap[pcObject->_Id] = pcObject;
|
||||
@@ -3750,8 +3705,6 @@ Document::addObjects(const char* sType, const std::vector<std::string>& objectNa
|
||||
pcObject->pcNameInDocument = &(d->objectMap.find(ObjectName)->first);
|
||||
// insert in the vector
|
||||
d->objectArray.push_back(pcObject);
|
||||
// Register the current Label even though it is about to change
|
||||
registerLabel(pcObject->Label.getStrValue());
|
||||
|
||||
pcObject->Label.setValue(ObjectName);
|
||||
|
||||
@@ -3812,7 +3765,6 @@ void Document::addObject(DocumentObject* pcObject, const char* pObjectName)
|
||||
|
||||
// insert in the name map
|
||||
d->objectMap[ObjectName] = pcObject;
|
||||
d->objectNameManager.addExactName(ObjectName);
|
||||
// generate object id and add to id map;
|
||||
if (!pcObject->_Id) {
|
||||
pcObject->_Id = ++d->lastObjectId;
|
||||
@@ -3823,8 +3775,6 @@ void Document::addObject(DocumentObject* pcObject, const char* pObjectName)
|
||||
pcObject->pcNameInDocument = &(d->objectMap.find(ObjectName)->first);
|
||||
// insert in the vector
|
||||
d->objectArray.push_back(pcObject);
|
||||
// Register the current Label even though it is about to change
|
||||
registerLabel(pcObject->Label.getStrValue());
|
||||
|
||||
pcObject->Label.setValue(ObjectName);
|
||||
|
||||
@@ -3848,14 +3798,12 @@ void Document::_addObject(DocumentObject* pcObject, const char* pObjectName)
|
||||
{
|
||||
std::string ObjectName = getUniqueObjectName(pObjectName);
|
||||
d->objectMap[ObjectName] = pcObject;
|
||||
d->objectNameManager.addExactName(ObjectName);
|
||||
// generate object id and add to id map;
|
||||
if (!pcObject->_Id) {
|
||||
pcObject->_Id = ++d->lastObjectId;
|
||||
}
|
||||
d->objectIdMap[pcObject->_Id] = pcObject;
|
||||
d->objectArray.push_back(pcObject);
|
||||
registerLabel(pcObject->Label.getStrValue());
|
||||
// cache the pointer to the name string in the Object (for performance of
|
||||
// DocumentObject::getNameInDocument())
|
||||
pcObject->pcNameInDocument = &(d->objectMap.find(ObjectName)->first);
|
||||
@@ -3884,15 +3832,6 @@ void Document::_addObject(DocumentObject* pcObject, const char* pObjectName)
|
||||
signalActivatedObject(*pcObject);
|
||||
}
|
||||
|
||||
bool Document::containsObject(const DocumentObject* pcObject) const
|
||||
{
|
||||
// We could look for the object in objectMap (keyed by object name),
|
||||
// or search in objectArray (a O(n) vector search) but looking by Id
|
||||
// in objectIdMap would be fastest.
|
||||
auto found = d->objectIdMap.find(pcObject->getID());
|
||||
return found != d->objectIdMap.end() && found->second == pcObject;
|
||||
}
|
||||
|
||||
/// Remove an object out of the document
|
||||
void Document::removeObject(const char* sName)
|
||||
{
|
||||
@@ -3980,7 +3919,6 @@ void Document::removeObject(const char* sName)
|
||||
}
|
||||
}
|
||||
|
||||
unregisterLabel(pos->second->Label.getStrValue());
|
||||
for (std::vector<DocumentObject*>::iterator obj = d->objectArray.begin();
|
||||
obj != d->objectArray.end();
|
||||
++obj) {
|
||||
@@ -3994,7 +3932,6 @@ void Document::removeObject(const char* sName)
|
||||
if (tobedestroyed) {
|
||||
tobedestroyed->pcNameInDocument = nullptr;
|
||||
}
|
||||
d->objectNameManager.removeExactName(pos->first);
|
||||
d->objectMap.erase(pos);
|
||||
}
|
||||
|
||||
@@ -4064,8 +4001,6 @@ void Document::_removeObject(DocumentObject* pcObject)
|
||||
// remove from map
|
||||
pcObject->setStatus(ObjectStatus::Remove, false); // Unset the bit to be on the safe side
|
||||
d->objectIdMap.erase(pcObject->_Id);
|
||||
d->objectNameManager.removeExactName(pos->first);
|
||||
unregisterLabel(pos->second->Label.getStrValue());
|
||||
d->objectMap.erase(pos);
|
||||
|
||||
for (std::vector<DocumentObject*>::iterator it = d->objectArray.begin();
|
||||
@@ -4342,29 +4277,50 @@ const char* Document::getObjectName(DocumentObject* pFeat) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string Document::getUniqueObjectName(const char* proposedName) const
|
||||
std::string Document::getUniqueObjectName(const char* Name) const
|
||||
{
|
||||
if (!proposedName || *proposedName == '\0') {
|
||||
if (!Name || *Name == '\0') {
|
||||
return {};
|
||||
}
|
||||
std::string cleanName = Base::Tools::getIdentifier(proposedName);
|
||||
std::string CleanName = Base::Tools::getIdentifier(Name);
|
||||
|
||||
if (!d->objectNameManager.containsName(cleanName)) {
|
||||
// Not in use yet, name is OK
|
||||
return cleanName;
|
||||
// name in use?
|
||||
auto pos = d->objectMap.find(CleanName);
|
||||
|
||||
if (pos == d->objectMap.end()) {
|
||||
// if not, name is OK
|
||||
return CleanName;
|
||||
}
|
||||
else {
|
||||
// remove also trailing digits from clean name which is to avoid to create lengthy names
|
||||
// like 'Box001001'
|
||||
if (!testStatus(KeepTrailingDigits)) {
|
||||
std::string::size_type index = CleanName.find_last_not_of("0123456789");
|
||||
if (index + 1 < CleanName.size()) {
|
||||
CleanName = CleanName.substr(0, index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> names;
|
||||
names.reserve(d->objectMap.size());
|
||||
for (pos = d->objectMap.begin(); pos != d->objectMap.end(); ++pos) {
|
||||
names.push_back(pos->first);
|
||||
}
|
||||
return Base::Tools::getUniqueName(CleanName, names, 3);
|
||||
}
|
||||
return d->objectNameManager.makeUniqueName(cleanName, 3);
|
||||
}
|
||||
|
||||
std::tuple<uint, uint>
|
||||
Document::decomposeName(const std::string& name, std::string& baseName, std::string& nameExtension)
|
||||
std::string Document::getStandardObjectName(const char* Name, int d) const
|
||||
{
|
||||
return d->objectNameManager.decomposeName(name, baseName, nameExtension);
|
||||
}
|
||||
std::vector<App::DocumentObject*> mm = getObjects();
|
||||
std::vector<std::string> labels;
|
||||
labels.reserve(mm.size());
|
||||
|
||||
std::string Document::getStandardObjectLabel(const char* modelName, int digitCount) const
|
||||
{
|
||||
return d->objectLabelManager.makeUniqueName(modelName, digitCount);
|
||||
for (auto it : mm) {
|
||||
std::string label = it->Label.getValue();
|
||||
labels.push_back(label);
|
||||
}
|
||||
return Base::Tools::getUniqueName(Name, labels, d);
|
||||
}
|
||||
|
||||
std::vector<DocumentObject*> Document::getDependingObjects() const
|
||||
|
||||
Reference in New Issue
Block a user