Files
create/src/App/MappedElement.cpp

173 lines
5.9 KiB
C++

// SPDX-License-Identifier: LGPL-2.1-or-later
/***************************************************************************************************
* *
* Copyright (c) 2022 Zheng, Lei (realthunder) <realthunder.dev@gmail.com> *
* Copyright (c) 2023 FreeCAD Project Association *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it under the terms of the *
* GNU Lesser General Public License as published by the Free Software Foundation, either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* FreeCAD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; *
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License along with *
* FreeCAD. If not, see <https://www.gnu.org/licenses/>. *
* *
**************************************************************************************************/
// NOLINTNEXTLINE
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cstdlib>
# include <unordered_set>
#endif
#include "DocumentObject.h"
#include "MappedElement.h"
using namespace Data;
bool ElementNameComparator::operator()(const MappedName& leftName,
const MappedName& rightName) const
{
int size = static_cast<int>(std::min(leftName.size(), rightName.size()));
if (size == 0U) {
return leftName.size() < rightName.size();
}
int currentIndex = 0;
if (rightName[0] == '#') {
if (leftName[0] != '#') {
return true;
}
// If both string starts with '#', compare the following hex digits by
// its integer value.
int res = 0;
for (currentIndex = 1; currentIndex < size; ++currentIndex) {
auto ac = (unsigned char)leftName[currentIndex];
auto bc = (unsigned char)rightName[currentIndex];
if (std::isxdigit(bc) != 0) {
if (std::isxdigit(ac) == 0) {
return true;
}
if (res == 0) {
if (ac < bc) {
res = -1;
}
else if (ac > bc) {
res = 1;
}
}
}
else if (std::isxdigit(ac) != 0) {
res = 1;
}
else {
break;
}
}
if (res < 0) {
return true;
}
if (res > 0) {
return false;
}
for (; currentIndex < size; ++currentIndex) {
char ac = leftName[currentIndex];
char bc = rightName[currentIndex];
if (ac < bc) {
return true;
}
if (ac > bc) {
return false;
}
}
return leftName.size() < rightName.size();
}
if (leftName[0] == '#') {
return false;
}
// If the string does not start with '#', compare the non-digits prefix
// using lexical order.
for (currentIndex = 0; currentIndex < size; ++currentIndex) {
auto ac = (unsigned char)leftName[currentIndex];
auto bc = (unsigned char)rightName[currentIndex];
if (std::isdigit(bc) == 0) {
if (std::isdigit(ac) != 0) {
return true;
}
if (ac < bc) {
return true;
}
if (ac > bc) {
return false;
}
}
else if (std::isdigit(ac) == 0) {
return false;
}
else {
break;
}
}
// Then compare the following digits part by integer value
int res = 0;
for (; currentIndex < size; ++currentIndex) {
auto ac = (unsigned char)leftName[currentIndex];
auto bc = (unsigned char)rightName[currentIndex];
if (std::isdigit(bc) != 0) {
if (std::isdigit(ac) == 0) {
return true;
}
if (res == 0) {
if (ac < bc) {
res = -1;
}
else if (ac > bc) {
res = 1;
}
}
}
else if (std::isdigit(ac) != 0) {
return false;
}
else {
break;
}
}
if (res < 0) {
return true;
}
if (res > 0) {
return false;
}
// Finally, compare the remaining tail using lexical order
for (; currentIndex < size; ++currentIndex) {
char ac = leftName[currentIndex];
char bc = rightName[currentIndex];
if (ac < bc) {
return true;
}
if (ac > bc) {
return false;
}
}
return leftName.size() < rightName.size();
}
HistoryItem::HistoryItem(App::DocumentObject *obj, const Data::MappedName &name)
:obj(obj),tag(0),element(name)
{
if(obj)
tag = obj->getID();
}