From 9200160502c2073bfa8fdcfea5c81e22c0616c62 Mon Sep 17 00:00:00 2001 From: Pesc0 Date: Wed, 8 Mar 2023 17:58:50 +0100 Subject: [PATCH 01/12] Added MappedName class --- src/App/CMakeLists.txt | 2 + src/App/MappedName.cpp | 54 +++ src/App/MappedName.h | 615 +++++++++++++++++++++++++++++++++++ tests/src/App/CMakeLists.txt | 1 + tests/src/App/MappedName.cpp | 16 + 5 files changed, 688 insertions(+) create mode 100644 src/App/MappedName.cpp create mode 100644 src/App/MappedName.h create mode 100644 tests/src/App/MappedName.cpp diff --git a/src/App/CMakeLists.txt b/src/App/CMakeLists.txt index 918ced0a6f..e4b096aedd 100644 --- a/src/App/CMakeLists.txt +++ b/src/App/CMakeLists.txt @@ -262,6 +262,7 @@ SET(FreeCADApp_CPP_SRCS ComplexGeoDataPyImp.cpp Enumeration.cpp IndexedName.cpp + MappedName.cpp Material.cpp MaterialPyImp.cpp Metadata.cpp @@ -279,6 +280,7 @@ SET(FreeCADApp_HPP_SRCS ComplexGeoData.h Enumeration.h IndexedName.h + MappedName.h Material.h Metadata.h ) diff --git a/src/App/MappedName.cpp b/src/App/MappedName.cpp new file mode 100644 index 0000000000..f7620ff7c8 --- /dev/null +++ b/src/App/MappedName.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** + * Copyright (c) 2020 Zheng, Lei (realthunder) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ****************************************************************************/ + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +#endif + +//#include + +#include "MappedName.h" + +using namespace Data; + + +void MappedName::compact() const +{ + auto self = const_cast(this); + + if (this->raw) { + self->data = QByteArray(self->data.constData(), self->data.size()); + self->raw = false; + } + +#if 0 + static std::unordered_set PostfixSet; + if (this->postfix.size()) { + auto res = PostfixSet.insert(this->postfix); + if (!res.second) + self->postfix = *res.first; + } +#endif +} + diff --git a/src/App/MappedName.h b/src/App/MappedName.h new file mode 100644 index 0000000000..5bf15b1c89 --- /dev/null +++ b/src/App/MappedName.h @@ -0,0 +1,615 @@ +/**************************************************************************** + * Copyright (c) 2020 Zheng, Lei (realthunder) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ****************************************************************************/ + + +#ifndef _AppMappedName_h_ +#define _AppMappedName_h_ + + +#include + +#include + +#include +#include + +#include "ComplexGeoData.h" + + +namespace Data +{ + + +class AppExport MappedName +{ +public: + + explicit MappedName(const char * name, int size = -1) + : raw(false) + { + if (!name) return; + if (boost::starts_with(name, ComplexGeoData::elementMapPrefix())) + name += ComplexGeoData::elementMapPrefix().size(); + + data = size < 0 ? QByteArray(name) : QByteArray(name, size); + } + + explicit MappedName(const std::string & name) + : raw(false) + { + int size = name.size(); + const char *n = name.c_str(); + if (boost::starts_with(name, ComplexGeoData::elementMapPrefix())) { + n += ComplexGeoData::elementMapPrefix().size(); + size -= ComplexGeoData::elementMapPrefix().size(); + } + data = QByteArray(n, size); + } +/* + explicit MappedName(const IndexedName & element) + : data(element.getType()), raw(false) + { + if (element.getIndex() > 0) + data += QByteArray::number(element.getIndex()); + } +*/ + MappedName() + : raw(false) + {} + + MappedName(const MappedName & other) + : data(other.data), postfix(other.postfix), raw(other.raw) + {} + + MappedName(const MappedName & other, int startpos, int size = -1) + : raw(false) + { + append(other, startpos, size); + } + + MappedName(const MappedName & other, const char *postfix) + : data(other.data + other.postfix), postfix(postfix), raw(false) + {} + +#if QT_VERSION >= 0x050200 + MappedName(MappedName &&other) + : data(std::move(other.data)), postfix(std::move(other.postfix)), raw(other.raw) + {} +#endif + + static MappedName fromRawData(const char * name, int size = -1) + { + MappedName res; + if (name) { + res.data = QByteArray::fromRawData(name, size>=0 ? size : qstrlen(name)); + res.raw = true; + } + return res; + } + + static MappedName fromRawData(const QByteArray & data) + { + return fromRawData(data.constData(), data.size()); + } + + static MappedName fromRawData(const MappedName &other, int startpos, int size = -1) + { + if (startpos < 0) + startpos = 0; + + if (startpos >= other.size()) + return MappedName(); + + if (startpos >= other.data.size()) + return MappedName(other, startpos, size); + + MappedName res; + res.raw = true; + if (size < 0) + size = other.size() - startpos; + + if (size < other.data.size() - startpos) { + res.data = QByteArray::fromRawData(other.data.constData() + startpos, size); + } + else { + res.data = QByteArray::fromRawData(other.data.constData() + startpos, other.data.size() - startpos); + size -= other.data.size() - startpos; + if (size == other.postfix.size()) + res.postfix = other.postfix; + else if (size) + res.postfix.append(other.postfix.constData(), size); + } + return res; + } + + MappedName & operator=(const MappedName & other) + { + this->data = other.data; + this->postfix = other.postfix; + this->raw = other.raw; + return *this; + } + + MappedName & operator=(const std::string & other) + { + *this = MappedName(other); + return *this; + } + + MappedName & operator=(const char * other) + { + *this = MappedName(other); + return *this; + } + + +#if QT_VERSION >= 0x050200 + MappedName & operator=(MappedName &&other) + { + this->data = std::move(other.data); + this->postfix = std::move(other.postfix); + this->raw = other.raw; + return *this; + } +#endif + + friend std::ostream & operator<<(std::ostream & s, const MappedName & n) + { + s.write(n.data.constData(), n.data.size()); + s.write(n.postfix.constData(), n.postfix.size()); + return s; + } + + bool operator==(const MappedName & other) const + { + if (this->size() != other.size()) { + return false; + } + + if (this->data.size() == other.data.size()) { + return this->data == other.data && this->postfix == other.postfix; + } + + const auto &smaller = this->data.size() < other.data.size() ? *this : other; + const auto &larger = this->data.size() < other.data.size() ? other: *this; + + if (!larger.data.startsWith(smaller.data)) { + return false; + } + + QByteArray tmp = QByteArray::fromRawData( + larger.data.constData() + smaller.data.size(), + larger.data.size() - smaller.data.size() + ); + + if (!smaller.postfix.startsWith(tmp)) { + return false; + } + + tmp = QByteArray::fromRawData( + smaller.postfix.constData() + tmp.size(), + smaller.postfix.size() - tmp.size() + ); + + return tmp == larger.postfix; + } + + bool operator!=(const MappedName & other) const + { + return !(this->operator==(other)); + } + + MappedName operator+(const MappedName & other) const + { + MappedName res(*this); + res += other; + return res; + } + + MappedName operator+(const char * other) const + { + MappedName res(*this); + res += other; + return res; + } + + MappedName operator+(const std::string & other) const + { + MappedName res(*this); + res += other; + return res; + } + + MappedName operator+(const QByteArray & other) const + { + MappedName res(*this); + res += other; + return res; + } + + MappedName & operator+=(const char * other) + { + if (other && other[0]) + this->postfix.append(other, -1); + return *this; + } + + MappedName & operator+=(const std::string & other) + { + if (other.size()) { + this->postfix.reserve(this->postfix.size() + other.size()); + this->postfix.append(other.c_str(), other.size()); + } + return *this; + } + + MappedName & operator+=(const QByteArray & other) + { + this->postfix += other; + return *this; + } + + MappedName & operator+=(const MappedName & other) + { + append(other); + return *this; + } + + void append(const char * d, int size = -1) + { + if (d && size) { + if (size < 0) + size = qstrlen(d); + if (empty()) + this->data.append(d, size); + else + this->postfix.append(d, size); + } + } + + void append(const MappedName & other, int startpos = 0, int size = -1) + { + if (startpos < 0) + startpos = 0; + else if (startpos > other.size()) + return; + if (size < 0 || size + startpos > other.size()) + size = other.size() - startpos; + + int count = size; + if (startpos < other.data.size()) { + if (count > other.data.size() - startpos) + count = other.data.size() - startpos; + if (startpos == 0 && count == other.data.size() && this->empty()) { + this->data = other.data; + this->raw = other.raw; + } else + append(other.data.constData() + startpos, count); + startpos = 0; + size -= count; + } else + startpos -= other.data.size(); + if (size) { + if (startpos == 0 && size == other.postfix.size()) { + if (this->empty()) + this->data = other.postfix; + else if (this->postfix.isEmpty()) + this->postfix = other.postfix; + else + this->postfix += other.postfix; + } else + append(other.postfix.constData() + startpos, size); + } + } + + std::string toString(int startpos, int len=-1) const + { + std::string res; + return toString(res, startpos, len); + } + + const char * toString(std::string &s, int startpos=0, int len=-1) const + { + std::size_t offset = s.size(); + int count = this->size(); + if (startpos < 0) + startpos = 0; + else if (startpos >= count) + return s.c_str()+s.size(); + if (len < 0 || len > count - startpos) + len = count - startpos; + s.reserve(s.size() + len); + if (startpos < this->data.size()) { + count = this->data.size() - startpos; + if (len < count) + count = len; + s.append(this->data.constData()+startpos, count); + len -= count; + } + s.append(this->postfix.constData(), len); + return s.c_str() + offset; + } + + const char * toConstString(int offset, int &size) const + { + if (offset < 0) + offset = 0; + if (offset > this->data.size()) { + offset -= this->data.size(); + if (offset > this->postfix.size()) { + size = 0; + return ""; + } + size = this->postfix.size() - offset; + return this->postfix.constData() + offset; + } + size = this->data.size() - offset; + return this->data.constData() + offset; + } + + QByteArray toRawBytes(int offset=0, int size=-1) const + { + if (offset < 0) + offset = 0; + if (offset >= this->size()) + return QByteArray(); + if (size < 0 || size > this->size() - offset) + size = this->size() - offset; + if (offset >= this->data.size()) { + offset -= this->data.size(); + return QByteArray::fromRawData(this->postfix.constData()+offset, size); + } + if (size <= this->data.size() - offset) + return QByteArray::fromRawData(this->data.constData()+offset, size); + + QByteArray res(this->data.constData()+offset, this->data.size()-offset); + res.append(this->postfix.constData(), size - this->data.size() + offset); + return res; + } + + const QByteArray & dataBytes() const + { + return this->data; + } + + const QByteArray & postfixBytes() const + { + return this->postfix; + } + + const char * constPostfix() const + { + return this->postfix.constData(); + } + + // No constData() because 'data' is allow to contain raw data, which may + // not end with 0. +#if 0 + void char * constData() const + { + return this->data.constData(); + } +#endif + + QByteArray toBytes() const + { + if (this->postfix.isEmpty()) + return this->data; + if (this->data.isEmpty()) + return this->postfix; + return this->data + this->postfix; + } +/* + IndexedName toIndexedName() const + { + if (this->postfix.isEmpty()) + return IndexedName(this->data); + return IndexedName(); + } + + std::string toPrefixedString() const + { + std::string res; + toPrefixedString(res); + return res; + } + + const char *toPrefixedString(std::string &buf) const + { + if (!toIndexedName()) + buf += ComplexGeoData::elementMapPrefix(); + toString(buf); + return buf.c_str(); + } +*/ + int compare(const MappedName &other) const + { + int asize = this->size(); + int bsize = other.size(); + for (int i=0, count=std::min(asize, bsize); ioperator[](i); + char b = other[i]; + if (a < b) + return -1; + if (a > b) + return 1; + } + if (asize < bsize) + return -1; + if (asize > bsize) + return 1; + return 0; + } + + bool operator<(const MappedName & other) const + { + return compare(other) < 0; + } + + char operator[](int index) const + { + if (index >= this->data.size()) + return this->postfix[index - this->data.size()]; + return this->data[index]; + } + + int size() const + { + return this->data.size() + this->postfix.size(); + } + + bool empty() const + { + return this->data.isEmpty() && this->postfix.isEmpty(); + } + + bool isRaw() const + { + return this->raw; + } + + MappedName copy() const + { + if (!this->raw) + return *this; + MappedName res; + res.data.append(this->data.constData(), this->data.size()); + res.postfix = this->postfix; + return res; + } + + void compact() const; + + explicit operator bool() const + { + return !empty(); + } + + void clear() + { + this->data.clear(); + this->postfix.clear(); + this->raw = false; + } + + int find(const char *d, int startpos = 0) const + { + if (!d) + return -1; + if (startpos < 0) + startpos = 0; + if (startpos < this->data.size()) { + int res = this->data.indexOf(d, startpos); + if (res >= 0) + return res; + startpos = 0; + } else + startpos -= this->data.size(); + int res = this->postfix.indexOf(d, startpos); + if (res < 0) + return res; + return res + this->data.size(); + } + + int find(const std::string &d, int startpos = 0) const + { + return find(d.c_str(), startpos); + } + + int rfind(const char *d, int startpos = -1) const + { + if (!d) + return -1; + if (startpos < 0 || startpos > this->postfix.size()) { + if (startpos > postfix.size()) + startpos -= postfix.size(); + int res = this->postfix.lastIndexOf(d, startpos); + if (res >= 0) + return res + this->data.size(); + startpos = -1; + } + return this->data.lastIndexOf(d, startpos); + } + + int rfind(const std::string &d, int startpos = -1) const + { + return rfind(d.c_str(), startpos); + } + + bool endsWith(const char *s) const + { + if (!s) + return false; + if (this->postfix.size()) + return this->postfix.endsWith(s); + return this->data.endsWith(s); + } + + bool endsWith(const std::string &s) const + { + return endsWith(s.c_str()); + } + + bool startsWith(const QByteArray & s, int offset = 0) const + { + if (s.size() > size() - offset) + return false; + if (offset || (this->data.size() && this->data.size() < s.size())) + return toRawBytes(offset, s.size()) == s; + if (this->data.size()) + return this->data.startsWith(s); + return this->postfix.startsWith(s); + } + + bool startsWith(const char *s, int offset = 0) const + { + if (!s) + return false; + return startsWith(QByteArray::fromRawData(s, qstrlen(s)), offset); + } + + bool startsWith(const std::string &s, int offset = 0) const + { + return startsWith(QByteArray::fromRawData(s.c_str(), s.size()), offset); + } + + std::size_t hash() const + { +#if QT_VERSION >= 0x050000 + return qHash(data, qHash(postfix)); +#else + return qHash(data) ^ qHash(postfix); +#endif + } + +private: + QByteArray data; + QByteArray postfix; + bool raw; +}; + + + +} //namespace Data + + +#endif \ No newline at end of file diff --git a/tests/src/App/CMakeLists.txt b/tests/src/App/CMakeLists.txt index fbde1bb2fa..c64ae328f5 100644 --- a/tests/src/App/CMakeLists.txt +++ b/tests/src/App/CMakeLists.txt @@ -5,5 +5,6 @@ target_sources( ${CMAKE_CURRENT_SOURCE_DIR}/Expression.cpp ${CMAKE_CURRENT_SOURCE_DIR}/IndexedName.cpp ${CMAKE_CURRENT_SOURCE_DIR}/License.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/MappedName.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Metadata.cpp ) diff --git a/tests/src/App/MappedName.cpp b/tests/src/App/MappedName.cpp new file mode 100644 index 0000000000..436bf0c520 --- /dev/null +++ b/tests/src/App/MappedName.cpp @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later + +#include "gtest/gtest.h" + +#include "App/MappedName.h" + + +// clang-format off +TEST(MappedName, defaultConstruction) +{ + +} + + + +// clang-format on \ No newline at end of file From c39f6037444755ecf2aa612bad0581b312ce381b Mon Sep 17 00:00:00 2001 From: Pesc0 Date: Fri, 10 Mar 2023 20:11:04 +0100 Subject: [PATCH 02/12] Added initial tests to MappedName --- src/App/MappedName.h | 29 +++++- tests/src/App/MappedName.cpp | 194 +++++++++++++++++++++++++++++++++++ 2 files changed, 218 insertions(+), 5 deletions(-) diff --git a/src/App/MappedName.h b/src/App/MappedName.h index 5bf15b1c89..89b6bf56ea 100644 --- a/src/App/MappedName.h +++ b/src/App/MappedName.h @@ -80,6 +80,9 @@ public: : data(other.data), postfix(other.postfix), raw(other.raw) {} + //FIXME if you pass a raw MappedName into these constructors they will + //reset raw to false and things will break. is this intended? + MappedName(const MappedName & other, int startpos, int size = -1) : raw(false) { @@ -276,6 +279,7 @@ public: void append(const char * d, int size = -1) { + //FIXME raw not assigned? if (d && size) { if (size < 0) size = qstrlen(d); @@ -288,26 +292,41 @@ public: void append(const MappedName & other, int startpos = 0, int size = -1) { + // enforce 0 <= startpos <= other.size if (startpos < 0) startpos = 0; else if (startpos > other.size()) return; - if (size < 0 || size + startpos > other.size()) + + // enforce 0 <= size <= other.size - startpos + if (size < 0 || size > other.size() - startpos) size = other.size() - startpos; - int count = size; - if (startpos < other.data.size()) { - if (count > other.data.size() - startpos) + + if (startpos < other.data.size()) // if starting inside data + { + int count = size; + //make sure count doesn't exceed data size and end up in postfix + if (count > other.data.size() - startpos) count = other.data.size() - startpos; + + //if this is empty append in data else append in postfix if (startpos == 0 && count == other.data.size() && this->empty()) { this->data = other.data; this->raw = other.raw; } else append(other.data.constData() + startpos, count); + + //setup startpos and count to contiune appending the remainder to postfix startpos = 0; size -= count; - } else + } + else //else starting inside postfix + { startpos -= other.data.size(); + } + + //if there is still data to be added to postfix if (size) { if (startpos == 0 && size == other.postfix.size()) { if (this->empty()) diff --git a/tests/src/App/MappedName.cpp b/tests/src/App/MappedName.cpp index 436bf0c520..dc3ae1b383 100644 --- a/tests/src/App/MappedName.cpp +++ b/tests/src/App/MappedName.cpp @@ -3,14 +3,208 @@ #include "gtest/gtest.h" #include "App/MappedName.h" +#include "App/ComplexGeoData.h" + +#include + // clang-format off TEST(MappedName, defaultConstruction) { + auto mappedName = Data::MappedName(); + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), true); + EXPECT_EQ(mappedName.size(), 0); +} + +TEST(MappedName, namedConstruction) +{ + auto mappedName = Data::MappedName("TEST"); + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 4); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); +} + +TEST(MappedName, namedConstructionWithMaxSize) +{ + auto mappedName = Data::MappedName("TEST", 2); + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 2); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TE")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); +} + +TEST(MappedName, namedConstructionDiscardPrefix) +{ + std::string name = Data::ComplexGeoData::elementMapPrefix() + "TEST"; + auto mappedName = Data::MappedName(name.c_str()); + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 4); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); } +TEST(MappedName, stringNamedConstruction) +{ + auto mappedName = Data::MappedName(std::string("TEST")); + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 4); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); +} + +TEST(MappedName, stringNamedConstructionDiscardPrefix) +{ + std::string name = Data::ComplexGeoData::elementMapPrefix() + "TEST"; + auto mappedName = Data::MappedName(name); + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 4); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); + +} + +TEST(MappedName, copyConstructor) +{ + auto temp = Data::MappedName("TEST"); + auto mappedName = Data::MappedName(temp); + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 4); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); + +} + +TEST(MappedName, copyConstructorWithPostfix) +{ + auto temp = Data::MappedName("TEST"); + auto mappedName = Data::MappedName(temp, "POSTFIXTEST"); + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 15); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POSTFIXTEST")); +} + +TEST(MappedName, constructorWithPostfixAndCopy) +{ + auto temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + auto mappedName = Data::MappedName(temp, "ANOTHERPOSTFIX"); + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 29); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TESTPOSTFIXTEST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray("ANOTHERPOSTFIX")); +} + +TEST(MappedName, copyConstructorStartpos) +{ + auto temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + auto mappedName = Data::MappedName(temp, 2, -1); + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 13); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("ST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POSTFIXTEST")); +} + +TEST(MappedName, copyConstructorStartposAndSize) +{ + auto temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + auto mappedName = Data::MappedName(temp, 2, 6); + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 6); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("ST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POST")); +} + +#if QT_VERSION >= 0x050200 +TEST(MappedName, moveConstructor) +{ + auto temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + auto mappedName = Data::MappedName(std::move(temp)); + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 15); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POSTFIXTEST")); + + EXPECT_EQ(temp.isRaw(), false); + EXPECT_EQ(temp.empty(), true); + EXPECT_EQ(temp.size(), 0); + EXPECT_EQ(temp.dataBytes(), QByteArray()); + EXPECT_EQ(temp.postfixBytes(), QByteArray()); +} +#endif + +TEST(MappedName, fromRawData) +{ + auto mappedName = Data::MappedName::fromRawData("TEST\0\0TEST", 10); + EXPECT_EQ(mappedName.isRaw(), true); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 10); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST\0\0TEST", 10)); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); +} + +TEST(MappedName, fromRawDataQByteArray) +{ + auto mappedName = Data::MappedName::fromRawData(QByteArray("TEST\0\0TEST", 10)); + EXPECT_EQ(mappedName.isRaw(), true); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 10); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST\0\0TEST", 10)); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); +} + +TEST(MappedName, fromRawDataCopy) +{ + auto temp = Data::MappedName::fromRawData(QByteArray("TEST\0\0TEST", 10)); + temp.append("TESTPOSTFIX"); + auto mappedName = Data::MappedName::fromRawData(temp, 0); + EXPECT_EQ(mappedName.isRaw(), true); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 21); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST\0\0TEST", 10)); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray("TESTPOSTFIX")); +} + + +TEST(MappedName, fromRawDataCopyStartposAndSize) +{ + auto temp = Data::MappedName::fromRawData(QByteArray("TEST\0\0TEST", 10)); + temp.append("ABCDEFGHIJKLM"); //postfix +/* This block is OK + EXPECT_EQ(temp.isRaw(), true); + EXPECT_EQ(temp.empty(), false); + EXPECT_EQ(temp.size(), 23); + EXPECT_EQ(temp.dataBytes(), QByteArray("TEST\0\0TEST", 10)); + EXPECT_EQ(temp.postfixBytes(), QByteArray("ABCDEFGHIJKLM")); +*/ + + auto mappedName = Data::MappedName::fromRawData(temp, 2, 13); + EXPECT_EQ(mappedName.isRaw(), true); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 13); + //next line fails with CDE\0TEST != ST\0\0TEST + //funny thing if i uncomment the block above, which does nothing, now the next line + //fails with CDE\0GHIJ != ST\0\0TEST + EXPECT_EQ(mappedName.dataBytes(), QByteArray("ST\0\0TEST", 8)); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray("ABCDE")); +} + +//TODO raw postfix? + // clang-format on \ No newline at end of file From 2ec169f2a934d2fda5123721e571a36d37fa2055 Mon Sep 17 00:00:00 2001 From: Pesc0 Date: Sat, 11 Mar 2023 15:48:12 +0100 Subject: [PATCH 03/12] MappedName unit tests almost complete --- src/App/MappedName.h | 13 +- tests/src/App/MappedName.cpp | 420 ++++++++++++++++++++++++++++++++--- 2 files changed, 397 insertions(+), 36 deletions(-) diff --git a/src/App/MappedName.h b/src/App/MappedName.h index 89b6bf56ea..89e95fd4ad 100644 --- a/src/App/MappedName.h +++ b/src/App/MappedName.h @@ -93,11 +93,9 @@ public: : data(other.data + other.postfix), postfix(postfix), raw(false) {} -#if QT_VERSION >= 0x050200 MappedName(MappedName &&other) : data(std::move(other.data)), postfix(std::move(other.postfix)), raw(other.raw) {} -#endif static MappedName fromRawData(const char * name, int size = -1) { @@ -165,7 +163,6 @@ public: } -#if QT_VERSION >= 0x050200 MappedName & operator=(MappedName &&other) { this->data = std::move(other.data); @@ -173,7 +170,6 @@ public: this->raw = other.raw; return *this; } -#endif friend std::ostream & operator<<(std::ostream & s, const MappedName & n) { @@ -368,6 +364,8 @@ public: return s.c_str() + offset; } + //if offset is inside data return data, if offset is > data.size + //(ends up in postfix) return postfix const char * toConstString(int offset, int &size) const { if (offset < 0) @@ -486,6 +484,7 @@ public: char operator[](int index) const { + //FIXME overflow underflow checks? if (index >= this->data.size()) return this->postfix[index - this->data.size()]; return this->data[index]; @@ -558,7 +557,7 @@ public: { if (!d) return -1; - if (startpos < 0 || startpos > this->postfix.size()) { + if (startpos < 0 || startpos > this->postfix.size()) { //FIXME should be this->data.size if (startpos > postfix.size()) startpos -= postfix.size(); int res = this->postfix.lastIndexOf(d, startpos); @@ -613,11 +612,7 @@ public: std::size_t hash() const { -#if QT_VERSION >= 0x050000 return qHash(data, qHash(postfix)); -#else - return qHash(data) ^ qHash(postfix); -#endif } private: diff --git a/tests/src/App/MappedName.cpp b/tests/src/App/MappedName.cpp index dc3ae1b383..5ddee750d8 100644 --- a/tests/src/App/MappedName.cpp +++ b/tests/src/App/MappedName.cpp @@ -6,13 +6,14 @@ #include "App/ComplexGeoData.h" #include +#include // clang-format off TEST(MappedName, defaultConstruction) { - auto mappedName = Data::MappedName(); + Data::MappedName mappedName = Data::MappedName(); EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), true); EXPECT_EQ(mappedName.size(), 0); @@ -20,7 +21,7 @@ TEST(MappedName, defaultConstruction) TEST(MappedName, namedConstruction) { - auto mappedName = Data::MappedName("TEST"); + Data::MappedName mappedName = Data::MappedName("TEST"); EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 4); @@ -30,7 +31,7 @@ TEST(MappedName, namedConstruction) TEST(MappedName, namedConstructionWithMaxSize) { - auto mappedName = Data::MappedName("TEST", 2); + Data::MappedName mappedName = Data::MappedName("TEST", 2); EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 2); @@ -41,7 +42,7 @@ TEST(MappedName, namedConstructionWithMaxSize) TEST(MappedName, namedConstructionDiscardPrefix) { std::string name = Data::ComplexGeoData::elementMapPrefix() + "TEST"; - auto mappedName = Data::MappedName(name.c_str()); + Data::MappedName mappedName = Data::MappedName(name.c_str()); EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 4); @@ -52,7 +53,7 @@ TEST(MappedName, namedConstructionDiscardPrefix) TEST(MappedName, stringNamedConstruction) { - auto mappedName = Data::MappedName(std::string("TEST")); + Data::MappedName mappedName = Data::MappedName(std::string("TEST")); EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 4); @@ -63,7 +64,7 @@ TEST(MappedName, stringNamedConstruction) TEST(MappedName, stringNamedConstructionDiscardPrefix) { std::string name = Data::ComplexGeoData::elementMapPrefix() + "TEST"; - auto mappedName = Data::MappedName(name); + Data::MappedName mappedName = Data::MappedName(name); EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 4); @@ -74,8 +75,8 @@ TEST(MappedName, stringNamedConstructionDiscardPrefix) TEST(MappedName, copyConstructor) { - auto temp = Data::MappedName("TEST"); - auto mappedName = Data::MappedName(temp); + Data::MappedName temp = Data::MappedName("TEST"); + Data::MappedName mappedName = Data::MappedName(temp); EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 4); @@ -86,8 +87,8 @@ TEST(MappedName, copyConstructor) TEST(MappedName, copyConstructorWithPostfix) { - auto temp = Data::MappedName("TEST"); - auto mappedName = Data::MappedName(temp, "POSTFIXTEST"); + Data::MappedName temp = Data::MappedName("TEST"); + Data::MappedName mappedName = Data::MappedName(temp, "POSTFIXTEST"); EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 15); @@ -97,8 +98,8 @@ TEST(MappedName, copyConstructorWithPostfix) TEST(MappedName, constructorWithPostfixAndCopy) { - auto temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); - auto mappedName = Data::MappedName(temp, "ANOTHERPOSTFIX"); + Data::MappedName temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName = Data::MappedName(temp, "ANOTHERPOSTFIX"); EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 29); @@ -108,8 +109,8 @@ TEST(MappedName, constructorWithPostfixAndCopy) TEST(MappedName, copyConstructorStartpos) { - auto temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); - auto mappedName = Data::MappedName(temp, 2, -1); + Data::MappedName temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName = Data::MappedName(temp, 2, -1); EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 13); @@ -119,8 +120,8 @@ TEST(MappedName, copyConstructorStartpos) TEST(MappedName, copyConstructorStartposAndSize) { - auto temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); - auto mappedName = Data::MappedName(temp, 2, 6); + Data::MappedName temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName = Data::MappedName(temp, 2, 6); EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 6); @@ -128,11 +129,10 @@ TEST(MappedName, copyConstructorStartposAndSize) EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POST")); } -#if QT_VERSION >= 0x050200 TEST(MappedName, moveConstructor) { - auto temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); - auto mappedName = Data::MappedName(std::move(temp)); + Data::MappedName temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName = Data::MappedName(std::move(temp)); EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 15); @@ -145,11 +145,10 @@ TEST(MappedName, moveConstructor) EXPECT_EQ(temp.dataBytes(), QByteArray()); EXPECT_EQ(temp.postfixBytes(), QByteArray()); } -#endif TEST(MappedName, fromRawData) { - auto mappedName = Data::MappedName::fromRawData("TEST\0\0TEST", 10); + Data::MappedName mappedName = Data::MappedName::fromRawData("TEST\0\0TEST", 10); EXPECT_EQ(mappedName.isRaw(), true); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 10); @@ -159,7 +158,7 @@ TEST(MappedName, fromRawData) TEST(MappedName, fromRawDataQByteArray) { - auto mappedName = Data::MappedName::fromRawData(QByteArray("TEST\0\0TEST", 10)); + Data::MappedName mappedName = Data::MappedName::fromRawData(QByteArray("TEST\0\0TEST", 10)); EXPECT_EQ(mappedName.isRaw(), true); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 10); @@ -169,9 +168,9 @@ TEST(MappedName, fromRawDataQByteArray) TEST(MappedName, fromRawDataCopy) { - auto temp = Data::MappedName::fromRawData(QByteArray("TEST\0\0TEST", 10)); + Data::MappedName temp = Data::MappedName::fromRawData(QByteArray("TEST\0\0TEST", 10)); temp.append("TESTPOSTFIX"); - auto mappedName = Data::MappedName::fromRawData(temp, 0); + Data::MappedName mappedName = Data::MappedName::fromRawData(temp, 0); EXPECT_EQ(mappedName.isRaw(), true); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 21); @@ -182,7 +181,7 @@ TEST(MappedName, fromRawDataCopy) TEST(MappedName, fromRawDataCopyStartposAndSize) { - auto temp = Data::MappedName::fromRawData(QByteArray("TEST\0\0TEST", 10)); + Data::MappedName temp = Data::MappedName::fromRawData(QByteArray("TEST\0\0TEST", 10)); temp.append("ABCDEFGHIJKLM"); //postfix /* This block is OK EXPECT_EQ(temp.isRaw(), true); @@ -192,7 +191,7 @@ TEST(MappedName, fromRawDataCopyStartposAndSize) EXPECT_EQ(temp.postfixBytes(), QByteArray("ABCDEFGHIJKLM")); */ - auto mappedName = Data::MappedName::fromRawData(temp, 2, 13); + Data::MappedName mappedName = Data::MappedName::fromRawData(temp, 2, 13); EXPECT_EQ(mappedName.isRaw(), true); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 13); @@ -203,8 +202,375 @@ TEST(MappedName, fromRawDataCopyStartposAndSize) EXPECT_EQ(mappedName.postfixBytes(), QByteArray("ABCDE")); } -//TODO raw postfix? +//TODO raw postfix? answer: apparently postfix will never be raw. See copy() + +TEST(MappedName, assignmentOperator) +{ + Data::MappedName temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName = temp; + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 15); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POSTFIXTEST")); +} + +TEST(MappedName, assignmentOperatorString) +{ + Data::MappedName mappedName; + mappedName = std::string("TEST"); + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 4); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); +} + +TEST(MappedName, assignmentOperatorConstCharPtr) +{ + Data::MappedName mappedName; + mappedName = "TEST"; + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 4); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); +} + +TEST(MappedName, operatorEqualMove) +{ + Data::MappedName temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName = std::move(temp); + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 15); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POSTFIXTEST")); + + EXPECT_EQ(temp.isRaw(), false); + EXPECT_EQ(temp.empty(), true); + EXPECT_EQ(temp.size(), 0); + EXPECT_EQ(temp.dataBytes(), QByteArray()); + EXPECT_EQ(temp.postfixBytes(), QByteArray()); +} + +TEST(MappedName, streamInsertionOperator) +{ + Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 15); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POSTFIXTEST")); + + std::stringstream ss; + ss << mappedName; + EXPECT_EQ(ss.str(), std::string("TESTPOSTFIXTEST")); +} +TEST(MappedName, comparisonOperators) +{ + Data::MappedName mappedName1 = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName2 = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName3 = Data::MappedName(Data::MappedName("TESTPOST"), "FIXTEST"); + Data::MappedName mappedName4 = Data::MappedName(Data::MappedName("THIS"), "ISDIFFERENT"); + + EXPECT_EQ(mappedName1 == mappedName1, true); + EXPECT_EQ(mappedName1 == mappedName2, true); + EXPECT_EQ(mappedName1 == mappedName3, true); + EXPECT_EQ(mappedName1 == mappedName4, false); + + EXPECT_EQ(mappedName1 != mappedName1, false); + EXPECT_EQ(mappedName1 != mappedName2, false); + EXPECT_EQ(mappedName1 != mappedName3, false); + EXPECT_EQ(mappedName1 != mappedName4, true); +} + +TEST(MappedName, additionOperators) +{ + Data::MappedName mappedName1 = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + mappedName1 += "POST1"; + mappedName1 += std::string("POST2"); + mappedName1 += QByteArray("POST3"); + mappedName1 += Data::MappedName("POST4"); + + EXPECT_EQ(mappedName1.isRaw(), false); + EXPECT_EQ(mappedName1.empty(), false); + EXPECT_EQ(mappedName1.size(), 35); + EXPECT_EQ(mappedName1.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName1.postfixBytes(), QByteArray("POSTFIXTESTPOST1POST2POST3POST4")); + + mappedName1 = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + mappedName1 = mappedName1 + Data::MappedName("POST5"); + mappedName1 = mappedName1 + "POST6"; + mappedName1 = mappedName1 + std::string("POST7"); + mappedName1 = mappedName1 + QByteArray("POST8"); + + EXPECT_EQ(mappedName1.isRaw(), false); + EXPECT_EQ(mappedName1.empty(), false); + EXPECT_EQ(mappedName1.size(), 35); + EXPECT_EQ(mappedName1.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName1.postfixBytes(), QByteArray("POSTFIXTESTPOST5POST6POST7POST8")); +} + + +TEST(MappedName, append) +{ + Data::MappedName mappedName = Data::MappedName(); + mappedName.append("TEST"); + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 4); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray("")); + + mappedName.append("POSTFIX"); + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 11); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POSTFIX")); + + mappedName.append("ANOTHERPOSTFIX", 5); + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 16); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POSTFIXANOTH")); +} + + +TEST(MappedName, appendMappedNameObj) +{ + Data::MappedName mappedName = Data::MappedName(); + + mappedName.append(Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST")); + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 15); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POSTFIXTEST")); + + mappedName.append(Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"), 2, 7); + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 22); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POSTFIXTESTSTPOSTF")); +} + +TEST(MappedName, toString) +{ + Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + EXPECT_EQ(mappedName.toString(0), "TESTPOSTFIXTEST"); + EXPECT_EQ(mappedName.toString(0), std::string("TESTPOSTFIXTEST")); + EXPECT_EQ(mappedName.toString(2, 8), "STPOSTFI"); + EXPECT_EQ(mappedName.toString(2, 8), std::string("STPOSTFI")); +} + + +TEST(MappedName, toConstString) +{ + Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + int size; + const char *temp = mappedName.toConstString(0, size); + EXPECT_EQ(QByteArray(temp, size), QByteArray("TEST")); + EXPECT_EQ(size, 4); + const char *temp2 = mappedName.toConstString(7, size); + EXPECT_EQ(QByteArray(temp2, size), QByteArray("TFIXTEST")); + EXPECT_EQ(size, 8); +} + +TEST(MappedName, toRawBytes) +{ + Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + EXPECT_EQ(mappedName.toRawBytes(), QByteArray("TESTPOSTFIXTEST")); + EXPECT_EQ(mappedName.toRawBytes(3), QByteArray("TPOSTFIXTEST")); + EXPECT_EQ(mappedName.toRawBytes(7, 3), QByteArray("TFI")); + EXPECT_EQ(mappedName.toRawBytes(502, 5), QByteArray()); +} + +TEST(MappedName, toBytes) +{ + Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + EXPECT_EQ(mappedName.toBytes(), QByteArray("TESTPOSTFIXTEST")); +} + + +TEST(MappedName, compare) +{ + Data::MappedName mappedName1 = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName2 = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName3 = Data::MappedName(Data::MappedName("TESTPOST"), "FIXTEST"); + Data::MappedName mappedName4 = Data::MappedName(Data::MappedName("THIS"), "ISDIFFERENT"); + Data::MappedName mappedName5 = Data::MappedName(Data::MappedName("SH"), "ORTHER"); + Data::MappedName mappedName6 = Data::MappedName(Data::MappedName("VERYVERYVERY"), "VERYMUCHLONGER"); + + EXPECT_EQ(mappedName1.compare(mappedName1), 0); + EXPECT_EQ(mappedName1.compare(mappedName2), 0); + EXPECT_EQ(mappedName1.compare(mappedName3), 0); + EXPECT_EQ(mappedName1.compare(mappedName4), -1); + EXPECT_EQ(mappedName1.compare(mappedName5), 1); + EXPECT_EQ(mappedName1.compare(mappedName6), -1); + + EXPECT_EQ(mappedName1 < mappedName1, false); + EXPECT_EQ(mappedName1 < mappedName2, false); + EXPECT_EQ(mappedName1 < mappedName3, false); + EXPECT_EQ(mappedName1 < mappedName4, true); + EXPECT_EQ(mappedName1 < mappedName5, false); + EXPECT_EQ(mappedName1 < mappedName6, true); +} + +TEST(MappedName, indexOperator) +{ + Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + EXPECT_EQ(mappedName[0], 'T'); + EXPECT_EQ(mappedName[1], 'E'); + EXPECT_EQ(mappedName[2], 'S'); + EXPECT_EQ(mappedName[3], 'T'); + EXPECT_EQ(mappedName[4], 'P'); + EXPECT_EQ(mappedName[5], 'O'); + EXPECT_EQ(mappedName[6], 'S'); + EXPECT_EQ(mappedName[7], 'T'); + EXPECT_EQ(mappedName[8], 'F'); + EXPECT_EQ(mappedName[9], 'I'); +} + +TEST(MappedName, copy) +{ + Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName2 = mappedName.copy(); + EXPECT_EQ(mappedName, mappedName2); +} + + +TEST(MappedName, compact) +{ + Data::MappedName mappedName = Data::MappedName::fromRawData("TEST\0\0TEST", 10); + EXPECT_EQ(mappedName.isRaw(), true); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 10); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST\0\0TEST", 10)); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); + + mappedName.compact(); + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 10); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST\0\0TEST", 10)); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); +} + +TEST(MappedName, boolOperator) +{ + Data::MappedName mappedName = Data::MappedName(); + EXPECT_EQ((bool)mappedName, false); + mappedName.append("TEST"); + EXPECT_EQ((bool)mappedName, true); +} + +TEST(MappedName, clear) +{ + Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + EXPECT_EQ(mappedName.empty(), false); + mappedName.clear(); + EXPECT_EQ(mappedName.empty(), true); +} + +TEST(MappedName, find) +{ + Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + EXPECT_EQ(mappedName.find(nullptr), -1); + EXPECT_EQ(mappedName.find(""), 0); + EXPECT_EQ(mappedName.find("TEST"), 0); + EXPECT_EQ(mappedName.find("STPO"), -1); //sentence must be fully contained in data or postfix + EXPECT_EQ(mappedName.find("POST"), 4); + EXPECT_EQ(mappedName.find("ST", 3), 6); //found in postfix + EXPECT_EQ(mappedName.find("POST", 4), 4); + EXPECT_EQ(mappedName.find("POST", 5), -1); + + EXPECT_EQ(mappedName.find(std::string("")), 0); +} + + +TEST(MappedName, rfind) +{ + Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + EXPECT_EQ(mappedName.rfind(nullptr), -1); + EXPECT_EQ(mappedName.rfind(""), mappedName.size()); + EXPECT_EQ(mappedName.rfind("TEST"), 11); + EXPECT_EQ(mappedName.rfind("STPO"), -1); //sentence must be fully contained in data or postfix + EXPECT_EQ(mappedName.rfind("POST"), 4); + + + //FIXME looks broken + EXPECT_EQ(mappedName.rfind("ST"), 13); + EXPECT_EQ(mappedName.rfind("ST", 0), -1); + EXPECT_EQ(mappedName.rfind("ST", 1), -1); + EXPECT_EQ(mappedName.rfind("ST", 2), 2); + EXPECT_EQ(mappedName.rfind("ST", 3), 2); + EXPECT_EQ(mappedName.rfind("ST", 4), 2); + EXPECT_EQ(mappedName.rfind("ST", 5), -1); + EXPECT_EQ(mappedName.rfind("ST", 6), -1); + EXPECT_EQ(mappedName.rfind("ST", 7), -1); + EXPECT_EQ(mappedName.rfind("ST", 8), -1); + EXPECT_EQ(mappedName.rfind("ST", 9), -1); + EXPECT_EQ(mappedName.rfind("ST", 10), -1); + EXPECT_EQ(mappedName.rfind("ST", 11), -1); + EXPECT_EQ(mappedName.rfind("ST", 12), 2); + EXPECT_EQ(mappedName.rfind("ST", 13), 6); + EXPECT_EQ(mappedName.rfind("ST", 14), 6); + EXPECT_EQ(mappedName.rfind("ST", 15), 6); + EXPECT_EQ(mappedName.rfind("ST", 16), 6); + EXPECT_EQ(mappedName.rfind("ST", 17), 6); + EXPECT_EQ(mappedName.rfind("ST", 18), 6); + EXPECT_EQ(mappedName.rfind("ST", 19), 6); + EXPECT_EQ(mappedName.rfind("ST", 20), 13); + EXPECT_EQ(mappedName.rfind("ST", 21), 13); + EXPECT_EQ(mappedName.rfind("ST", 22), 13); + EXPECT_EQ(mappedName.rfind("ST", 23), 2); + EXPECT_EQ(mappedName.rfind("ST", 24), 2); + EXPECT_EQ(mappedName.rfind("ST", 25), 2); + EXPECT_EQ(mappedName.rfind("ST", 26), 2); + EXPECT_EQ(mappedName.rfind("ST", 27), 2); + EXPECT_EQ(mappedName.rfind("ST", 28), 2); + //EXPECT_EQ(mappedName.rfind("POST", 7), 4); + //EXPECT_EQ(mappedName.rfind("POST", 8), -1); + + EXPECT_EQ(mappedName.rfind(std::string("")), mappedName.size()); +} + +TEST(MappedName, endswith) +{ + Data::MappedName mappedName = Data::MappedName("TEST"); + EXPECT_EQ(mappedName.endsWith(nullptr), false); + EXPECT_EQ(mappedName.endsWith("TEST"), true); + EXPECT_EQ(mappedName.endsWith("WASD"), false); + + EXPECT_EQ(mappedName.endsWith(std::string("TEST")), true); + + mappedName.append("POSTFIX"); + + EXPECT_EQ(mappedName.endsWith(nullptr), false); + EXPECT_EQ(mappedName.endsWith("TEST"), false); + EXPECT_EQ(mappedName.endsWith("FIX"), true); +} + + +TEST(MappedName, startsWith) +{ + Data::MappedName mappedName = Data::MappedName("TEST"); + EXPECT_EQ(mappedName.startsWith(QByteArray()), true); + EXPECT_EQ(mappedName.startsWith("TEST"), true); + EXPECT_EQ(mappedName.startsWith("WASD"), false); + + EXPECT_EQ(mappedName.startsWith(nullptr), false); + EXPECT_EQ(mappedName.startsWith("TEST"), true); + EXPECT_EQ(mappedName.startsWith(std::string("TEST")), true); +} + +//TODO test hash function // clang-format on \ No newline at end of file From d589d5205dd88e3fefb288992a9414ee55636ab9 Mon Sep 17 00:00:00 2001 From: Pesc0 Date: Tue, 14 Mar 2023 02:11:15 +0100 Subject: [PATCH 04/12] Use AAA pattern in test suite --- tests/src/App/MappedName.cpp | 304 ++++++++++++++++++++++++++--------- 1 file changed, 229 insertions(+), 75 deletions(-) diff --git a/tests/src/App/MappedName.cpp b/tests/src/App/MappedName.cpp index 5ddee750d8..c5e176f540 100644 --- a/tests/src/App/MappedName.cpp +++ b/tests/src/App/MappedName.cpp @@ -13,15 +13,23 @@ // clang-format off TEST(MappedName, defaultConstruction) { + // Act Data::MappedName mappedName = Data::MappedName(); + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), true); EXPECT_EQ(mappedName.size(), 0); + EXPECT_EQ(mappedName.dataBytes(), QByteArray()); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); } TEST(MappedName, namedConstruction) { + // Act Data::MappedName mappedName = Data::MappedName("TEST"); + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 4); @@ -31,7 +39,10 @@ TEST(MappedName, namedConstruction) TEST(MappedName, namedConstructionWithMaxSize) { + // Act Data::MappedName mappedName = Data::MappedName("TEST", 2); + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 2); @@ -41,19 +52,26 @@ TEST(MappedName, namedConstructionWithMaxSize) TEST(MappedName, namedConstructionDiscardPrefix) { + // Arrange std::string name = Data::ComplexGeoData::elementMapPrefix() + "TEST"; + + // Act Data::MappedName mappedName = Data::MappedName(name.c_str()); + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 4); EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); - } TEST(MappedName, stringNamedConstruction) { + // Act Data::MappedName mappedName = Data::MappedName(std::string("TEST")); + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 4); @@ -63,43 +81,58 @@ TEST(MappedName, stringNamedConstruction) TEST(MappedName, stringNamedConstructionDiscardPrefix) { + // Arrange std::string name = Data::ComplexGeoData::elementMapPrefix() + "TEST"; + + // Act Data::MappedName mappedName = Data::MappedName(name); + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 4); EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); - } TEST(MappedName, copyConstructor) { + // Arrange Data::MappedName temp = Data::MappedName("TEST"); + + // Act Data::MappedName mappedName = Data::MappedName(temp); + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 4); EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); - } TEST(MappedName, copyConstructorWithPostfix) { + // Arrange Data::MappedName temp = Data::MappedName("TEST"); + + // Act Data::MappedName mappedName = Data::MappedName(temp, "POSTFIXTEST"); + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 15); EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POSTFIXTEST")); -} -TEST(MappedName, constructorWithPostfixAndCopy) -{ - Data::MappedName temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); - Data::MappedName mappedName = Data::MappedName(temp, "ANOTHERPOSTFIX"); + // Arrange + temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + + // Act + mappedName = Data::MappedName(temp, "ANOTHERPOSTFIX"); + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 29); @@ -109,8 +142,13 @@ TEST(MappedName, constructorWithPostfixAndCopy) TEST(MappedName, copyConstructorStartpos) { + // Arrange Data::MappedName temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + + // Act Data::MappedName mappedName = Data::MappedName(temp, 2, -1); + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 13); @@ -120,8 +158,13 @@ TEST(MappedName, copyConstructorStartpos) TEST(MappedName, copyConstructorStartposAndSize) { + // Arrange Data::MappedName temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + + // Act Data::MappedName mappedName = Data::MappedName(temp, 2, 6); + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 6); @@ -131,8 +174,13 @@ TEST(MappedName, copyConstructorStartposAndSize) TEST(MappedName, moveConstructor) { + // Arrange Data::MappedName temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + + // Act Data::MappedName mappedName = Data::MappedName(std::move(temp)); + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 15); @@ -148,66 +196,84 @@ TEST(MappedName, moveConstructor) TEST(MappedName, fromRawData) { - Data::MappedName mappedName = Data::MappedName::fromRawData("TEST\0\0TEST", 10); + // Act + Data::MappedName mappedName = Data::MappedName::fromRawData("TESTTEST", 10); + + // Assert EXPECT_EQ(mappedName.isRaw(), true); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 10); - EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST\0\0TEST", 10)); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TESTTEST", 10)); EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); } TEST(MappedName, fromRawDataQByteArray) { - Data::MappedName mappedName = Data::MappedName::fromRawData(QByteArray("TEST\0\0TEST", 10)); + // Act + Data::MappedName mappedName = Data::MappedName::fromRawData(QByteArray("TESTTEST", 10)); + + // Assert EXPECT_EQ(mappedName.isRaw(), true); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 10); - EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST\0\0TEST", 10)); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TESTTEST", 10)); EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); } TEST(MappedName, fromRawDataCopy) { - Data::MappedName temp = Data::MappedName::fromRawData(QByteArray("TEST\0\0TEST", 10)); + // Arrange + Data::MappedName temp = Data::MappedName::fromRawData(QByteArray("TESTTEST", 10)); temp.append("TESTPOSTFIX"); + + // Act Data::MappedName mappedName = Data::MappedName::fromRawData(temp, 0); + + // Assert EXPECT_EQ(mappedName.isRaw(), true); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 21); - EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST\0\0TEST", 10)); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TESTTEST", 10)); EXPECT_EQ(mappedName.postfixBytes(), QByteArray("TESTPOSTFIX")); } - -TEST(MappedName, fromRawDataCopyStartposAndSize) +TEST(MappedName, fromRawDataCopyStartposAndSize) //FIXME { - Data::MappedName temp = Data::MappedName::fromRawData(QByteArray("TEST\0\0TEST", 10)); + // Arrange + Data::MappedName temp = Data::MappedName::fromRawData(QByteArray("TESTTEST", 8)); temp.append("ABCDEFGHIJKLM"); //postfix + /* This block is OK EXPECT_EQ(temp.isRaw(), true); EXPECT_EQ(temp.empty(), false); - EXPECT_EQ(temp.size(), 23); - EXPECT_EQ(temp.dataBytes(), QByteArray("TEST\0\0TEST", 10)); + EXPECT_EQ(temp.size(), 21); + EXPECT_EQ(temp.dataBytes(), QByteArray("TESTTEST", 8)); EXPECT_EQ(temp.postfixBytes(), QByteArray("ABCDEFGHIJKLM")); */ + // Act Data::MappedName mappedName = Data::MappedName::fromRawData(temp, 2, 13); + + // Assert EXPECT_EQ(mappedName.isRaw(), true); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 13); - //next line fails with CDE\0TEST != ST\0\0TEST + //next line fails with TEST\0T != STTEST //funny thing if i uncomment the block above, which does nothing, now the next line - //fails with CDE\0GHIJ != ST\0\0TEST - EXPECT_EQ(mappedName.dataBytes(), QByteArray("ST\0\0TEST", 8)); - EXPECT_EQ(mappedName.postfixBytes(), QByteArray("ABCDE")); + //fails with TEST\0H != STTEST + EXPECT_EQ(mappedName.dataBytes(), QByteArray("STTEST", 6)); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray("ABCDEFG")); } -//TODO raw postfix? answer: apparently postfix will never be raw. See copy() - TEST(MappedName, assignmentOperator) { + // Arrange Data::MappedName temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + + // Act Data::MappedName mappedName = temp; + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 15); @@ -217,8 +283,13 @@ TEST(MappedName, assignmentOperator) TEST(MappedName, assignmentOperatorString) { + // Arrange Data::MappedName mappedName; + + // Act mappedName = std::string("TEST"); + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 4); @@ -228,8 +299,13 @@ TEST(MappedName, assignmentOperatorString) TEST(MappedName, assignmentOperatorConstCharPtr) { + // Arrange Data::MappedName mappedName; + + // Act mappedName = "TEST"; + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 4); @@ -237,10 +313,15 @@ TEST(MappedName, assignmentOperatorConstCharPtr) EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); } -TEST(MappedName, operatorEqualMove) +TEST(MappedName, assignmentOperatorMove) { + // Arrange Data::MappedName temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + + // Act Data::MappedName mappedName = std::move(temp); + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 15); @@ -256,27 +337,26 @@ TEST(MappedName, operatorEqualMove) TEST(MappedName, streamInsertionOperator) { + // Arrange Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); - EXPECT_EQ(mappedName.isRaw(), false); - EXPECT_EQ(mappedName.empty(), false); - EXPECT_EQ(mappedName.size(), 15); - EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); - EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POSTFIXTEST")); - + // Act std::stringstream ss; ss << mappedName; + + // Assert EXPECT_EQ(ss.str(), std::string("TESTPOSTFIXTEST")); } - TEST(MappedName, comparisonOperators) { + // Arrange Data::MappedName mappedName1 = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); Data::MappedName mappedName2 = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); Data::MappedName mappedName3 = Data::MappedName(Data::MappedName("TESTPOST"), "FIXTEST"); Data::MappedName mappedName4 = Data::MappedName(Data::MappedName("THIS"), "ISDIFFERENT"); - + + // Act & Assert EXPECT_EQ(mappedName1 == mappedName1, true); EXPECT_EQ(mappedName1 == mappedName2, true); EXPECT_EQ(mappedName1 == mappedName3, true); @@ -290,50 +370,68 @@ TEST(MappedName, comparisonOperators) TEST(MappedName, additionOperators) { - Data::MappedName mappedName1 = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); - mappedName1 += "POST1"; - mappedName1 += std::string("POST2"); - mappedName1 += QByteArray("POST3"); - mappedName1 += Data::MappedName("POST4"); + // Arrange + Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + + // Act + mappedName += "POST1"; + mappedName += std::string("POST2"); + mappedName += QByteArray("POST3"); + mappedName += Data::MappedName("POST4"); + + // Assert + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 35); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POSTFIXTESTPOST1POST2POST3POST4")); - EXPECT_EQ(mappedName1.isRaw(), false); - EXPECT_EQ(mappedName1.empty(), false); - EXPECT_EQ(mappedName1.size(), 35); - EXPECT_EQ(mappedName1.dataBytes(), QByteArray("TEST")); - EXPECT_EQ(mappedName1.postfixBytes(), QByteArray("POSTFIXTESTPOST1POST2POST3POST4")); + // Arrange + mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); - mappedName1 = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); - mappedName1 = mappedName1 + Data::MappedName("POST5"); - mappedName1 = mappedName1 + "POST6"; - mappedName1 = mappedName1 + std::string("POST7"); - mappedName1 = mappedName1 + QByteArray("POST8"); - - EXPECT_EQ(mappedName1.isRaw(), false); - EXPECT_EQ(mappedName1.empty(), false); - EXPECT_EQ(mappedName1.size(), 35); - EXPECT_EQ(mappedName1.dataBytes(), QByteArray("TEST")); - EXPECT_EQ(mappedName1.postfixBytes(), QByteArray("POSTFIXTESTPOST5POST6POST7POST8")); + // Act + mappedName = mappedName + Data::MappedName("POST5"); + mappedName = mappedName + "POST6"; + mappedName = mappedName + std::string("POST7"); + mappedName = mappedName + QByteArray("POST8"); + + // Assert + EXPECT_EQ(mappedName.isRaw(), false); + EXPECT_EQ(mappedName.empty(), false); + EXPECT_EQ(mappedName.size(), 35); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); + EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POSTFIXTESTPOST5POST6POST7POST8")); } - TEST(MappedName, append) { + // Arrange Data::MappedName mappedName = Data::MappedName(); + + // Act mappedName.append("TEST"); + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 4); EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); EXPECT_EQ(mappedName.postfixBytes(), QByteArray("")); + // Act mappedName.append("POSTFIX"); + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 11); EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POSTFIX")); + // Act mappedName.append("ANOTHERPOSTFIX", 5); + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 16); @@ -341,19 +439,26 @@ TEST(MappedName, append) EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POSTFIXANOTH")); } - TEST(MappedName, appendMappedNameObj) { + // Arrange Data::MappedName mappedName = Data::MappedName(); + Data::MappedName temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); - mappedName.append(Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST")); + // Act + mappedName.append(temp); + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 15); EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POSTFIXTEST")); - mappedName.append(Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"), 2, 7); + // Act + mappedName.append(temp, 2, 7); + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 22); @@ -363,29 +468,43 @@ TEST(MappedName, appendMappedNameObj) TEST(MappedName, toString) { + // Arrange Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + + // Act & Assert EXPECT_EQ(mappedName.toString(0), "TESTPOSTFIXTEST"); EXPECT_EQ(mappedName.toString(0), std::string("TESTPOSTFIXTEST")); EXPECT_EQ(mappedName.toString(2, 8), "STPOSTFI"); EXPECT_EQ(mappedName.toString(2, 8), std::string("STPOSTFI")); } - TEST(MappedName, toConstString) { + // Arrange Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); int size; + + // Act const char *temp = mappedName.toConstString(0, size); + + // Assert EXPECT_EQ(QByteArray(temp, size), QByteArray("TEST")); EXPECT_EQ(size, 4); + + // Act const char *temp2 = mappedName.toConstString(7, size); + + // Assert EXPECT_EQ(QByteArray(temp2, size), QByteArray("TFIXTEST")); EXPECT_EQ(size, 8); } TEST(MappedName, toRawBytes) { + // Arrange Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + + // Act & Assert EXPECT_EQ(mappedName.toRawBytes(), QByteArray("TESTPOSTFIXTEST")); EXPECT_EQ(mappedName.toRawBytes(3), QByteArray("TPOSTFIXTEST")); EXPECT_EQ(mappedName.toRawBytes(7, 3), QByteArray("TFI")); @@ -394,20 +513,24 @@ TEST(MappedName, toRawBytes) TEST(MappedName, toBytes) { + // Arrange Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + + // Act & Assert EXPECT_EQ(mappedName.toBytes(), QByteArray("TESTPOSTFIXTEST")); } - TEST(MappedName, compare) { + // Arrange Data::MappedName mappedName1 = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); Data::MappedName mappedName2 = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); Data::MappedName mappedName3 = Data::MappedName(Data::MappedName("TESTPOST"), "FIXTEST"); Data::MappedName mappedName4 = Data::MappedName(Data::MappedName("THIS"), "ISDIFFERENT"); Data::MappedName mappedName5 = Data::MappedName(Data::MappedName("SH"), "ORTHER"); Data::MappedName mappedName6 = Data::MappedName(Data::MappedName("VERYVERYVERY"), "VERYMUCHLONGER"); - + + // Act & Assert EXPECT_EQ(mappedName1.compare(mappedName1), 0); EXPECT_EQ(mappedName1.compare(mappedName2), 0); EXPECT_EQ(mappedName1.compare(mappedName3), 0); @@ -423,9 +546,12 @@ TEST(MappedName, compare) EXPECT_EQ(mappedName1 < mappedName6, true); } -TEST(MappedName, indexOperator) +TEST(MappedName, subscriptOperator) { + // Arrange Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + + // Act & Assert EXPECT_EQ(mappedName[0], 'T'); EXPECT_EQ(mappedName[1], 'E'); EXPECT_EQ(mappedName[2], 'S'); @@ -440,48 +566,65 @@ TEST(MappedName, indexOperator) TEST(MappedName, copy) { + // Arrange Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + + // Act Data::MappedName mappedName2 = mappedName.copy(); + + // Assert EXPECT_EQ(mappedName, mappedName2); } - TEST(MappedName, compact) { - Data::MappedName mappedName = Data::MappedName::fromRawData("TEST\0\0TEST", 10); - EXPECT_EQ(mappedName.isRaw(), true); - EXPECT_EQ(mappedName.empty(), false); - EXPECT_EQ(mappedName.size(), 10); - EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST\0\0TEST", 10)); - EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); + // Arrange + Data::MappedName mappedName = Data::MappedName::fromRawData("TESTTEST", 10); + // Act mappedName.compact(); + + // Assert EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 10); - EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST\0\0TEST", 10)); + EXPECT_EQ(mappedName.dataBytes(), QByteArray("TESTTEST", 10)); EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); } TEST(MappedName, boolOperator) { + // Arrange Data::MappedName mappedName = Data::MappedName(); + + // Act & Assert EXPECT_EQ((bool)mappedName, false); + + // Arrange mappedName.append("TEST"); + + // Act & Assert EXPECT_EQ((bool)mappedName, true); } TEST(MappedName, clear) { + // Arrange Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); - EXPECT_EQ(mappedName.empty(), false); + + // Act mappedName.clear(); + + // Assert EXPECT_EQ(mappedName.empty(), true); } TEST(MappedName, find) { + // Arrange Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + + // Act & Assert EXPECT_EQ(mappedName.find(nullptr), -1); EXPECT_EQ(mappedName.find(""), 0); EXPECT_EQ(mappedName.find("TEST"), 0); @@ -494,10 +637,12 @@ TEST(MappedName, find) EXPECT_EQ(mappedName.find(std::string("")), 0); } - TEST(MappedName, rfind) { + // Arrange Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + + // Act & Assert EXPECT_EQ(mappedName.rfind(nullptr), -1); EXPECT_EQ(mappedName.rfind(""), mappedName.size()); EXPECT_EQ(mappedName.rfind("TEST"), 11); @@ -544,24 +689,31 @@ TEST(MappedName, rfind) TEST(MappedName, endswith) { + // Arrange Data::MappedName mappedName = Data::MappedName("TEST"); + + // Act & Assert EXPECT_EQ(mappedName.endsWith(nullptr), false); EXPECT_EQ(mappedName.endsWith("TEST"), true); EXPECT_EQ(mappedName.endsWith("WASD"), false); EXPECT_EQ(mappedName.endsWith(std::string("TEST")), true); + // Arrange mappedName.append("POSTFIX"); - + + // Act & Assert EXPECT_EQ(mappedName.endsWith(nullptr), false); EXPECT_EQ(mappedName.endsWith("TEST"), false); EXPECT_EQ(mappedName.endsWith("FIX"), true); } - TEST(MappedName, startsWith) { + // Arrange Data::MappedName mappedName = Data::MappedName("TEST"); + + // Act & Assert EXPECT_EQ(mappedName.startsWith(QByteArray()), true); EXPECT_EQ(mappedName.startsWith("TEST"), true); EXPECT_EQ(mappedName.startsWith("WASD"), false); @@ -572,5 +724,7 @@ TEST(MappedName, startsWith) } //TODO test hash function +//TODO test indexedName functions + // clang-format on \ No newline at end of file From cd57046c7a145d976dbee25af58f514393d69d86 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Wed, 15 Mar 2023 22:09:17 -0500 Subject: [PATCH 05/12] App/Toponaming: MappedName clang-tidy cleanup --- src/App/MappedName.h | 670 +++++++++++++++++++++++-------------------- 1 file changed, 363 insertions(+), 307 deletions(-) diff --git a/src/App/MappedName.h b/src/App/MappedName.h index 89e95fd4ad..6a84b19a42 100644 --- a/src/App/MappedName.h +++ b/src/App/MappedName.h @@ -21,8 +21,8 @@ ****************************************************************************/ -#ifndef _AppMappedName_h_ -#define _AppMappedName_h_ +#ifndef APP_MAPPED_NAME_H +#define APP_MAPPED_NAME_H #include @@ -33,152 +33,164 @@ #include #include "ComplexGeoData.h" +#include "IndexedName.h" namespace Data { +// NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) class AppExport MappedName { public: - - explicit MappedName(const char * name, int size = -1) - : raw(false) - { - if (!name) return; - if (boost::starts_with(name, ComplexGeoData::elementMapPrefix())) + explicit MappedName(const char* name, int size = -1) + : raw(false) + { + if (!name) { + return; + } + if (boost::starts_with(name, ComplexGeoData::elementMapPrefix())) { name += ComplexGeoData::elementMapPrefix().size(); + } data = size < 0 ? QByteArray(name) : QByteArray(name, size); } - explicit MappedName(const std::string & name) - : raw(false) + explicit MappedName(const std::string& nameString) + : raw(false) { - int size = name.size(); - const char *n = name.c_str(); - if (boost::starts_with(name, ComplexGeoData::elementMapPrefix())) { - n += ComplexGeoData::elementMapPrefix().size(); + auto size = nameString.size(); + const char* name = nameString.c_str(); + if (boost::starts_with(nameString, ComplexGeoData::elementMapPrefix())) { + name += ComplexGeoData::elementMapPrefix().size(); size -= ComplexGeoData::elementMapPrefix().size(); } - data = QByteArray(n, size); + data = QByteArray(name, static_cast(size)); } -/* - explicit MappedName(const IndexedName & element) - : data(element.getType()), raw(false) + + explicit MappedName(const IndexedName& element) + : data(element.getType()), + raw(false) { - if (element.getIndex() > 0) + if (element.getIndex() > 0) { data += QByteArray::number(element.getIndex()); + } } -*/ + MappedName() : raw(false) {} - MappedName(const MappedName & other) - : data(other.data), postfix(other.postfix), raw(other.raw) - {} + MappedName(const MappedName& other) = default; - //FIXME if you pass a raw MappedName into these constructors they will - //reset raw to false and things will break. is this intended? + // FIXME if you pass a raw MappedName into these constructors they will + // reset raw to false and things will break. is this intended? - MappedName(const MappedName & other, int startpos, int size = -1) + MappedName(const MappedName& other, int startPosition, int size = -1) : raw(false) { - append(other, startpos, size); + append(other, startPosition, size); } - MappedName(const MappedName & other, const char *postfix) - : data(other.data + other.postfix), postfix(postfix), raw(false) - {} - - MappedName(MappedName &&other) - : data(std::move(other.data)), postfix(std::move(other.postfix)), raw(other.raw) + MappedName(const MappedName& other, const char* postfix) + : data(other.data + other.postfix), + postfix(postfix), + raw(false) {} - static MappedName fromRawData(const char * name, int size = -1) + MappedName(MappedName&& other) noexcept + : data(std::move(other.data)), + postfix(std::move(other.postfix)), + raw(other.raw) + {} + + ~MappedName() = default; + + static MappedName fromRawData(const char* name, int size = -1) { MappedName res; if (name) { - res.data = QByteArray::fromRawData(name, size>=0 ? size : qstrlen(name)); + res.data = + QByteArray::fromRawData(name, size >= 0 ? size : static_cast(qstrlen(name))); res.raw = true; } return res; } - static MappedName fromRawData(const QByteArray & data) + static MappedName fromRawData(const QByteArray& data) { return fromRawData(data.constData(), data.size()); } - static MappedName fromRawData(const MappedName &other, int startpos, int size = -1) + static MappedName fromRawData(const MappedName& other, int startPosition, int size = -1) { - if (startpos < 0) - startpos = 0; + if (startPosition < 0) { + startPosition = 0; + } - if (startpos >= other.size()) - return MappedName(); + if (startPosition >= other.size()) { + return {}; + } - if (startpos >= other.data.size()) - return MappedName(other, startpos, size); + if (startPosition >= other.data.size()) { + return {other, startPosition, size}; + } MappedName res; res.raw = true; - if (size < 0) - size = other.size() - startpos; + if (size < 0) { + size = other.size() - startPosition; + } - if (size < other.data.size() - startpos) { - res.data = QByteArray::fromRawData(other.data.constData() + startpos, size); + if (size < other.data.size() - startPosition) { + res.data = QByteArray::fromRawData(other.data.constData() + startPosition, size); } else { - res.data = QByteArray::fromRawData(other.data.constData() + startpos, other.data.size() - startpos); - size -= other.data.size() - startpos; - if (size == other.postfix.size()) + res.data = QByteArray::fromRawData(other.data.constData() + startPosition, + other.data.size() - startPosition); + size -= other.data.size() - startPosition; + if (size == other.postfix.size()) { res.postfix = other.postfix; - else if (size) + } + else if (size != 0) { res.postfix.append(other.postfix.constData(), size); + } } return res; } - MappedName & operator=(const MappedName & other) + MappedName& operator=(const MappedName& other) = default; + + MappedName& operator=(const std::string& other) { - this->data = other.data; - this->postfix = other.postfix; + *this = MappedName(other); + return *this; + } + + MappedName& operator=(const char* other) + { + *this = MappedName(other); + return *this; + } + + + MappedName& operator=(MappedName&& other) noexcept + { + this->data = std::move(other.data); + this->postfix = std::move(other.postfix); this->raw = other.raw; return *this; } - MappedName & operator=(const std::string & other) + friend std::ostream& operator<<(std::ostream& stream, const MappedName& mappedName) { - *this = MappedName(other); - return *this; + stream.write(mappedName.data.constData(), mappedName.data.size()); + stream.write(mappedName.postfix.constData(), mappedName.postfix.size()); + return stream; } - MappedName & operator=(const char * other) - { - *this = MappedName(other); - return *this; - } - - - MappedName & operator=(MappedName &&other) - { - this->data = std::move(other.data); - this->postfix = std::move(other.postfix); - this->raw = other.raw; - return *this; - } - - friend std::ostream & operator<<(std::ostream & s, const MappedName & n) - { - s.write(n.data.constData(), n.data.size()); - s.write(n.postfix.constData(), n.postfix.size()); - return s; - } - - bool operator==(const MappedName & other) const + bool operator==(const MappedName& other) const { if (this->size() != other.size()) { return false; @@ -188,188 +200,204 @@ public: return this->data == other.data && this->postfix == other.postfix; } - const auto &smaller = this->data.size() < other.data.size() ? *this : other; - const auto &larger = this->data.size() < other.data.size() ? other: *this; - + const auto& smaller = this->data.size() < other.data.size() ? *this : other; + const auto& larger = this->data.size() < other.data.size() ? other : *this; + if (!larger.data.startsWith(smaller.data)) { return false; } - QByteArray tmp = QByteArray::fromRawData( - larger.data.constData() + smaller.data.size(), - larger.data.size() - smaller.data.size() - ); - + QByteArray tmp = QByteArray::fromRawData(larger.data.constData() + smaller.data.size(), + larger.data.size() - smaller.data.size()); + if (!smaller.postfix.startsWith(tmp)) { return false; } - tmp = QByteArray::fromRawData( - smaller.postfix.constData() + tmp.size(), - smaller.postfix.size() - tmp.size() - ); + tmp = QByteArray::fromRawData(smaller.postfix.constData() + tmp.size(), + smaller.postfix.size() - tmp.size()); return tmp == larger.postfix; } - bool operator!=(const MappedName & other) const + bool operator!=(const MappedName& other) const { return !(this->operator==(other)); } - MappedName operator+(const MappedName & other) const - { - MappedName res(*this); - res += other; - return res; - } - - MappedName operator+(const char * other) const - { - MappedName res(*this); - res += other; - return res; - } - - MappedName operator+(const std::string & other) const - { - MappedName res(*this); - res += other; - return res; - } - - MappedName operator+(const QByteArray & other) const - { - MappedName res(*this); - res += other; - return res; - } - - MappedName & operator+=(const char * other) - { - if (other && other[0]) - this->postfix.append(other, -1); - return *this; - } - - MappedName & operator+=(const std::string & other) - { - if (other.size()) { - this->postfix.reserve(this->postfix.size() + other.size()); - this->postfix.append(other.c_str(), other.size()); - } - return *this; - } - - MappedName & operator+=(const QByteArray & other) - { - this->postfix += other; - return *this; - } - - MappedName & operator+=(const MappedName & other) - { - append(other); - return *this; - } - - void append(const char * d, int size = -1) + MappedName operator+(const MappedName& other) const { - //FIXME raw not assigned? - if (d && size) { - if (size < 0) - size = qstrlen(d); - if (empty()) - this->data.append(d, size); - else - this->postfix.append(d, size); + MappedName res(*this); + res += other; + return res; + } + + MappedName operator+(const char* other) const + { + MappedName res(*this); + res += other; + return res; + } + + MappedName operator+(const std::string& other) const + { + MappedName res(*this); + res += other; + return res; + } + + MappedName operator+(const QByteArray& other) const + { + MappedName res(*this); + res += other; + return res; + } + + MappedName& operator+=(const char* other) + { + if (other && (other[0] != 0)) { + this->postfix.append(other, -1); + } + return *this; + } + + MappedName& operator+=(const std::string& other) + { + if (!other.empty()) { + this->postfix.reserve(this->postfix.size() + static_cast(other.size())); + this->postfix.append(other.c_str(), static_cast(other.size())); + } + return *this; + } + + MappedName& operator+=(const QByteArray& other) + { + this->postfix += other; + return *this; + } + + MappedName& operator+=(const MappedName& other) + { + append(other); + return *this; + } + + void append(const char* dataToAppend, int size = -1) + { + // FIXME raw not assigned? + if (dataToAppend && (size != 0)) { + if (size < 0) { + size = static_cast(qstrlen(dataToAppend)); + } + if (empty()) { + this->data.append(dataToAppend, size); + } + else { + this->postfix.append(dataToAppend, size); + } } } - void append(const MappedName & other, int startpos = 0, int size = -1) + void append(const MappedName& other, int startPosition = 0, int size = -1) { - // enforce 0 <= startpos <= other.size - if (startpos < 0) - startpos = 0; - else if (startpos > other.size()) + // enforce 0 <= startPosition <= other.size + if (startPosition < 0) { + startPosition = 0; + } + else if (startPosition > other.size()) { return; + } - // enforce 0 <= size <= other.size - startpos - if (size < 0 || size > other.size() - startpos) - size = other.size() - startpos; + // enforce 0 <= size <= other.size - startPosition + if (size < 0 || size > other.size() - startPosition) { + size = other.size() - startPosition; + } - - if (startpos < other.data.size()) // if starting inside data - { + + if (startPosition < other.data.size())// if starting inside data + { int count = size; - //make sure count doesn't exceed data size and end up in postfix - if (count > other.data.size() - startpos) - count = other.data.size() - startpos; - - //if this is empty append in data else append in postfix - if (startpos == 0 && count == other.data.size() && this->empty()) { + // make sure count doesn't exceed data size and end up in postfix + if (count > other.data.size() - startPosition) { + count = other.data.size() - startPosition; + } + + // if this is empty append in data else append in postfix + if (startPosition == 0 && count == other.data.size() && this->empty()) { this->data = other.data; this->raw = other.raw; - } else - append(other.data.constData() + startpos, count); + } + else { + append(other.data.constData() + startPosition, count); + } - //setup startpos and count to contiune appending the remainder to postfix - startpos = 0; + // setup startPosition and count to continue appending the remainder to postfix + startPosition = 0; size -= count; - } - else //else starting inside postfix + } + else// else starting inside postfix { - startpos -= other.data.size(); + startPosition -= other.data.size(); } - //if there is still data to be added to postfix - if (size) { - if (startpos == 0 && size == other.postfix.size()) { - if (this->empty()) + // if there is still data to be added to postfix + if (size != 0) { + if (startPosition == 0 && size == other.postfix.size()) { + if (this->empty()) { this->data = other.postfix; - else if (this->postfix.isEmpty()) + } + else if (this->postfix.isEmpty()) { this->postfix = other.postfix; - else + } + else { this->postfix += other.postfix; - } else - append(other.postfix.constData() + startpos, size); + } + } + else { + append(other.postfix.constData() + startPosition, size); + } } } - std::string toString(int startpos, int len=-1) const + std::string toString(int startPosition, int len = -1) const { std::string res; - return toString(res, startpos, len); + return toString(res, startPosition, len); } - const char * toString(std::string &s, int startpos=0, int len=-1) const + const char* toString(std::string& buffer, int startPosition = 0, int len = -1) const { - std::size_t offset = s.size(); + std::size_t offset = buffer.size(); int count = this->size(); - if (startpos < 0) - startpos = 0; - else if (startpos >= count) - return s.c_str()+s.size(); - if (len < 0 || len > count - startpos) - len = count - startpos; - s.reserve(s.size() + len); - if (startpos < this->data.size()) { - count = this->data.size() - startpos; - if (len < count) + if (startPosition < 0) { + startPosition = 0; + } + else if (startPosition >= count) { + return buffer.c_str() + buffer.size(); + } + if (len < 0 || len > count - startPosition) { + len = count - startPosition; + } + buffer.reserve(buffer.size() + len); + if (startPosition < this->data.size()) { + count = this->data.size() - startPosition; + if (len < count) { count = len; - s.append(this->data.constData()+startpos, count); + } + buffer.append(this->data.constData() + startPosition, count); len -= count; } - s.append(this->postfix.constData(), len); - return s.c_str() + offset; + buffer.append(this->postfix.constData(), len); + return buffer.c_str() + offset; } - //if offset is inside data return data, if offset is > data.size + // if offset is inside data return data, if offset is > data.size //(ends up in postfix) return postfix - const char * toConstString(int offset, int &size) const + const char* toConstString(int offset, int& size) const { - if (offset < 0) + if (offset < 0) { offset = 0; + } if (offset > this->data.size()) { offset -= this->data.size(); if (offset > this->postfix.size()) { @@ -383,63 +411,63 @@ public: return this->data.constData() + offset; } - QByteArray toRawBytes(int offset=0, int size=-1) const + QByteArray toRawBytes(int offset = 0, int size = -1) const { - if (offset < 0) + if (offset < 0) { offset = 0; - if (offset >= this->size()) - return QByteArray(); - if (size < 0 || size > this->size() - offset) + } + if (offset >= this->size()) { + return {}; + } + if (size < 0 || size > this->size() - offset) { size = this->size() - offset; + } if (offset >= this->data.size()) { offset -= this->data.size(); - return QByteArray::fromRawData(this->postfix.constData()+offset, size); + return QByteArray::fromRawData(this->postfix.constData() + offset, size); + } + if (size <= this->data.size() - offset) { + return QByteArray::fromRawData(this->data.constData() + offset, size); } - if (size <= this->data.size() - offset) - return QByteArray::fromRawData(this->data.constData()+offset, size); - QByteArray res(this->data.constData()+offset, this->data.size()-offset); + QByteArray res(this->data.constData() + offset, this->data.size() - offset); res.append(this->postfix.constData(), size - this->data.size() + offset); return res; } - const QByteArray & dataBytes() const + const QByteArray& dataBytes() const { return this->data; } - const QByteArray & postfixBytes() const + const QByteArray& postfixBytes() const { return this->postfix; } - const char * constPostfix() const + const char* constPostfix() const { return this->postfix.constData(); } - // No constData() because 'data' is allow to contain raw data, which may - // not end with 0. -#if 0 - void char * constData() const - { - return this->data.constData(); - } -#endif + // No constData() because 'data' is allowed to contain raw data, which may not end with 0. QByteArray toBytes() const { - if (this->postfix.isEmpty()) + if (this->postfix.isEmpty()) { return this->data; - if (this->data.isEmpty()) + } + if (this->data.isEmpty()) { return this->postfix; + } return this->data + this->postfix; } -/* + IndexedName toIndexedName() const { - if (this->postfix.isEmpty()) + if (this->postfix.isEmpty()) { return IndexedName(this->data); + } return IndexedName(); } @@ -450,52 +478,58 @@ public: return res; } - const char *toPrefixedString(std::string &buf) const + const char* toPrefixedString(std::string& buf) const { - if (!toIndexedName()) + if (!toIndexedName()) { buf += ComplexGeoData::elementMapPrefix(); + } toString(buf); return buf.c_str(); } -*/ - int compare(const MappedName &other) const + + int compare(const MappedName& other) const { - int asize = this->size(); - int bsize = other.size(); - for (int i=0, count=std::min(asize, bsize); ioperator[](i); - char b = other[i]; - if (a < b) + int thisSize = this->size(); + int otherSize = other.size(); + for (int i = 0, count = std::min(thisSize, otherSize); i < count; ++i) { + char thisChar = this->operator[](i); + char otherChar = other[i]; + if (thisChar < otherChar) { return -1; - if (a > b) + } + if (thisChar > otherChar) { return 1; + } } - if (asize < bsize) + if (thisSize < otherSize) { return -1; - if (asize > bsize) + } + if (thisSize > otherSize) { return 1; + } return 0; } - bool operator<(const MappedName & other) const + bool operator<(const MappedName& other) const { return compare(other) < 0; } - char operator[](int index) const - { - //FIXME overflow underflow checks? - if (index >= this->data.size()) + char operator[](int index) const + { + // FIXME overflow underflow checks? + if (index >= this->data.size()) { return this->postfix[index - this->data.size()]; - return this->data[index]; - } + } + return this->data[index]; + } - int size() const + int size() const { return this->data.size() + this->postfix.size(); } - bool empty() const + bool empty() const { return this->data.isEmpty() && this->postfix.isEmpty(); } @@ -507,8 +541,9 @@ public: MappedName copy() const { - if (!this->raw) + if (!this->raw) { return *this; + } MappedName res; res.data.append(this->data.constData(), this->data.size()); res.postfix = this->postfix; @@ -522,92 +557,112 @@ public: return !empty(); } - void clear() + void clear() { this->data.clear(); this->postfix.clear(); this->raw = false; } - int find(const char *d, int startpos = 0) const + int find(const char* searchTarget, int startPosition = 0) const { - if (!d) + if (!searchTarget) { return -1; - if (startpos < 0) - startpos = 0; - if (startpos < this->data.size()) { - int res = this->data.indexOf(d, startpos); - if (res >= 0) + } + if (startPosition < 0) { + startPosition = 0; + } + if (startPosition < this->data.size()) { + int res = this->data.indexOf(searchTarget, startPosition); + if (res >= 0) { return res; - startpos = 0; - } else - startpos -= this->data.size(); - int res = this->postfix.indexOf(d, startpos); - if (res < 0) + } + startPosition = 0; + } + else { + startPosition -= this->data.size(); + } + int res = this->postfix.indexOf(searchTarget, startPosition); + if (res < 0) { return res; + } return res + this->data.size(); } - int find(const std::string &d, int startpos = 0) const + int find(const std::string& searchTarget, int startPosition = 0) const { - return find(d.c_str(), startpos); + return find(searchTarget.c_str(), startPosition); } - int rfind(const char *d, int startpos = -1) const + int rfind(const char* searchTarget, int startPosition = -1) const { - if (!d) + if (!searchTarget) { return -1; - if (startpos < 0 || startpos > this->postfix.size()) { //FIXME should be this->data.size - if (startpos > postfix.size()) - startpos -= postfix.size(); - int res = this->postfix.lastIndexOf(d, startpos); - if (res >= 0) - return res + this->data.size(); - startpos = -1; } - return this->data.lastIndexOf(d, startpos); + if (startPosition < 0 + || startPosition > this->postfix.size()) {// FIXME should be this->data.size + if (startPosition > postfix.size()) { + startPosition -= postfix.size(); + } + int res = this->postfix.lastIndexOf(searchTarget, startPosition); + if (res >= 0) { + return res + this->data.size(); + } + startPosition = -1; + } + return this->data.lastIndexOf(searchTarget, startPosition); } - int rfind(const std::string &d, int startpos = -1) const + int rfind(const std::string& searchTarget, int startPosition = -1) const { - return rfind(d.c_str(), startpos); + return rfind(searchTarget.c_str(), startPosition); } - bool endsWith(const char *s) const + bool endsWith(const char* searchTarget) const { - if (!s) + if (!searchTarget) { return false; - if (this->postfix.size()) - return this->postfix.endsWith(s); - return this->data.endsWith(s); + } + if (this->postfix.size() != 0) { + return this->postfix.endsWith(searchTarget); + } + return this->data.endsWith(searchTarget); } - bool endsWith(const std::string &s) const + bool endsWith(const std::string& searchTarget) const { - return endsWith(s.c_str()); + return endsWith(searchTarget.c_str()); } - bool startsWith(const QByteArray & s, int offset = 0) const + bool startsWith(const QByteArray& searchTarget, int offset = 0) const { - if (s.size() > size() - offset) + if (searchTarget.size() > size() - offset) { return false; - if (offset || (this->data.size() && this->data.size() < s.size())) - return toRawBytes(offset, s.size()) == s; - if (this->data.size()) - return this->data.startsWith(s); - return this->postfix.startsWith(s); + } + if ((offset != 0) + || ((this->data.size() != 0) && this->data.size() < searchTarget.size())) { + return toRawBytes(offset, searchTarget.size()) == searchTarget; + } + if (this->data.size() != 0) { + return this->data.startsWith(searchTarget); + } + return this->postfix.startsWith(searchTarget); } - bool startsWith(const char *s, int offset = 0) const + bool startsWith(const char* searchTarget, int offset = 0) const { - if (!s) + if (!searchTarget) { return false; - return startsWith(QByteArray::fromRawData(s, qstrlen(s)), offset); + } + return startsWith( + QByteArray::fromRawData(searchTarget, static_cast(qstrlen(searchTarget))), offset); } - bool startsWith(const std::string &s, int offset = 0) const + bool startsWith(const std::string& searchTarget, int offset = 0) const { - return startsWith(QByteArray::fromRawData(s.c_str(), s.size()), offset); + return startsWith( + QByteArray::fromRawData(searchTarget.c_str(), static_cast(searchTarget.size())), + offset); } std::size_t hash() const @@ -616,14 +671,15 @@ public: } private: - QByteArray data; - QByteArray postfix; + QByteArray data; + QByteArray postfix; bool raw; }; +// NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic) -} //namespace Data +}// namespace Data -#endif \ No newline at end of file +#endif// APP_MAPPED_NAME_H \ No newline at end of file From e800ae29e1dcab409c995fef89126d7d1096101d Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Thu, 16 Mar 2023 19:54:29 -0500 Subject: [PATCH 06/12] App/Toponaming: Begin adding Doxygen comments --- src/App/MappedName.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/App/MappedName.h b/src/App/MappedName.h index 6a84b19a42..77e51dabf5 100644 --- a/src/App/MappedName.h +++ b/src/App/MappedName.h @@ -44,6 +44,12 @@ namespace Data class AppExport MappedName { public: + /// Create a MappedName from a C string, optionally prefixed by an element map prefix, which + /// will be omitted from the stored MappedName. + /// + /// \param name The new name. A deep copy is made. + /// \param size Optional, the length of the name string. If not provided, the string must be + /// null-terminated. explicit MappedName(const char* name, int size = -1) : raw(false) { @@ -57,6 +63,10 @@ public: data = size < 0 ? QByteArray(name) : QByteArray(name, size); } + /// Create a MappedName from a C++ std::string, optionally prefixed by an element map prefix, + /// which will be omitted from the stored MappedName. + /// + /// \param name The new name. A deep copy is made. explicit MappedName(const std::string& nameString) : raw(false) { @@ -69,6 +79,9 @@ public: data = QByteArray(name, static_cast(size)); } + /// Create a MappedName from an IndexedName. If non-zero, the numerical part of the IndexedName + /// is appended as text to the MappedName. In that case the memory is *not* shared between the + /// original IndexedName and the MappedName. explicit MappedName(const IndexedName& element) : data(element.getType()), raw(false) @@ -87,6 +100,11 @@ public: // FIXME if you pass a raw MappedName into these constructors they will // reset raw to false and things will break. is this intended? + /// Copy constructor with start position offset and optional size. The data is *not* reused. + /// + /// \param other The MappedName to copy + /// \param startPosition an integer offset to start the copy from + /// \param size the number of bytes to copy. If not specified MappedName(const MappedName& other, int startPosition, int size = -1) : raw(false) { From 6c9f1a119d88cb43ffebdf7d5d69c75fe16dfcf1 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Fri, 17 Mar 2023 14:45:41 -0500 Subject: [PATCH 07/12] App/Toponaming: Finish Doxygen comments --- src/App/MappedName.h | 257 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 229 insertions(+), 28 deletions(-) diff --git a/src/App/MappedName.h b/src/App/MappedName.h index 77e51dabf5..0d16018a5b 100644 --- a/src/App/MappedName.h +++ b/src/App/MappedName.h @@ -1,25 +1,26 @@ -/**************************************************************************** - * Copyright (c) 2020 Zheng, Lei (realthunder) * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library 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 Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ****************************************************************************/ +// SPDX-License-Identifier: LGPL-2.1-or-later +/**************************************************************************** + * Copyright (c) 2022 Zheng, Lei (realthunder) * + * 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 * + * . * + * * + ***************************************************************************/ #ifndef APP_MAPPED_NAME_H #define APP_MAPPED_NAME_H @@ -41,6 +42,11 @@ namespace Data // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) +/// The MappedName class maintains a two-part name: the first part ("data") is considered immutable +/// once created, while the second part ("postfix") can be modified/appended to by later operations. +/// It uses shared data when possible (see the fromRawData() members). Despite storing data and +/// postfix separately, they can be accessed via calls to size(), operator[], etc. as though they +/// were a single array. class AppExport MappedName { public: @@ -104,19 +110,25 @@ public: /// /// \param other The MappedName to copy /// \param startPosition an integer offset to start the copy from - /// \param size the number of bytes to copy. If not specified + /// \param size the number of bytes to copy. + /// \see append() for details about how the copy behaves for various sizes and start positions MappedName(const MappedName& other, int startPosition, int size = -1) : raw(false) { append(other, startPosition, size); } + /// Copy constructor with additional postfix + /// + /// \param other The mapped name to copy. Its data and postfix become the new MappedName's data + /// \param postfix The postfix for the new MappedName MappedName(const MappedName& other, const char* postfix) : data(other.data + other.postfix), postfix(postfix), raw(false) {} + /// Move constructor MappedName(MappedName&& other) noexcept : data(std::move(other.data)), postfix(std::move(other.postfix)), @@ -125,6 +137,12 @@ public: ~MappedName() = default; + /// Construct a MappedName from raw character data (including null characters, if size is + /// provided). No copy is made: the data is used in place. + /// + /// \param name The raw data to use. + /// \param size The number of bytes to access. If omitted, name must be null-terminated. + /// \return a new MappedName with name as its data. static MappedName fromRawData(const char* name, int size = -1) { MappedName res; @@ -136,11 +154,25 @@ public: return res; } + /// Construct a MappedName from QByteArray data (including any embedded null characters). + /// + /// \param data The original data. No copy is made, the data is shared with the other instance. + /// \return a new MappedName with data as its data. static MappedName fromRawData(const QByteArray& data) { return fromRawData(data.constData(), data.size()); } + /// Construct a MappedName from another MappedName + /// + /// \param other The MappedName to copy from. The data is usually not copied, but in some + /// cases a partial copy may be made to support a slice that extends across other's data into + /// its postfix. + /// \param startPosition The position to start the reference at. + /// \param size The number of bytes to access. If omitted, continues from startPosition + /// to the end of available data (including postfix). + /// \return a new MappedName sharing (possibly a subset of) data with other. + /// \see append() for details about how the copy behaves for various sizes and start positions static MappedName fromRawData(const MappedName& other, int startPosition, int size = -1) { if (startPosition < 0) { @@ -178,14 +210,17 @@ public: return res; } + /// Share data with another MappedName MappedName& operator=(const MappedName& other) = default; + /// Create a new MappedName from a std::string: the string's data is copied. MappedName& operator=(const std::string& other) { *this = MappedName(other); return *this; } + /// Create a new MappedName from a const char *. The character data is copied. MappedName& operator=(const char* other) { *this = MappedName(other); @@ -193,6 +228,7 @@ public: } + /// Move-construct a MappedName MappedName& operator=(MappedName&& other) noexcept { this->data = std::move(other.data); @@ -201,6 +237,8 @@ public: return *this; } + /// Write to a stream as the name with postfix directly appended to it. Note that there is no + /// special handling for null or non-ASCII characters, they are simply written to the stream. friend std::ostream& operator<<(std::ostream& stream, const MappedName& mappedName) { stream.write(mappedName.data.constData(), mappedName.data.size()); @@ -208,6 +246,8 @@ public: return stream; } + /// Two MappedNames are equal if the concatenation of their data and postfix is equal. The + /// individual data and postfix may NOT be equal in this case. bool operator==(const MappedName& other) const { if (this->size() != other.size()) { @@ -243,6 +283,8 @@ public: return !(this->operator==(other)); } + /// Returns a new MappedName whose data is the LHS argument's data and whose postfix is the LHS + /// argument's postfix with the RHS argument's data and postfix appended to it. MappedName operator+(const MappedName& other) const { MappedName res(*this); @@ -250,6 +292,8 @@ public: return res; } + /// Returns a new MappedName whose data is the LHS argument's data and whose postfix is the LHS + /// argument's postfix with the RHS argument appended to it. The character data is copied. MappedName operator+(const char* other) const { MappedName res(*this); @@ -257,6 +301,8 @@ public: return res; } + /// Returns a new MappedName whose data is the LHS argument's data and whose postfix is the LHS + /// argument's postfix with the RHS argument appended to it. The character data is copied. MappedName operator+(const std::string& other) const { MappedName res(*this); @@ -264,6 +310,8 @@ public: return res; } + /// Returns a new MappedName whose data is the LHS argument's data and whose postfix is the LHS + /// argument's postfix with the RHS argument appended to it. MappedName operator+(const QByteArray& other) const { MappedName res(*this); @@ -271,6 +319,8 @@ public: return res; } + /// Appends other to this instance's postfix. other must be a null-terminated C string. The + /// character data from the string is copied. MappedName& operator+=(const char* other) { if (other && (other[0] != 0)) { @@ -279,6 +329,7 @@ public: return *this; } + /// Appends other to this instance's postfix. The character data from the string is copied. MappedName& operator+=(const std::string& other) { if (!other.empty()) { @@ -288,18 +339,29 @@ public: return *this; } + /// Appends other to this instance's postfix. The data may be either copied or shared, depending + /// on whether this->postfix is empty (in which case the data is shared) or non-empty (in which + /// case it is copied). MappedName& operator+=(const QByteArray& other) { this->postfix += other; return *this; } + /// Appends other to this instance's postfix, unless this is empty, in which case this acts + /// like operator=, and makes this instance's data equal to other's data, and this instance's + /// postfix equal to the other instance's postfix. MappedName& operator+=(const MappedName& other) { append(other); return *this; } + /// Add dataToAppend to this MappedName. If the current name is empty, this becomes the new + /// data element. If this MappedName already has data, then the data is appended to the postfix. + /// + /// \param dataToAppend The data to add. A deep copy is made. + /// \param size The number of bytes to copy. If omitted, dataToAppend must be null-terminated. void append(const char* dataToAppend, int size = -1) { // FIXME raw not assigned? @@ -316,6 +378,20 @@ public: } } + /// Treating both this and other as single continuous byte arrays, append other to this. If this + /// is empty, then other's data is shared with this instance's data beginning at startPosition. + /// If this is *not* empty, then all data is appended to the postfix. If the copy crosses the + /// boundary between other's data and its postfix, then if this instance was empty, the new + /// data stops where other's data stops, and the remainder of the copy is placed in the suffix. + /// Otherwise the copy simply continues as though there was no distinction between other's + /// data and suffix. + /// + /// \param other The MappedName to obtain the data from. The data is shared when possible, + /// depending on the details of startPosition, size, and this->empty(). + /// \param startPosition The byte to start the copy at. Must be a positive non-zero integer less + /// than the length of other's combined data + postfix. + /// \param size The number of bytes to copy. Must not overrun the end of other's combined data + /// storage when taking startPosition into consideration. void append(const MappedName& other, int startPosition = 0, int size = -1) { // enforce 0 <= startPosition <= other.size @@ -377,13 +453,32 @@ public: } } - std::string toString(int startPosition, int len = -1) const + /// Create a std::string from this instance, starting at startPosition, and extending len bytes. + /// + /// \param startPosition The offset into the data + /// \param len The number of bytes to output + /// \return A new std::string containing the bytes copied from this instance's data and postfix + /// (depending on startPosition and len). + /// \note No effort is made to ensure that these are valid ASCII characters, and it is possible + /// the data includes embedded null characters, non-ASCII data, etc. + std::string toString(int startPosition = 0, int len = -1) const { std::string res; - return toString(res, startPosition, len); + return appendToBuffer(res, startPosition, len); } - const char* toString(std::string& buffer, int startPosition = 0, int len = -1) const + /// Given a (possibly non-empty) std::string buffer, append this instance to it, starting at a + /// specified position, and continuing for a specified number of bytes. + /// + /// \param buffer The string buffer to append to. + /// \param startPosition The position in this instance's data/postfix to start at (defaults to + /// zero). Must be less than the total length of the data plus the postfix. + /// \param len The number of bytes to append. If omitted, defaults to appending all available + /// data starting at startPosition. + /// \return A pointer to the beginning of the appended data within buffer. + /// \note No effort is made to ensure that these are valid ASCII characters, and it is possible + /// the data includes embedded null characters, non-ASCII data, etc. + const char* appendToBuffer(std::string& buffer, int startPosition = 0, int len = -1) const { std::size_t offset = buffer.size(); int count = this->size(); @@ -429,6 +524,16 @@ public: return this->data.constData() + offset; } + /// Get access to raw byte data. When possible, data is shared between this instance and the + /// returned QByteArray. If the combination of offset and size results in data that crosses the + /// boundary between this->data and this->postfix, the data must be copied in order to provide + /// access as a continuous array of bytes. + /// + /// \param offset The start position of the raw data access. + /// \param size The number of bytes to access. If omitted, the resulting QByteArray includes + /// everything starting from offset to the end, including any postfix data. + /// \return A new QByteArray that shares data with this instance if possible, or is a new copy + /// if required by offset and size. QByteArray toRawBytes(int offset = 0, int size = -1) const { if (offset < 0) { @@ -453,16 +558,19 @@ public: return res; } + /// Direct access to the stored QByteArray of data. A copy is never made. const QByteArray& dataBytes() const { return this->data; } + /// Direct access to the stored QByteArray of postfix. A copy is never made. const QByteArray& postfixBytes() const { return this->postfix; } + /// Convenience function providing access to the pointer to the beginning of the postfix data. const char* constPostfix() const { return this->postfix.constData(); @@ -470,6 +578,10 @@ public: // No constData() because 'data' is allowed to contain raw data, which may not end with 0. + /// Provide access to the content of this instance. If either postfix or data is empty, no copy + /// is made and the original QByteArray is returned, sharing data with this instance. If this + /// instance contains both data and postfix, a new QByteArray is created and stores a copy of + /// the data and postfix concatenated together. QByteArray toBytes() const { if (this->postfix.isEmpty()) { @@ -481,6 +593,13 @@ public: return this->data + this->postfix; } + /// Create an IndexedName from the data portion of this MappedName. If this data has a postfix, + /// the function returns an empty IndexedName. The function will fail if this->data contains + /// anything other than the ASCII letter a-z, A-Z, and the underscore, with an optional integer + /// suffix, returning an empty IndexedName (e.g. an IndexedName that evaluates to boolean + /// false and isNull() == true). + /// + /// \return a new IndexedName that shares its data with this instance's data member. IndexedName toIndexedName() const { if (this->postfix.isEmpty()) { @@ -489,22 +608,33 @@ public: return IndexedName(); } + /// Create and return a string version of this MappedName prefixed by the ComplexGeoData element + /// map prefix, if this MappedName cannot be converted to an indexed name. std::string toPrefixedString() const { std::string res; - toPrefixedString(res); + appendToBufferWithPrefix(res); return res; } - const char* toPrefixedString(std::string& buf) const + /// Append this MappedName to a provided string buffer, including the ComplexGeoData element + /// map prefix if the MappedName cannot be converted to an IndexedName. + /// + /// \param buf A (possibly non-empty) string to append this MappedName to. + /// \return A pointer to the beginning of the buffer. + const char* appendToBufferWithPrefix(std::string& buf) const { if (!toIndexedName()) { buf += ComplexGeoData::elementMapPrefix(); } - toString(buf); + appendToBuffer(buf); return buf.c_str(); } + /// Equivalent to C++20 operator<=>. Performs byte-by-byte comparison of this and other, + /// starting at the first byte and continuing through both data and postfix, ignoring which is + /// which. If the combined data and postfix members are of unequal size but start with the same + /// data, the shorter array is considered "less than" the longer. int compare(const MappedName& other) const { int thisSize = this->size(); @@ -528,11 +658,14 @@ public: return 0; } + /// \see compare() bool operator<(const MappedName& other) const { return compare(other) < 0; } + /// Treat this MappedName as a single continuous array of bytes, beginning with data and + /// continuing through postfix. No bounds checking is performed when compiled in release mode. char operator[](int index) const { // FIXME overflow underflow checks? @@ -542,21 +675,29 @@ public: return this->data[index]; } + /// Treat this MappedName as a single continuous array of bytes, returning the combined size + /// of the data and postfix. int size() const { return this->data.size() + this->postfix.size(); } + /// Treat this MappedName as a single continuous array of bytes, returning true only if both + /// data and prefix are empty. bool empty() const { return this->data.isEmpty() && this->postfix.isEmpty(); } + /// Returns true if this is shared data, or false if a unique copy has been made. bool isRaw() const { return this->raw; } + /// If this is shared data, a new unshared copy is made and returned. If it is already unshared + /// no new copy is made, a new instance is returned that shares is data with the current + /// instance. MappedName copy() const { if (!this->raw) { @@ -568,13 +709,17 @@ public: return res; } + /// Ensure that this data is unshared, making a copy if necessary. void compact() const; + /// Boolean conversion is the inverse of empty(), returning true if there is data in either the + /// data or postfix, and false if there is nothing in either. explicit operator bool() const { return !empty(); } + /// Reset this instance, clearing anything in data and postfix. void clear() { this->data.clear(); @@ -582,6 +727,12 @@ public: this->raw = false; } + /// Find a string of characters in this MappedName. The bytes must occur either entirely in the + /// data, or entirely in the postfix: a string that overlaps the two will not be found. + /// + /// \param searchTarget A null-terminated C string to search for. + /// \param startPosition A byte offset to start the search at. + /// \return The position of the target in this instance, or -1 if the target is not found. int find(const char* searchTarget, int startPosition = 0) const { if (!searchTarget) { @@ -607,11 +758,25 @@ public: return res + this->data.size(); } + /// Find a string of characters in this MappedName. The bytes must occur either entirely in the + /// data, or entirely in the postfix: a string that overlaps the two will not be found. + /// + /// \param searchTarget A string to search for. + /// \param startPosition A byte offset to start the search at. + /// \return The position of the target in this instance, or -1 if the target is not found. int find(const std::string& searchTarget, int startPosition = 0) const { return find(searchTarget.c_str(), startPosition); } + /// Find a string of characters in this MappedName, starting at the back of postfix and + /// proceeding in reverse through the data. The bytes must occur either entirely in the + /// data, or entirely in the postfix: a string that overlaps the two will not be found. + /// + /// \param searchTarget A null-terminated C string to search for. + /// \param startPosition A byte offset to start the search at. Negative numbers are supported + /// and count back from the end of the concatenated data (as in QByteArray::lastIndexOf()). + /// \return The position of the target in this instance, or -1 if the target is not found. int rfind(const char* searchTarget, int startPosition = -1) const { if (!searchTarget) { @@ -631,11 +796,22 @@ public: return this->data.lastIndexOf(searchTarget, startPosition); } + /// Find a string in this MappedName, starting at the back of postfix and proceeding in reverse + /// through the data. The bytes must occur either entirely in the data, or entirely in the + /// postfix: a string that overlaps the two will not be found. + /// + /// \param searchTarget A null-terminated C string to search for. + /// \param startPosition A byte offset to start the search at. Negative numbers are supported + /// and count back from the end of the concatenated data (as in QByteArray::lastIndexOf()). + /// \return The position of the target in this instance, or -1 if the target is not found. int rfind(const std::string& searchTarget, int startPosition = -1) const { return rfind(searchTarget.c_str(), startPosition); } + /// Returns true if this MappedName ends with the search target. If there is a postfix, only the + /// postfix is considered. If not, then only the data is considered. A search string that + /// overlaps the two will not be found. bool endsWith(const char* searchTarget) const { if (!searchTarget) { @@ -647,11 +823,21 @@ public: return this->data.endsWith(searchTarget); } + /// Returns true if this MappedName ends with the search target. If there is a postfix, only the + /// postfix is considered. If not, then only the data is considered. A search string that + /// overlaps the two will not be found. bool endsWith(const std::string& searchTarget) const { return endsWith(searchTarget.c_str()); } + /// Returns true if this MappedName starts with the search target. If there is a postfix, only + /// the postfix is considered. If not, then only the data is considered. A search string that + /// overlaps the two will not be found. + /// + /// \param searchTarget An array of bytes to match + /// \param offset An offset to perform the match at + /// \return True if this MappedName begins with the target bytes bool startsWith(const QByteArray& searchTarget, int offset = 0) const { if (searchTarget.size() > size() - offset) { @@ -667,6 +853,13 @@ public: return this->postfix.startsWith(searchTarget); } + /// Returns true if this MappedName starts with the search target. If there is a postfix, only + /// the postfix is considered. If not, then only the data is considered. A search string that + /// overlaps the two will not be found. + /// + /// \param searchTarget An array of bytes to match + /// \param offset An offset to perform the match at + /// \return True if this MappedName begins with the target bytes bool startsWith(const char* searchTarget, int offset = 0) const { if (!searchTarget) { @@ -676,6 +869,13 @@ public: QByteArray::fromRawData(searchTarget, static_cast(qstrlen(searchTarget))), offset); } + /// Returns true if this MappedName starts with the search target. If there is a postfix, only + /// the postfix is considered. If not, then only the data is considered. A search string that + /// overlaps the two will not be found. + /// + /// \param searchTarget A string to match + /// \param offset An offset to perform the match at + /// \return True if this MappedName begins with the target bytes bool startsWith(const std::string& searchTarget, int offset = 0) const { return startsWith( @@ -683,6 +883,7 @@ public: offset); } + /// Get a hash for this MappedName std::size_t hash() const { return qHash(data, qHash(postfix)); From 9af5a71e92a020e1ddb466a05d2d93cc6f719b97 Mon Sep 17 00:00:00 2001 From: Pesc0 Date: Sat, 18 Mar 2023 19:44:18 +0100 Subject: [PATCH 08/12] Fixed tests --- src/App/MappedName.h | 12 ++++---- tests/src/App/MappedName.cpp | 56 +++++++++++------------------------- 2 files changed, 21 insertions(+), 47 deletions(-) diff --git a/src/App/MappedName.h b/src/App/MappedName.h index 0d16018a5b..90172b9c99 100644 --- a/src/App/MappedName.h +++ b/src/App/MappedName.h @@ -103,9 +103,6 @@ public: MappedName(const MappedName& other) = default; - // FIXME if you pass a raw MappedName into these constructors they will - // reset raw to false and things will break. is this intended? - /// Copy constructor with start position offset and optional size. The data is *not* reused. /// /// \param other The MappedName to copy @@ -364,7 +361,6 @@ public: /// \param size The number of bytes to copy. If omitted, dataToAppend must be null-terminated. void append(const char* dataToAppend, int size = -1) { - // FIXME raw not assigned? if (dataToAppend && (size != 0)) { if (size < 0) { size = static_cast(qstrlen(dataToAppend)); @@ -690,6 +686,8 @@ public: } /// Returns true if this is shared data, or false if a unique copy has been made. + /// It is safe to access data only if it has been copied prior. To force a copy + /// please \see compact() bool isRaw() const { return this->raw; @@ -783,9 +781,9 @@ public: return -1; } if (startPosition < 0 - || startPosition > this->postfix.size()) {// FIXME should be this->data.size - if (startPosition > postfix.size()) { - startPosition -= postfix.size(); + || startPosition >= this->data.size()) { + if (startPosition >= data.size()) { + startPosition -= data.size(); } int res = this->postfix.lastIndexOf(searchTarget, startPosition); if (res >= 0) { diff --git a/tests/src/App/MappedName.cpp b/tests/src/App/MappedName.cpp index c5e176f540..9ebeb7d41b 100644 --- a/tests/src/App/MappedName.cpp +++ b/tests/src/App/MappedName.cpp @@ -237,19 +237,12 @@ TEST(MappedName, fromRawDataCopy) EXPECT_EQ(mappedName.postfixBytes(), QByteArray("TESTPOSTFIX")); } -TEST(MappedName, fromRawDataCopyStartposAndSize) //FIXME +TEST(MappedName, fromRawDataCopyStartposAndSize) { // Arrange Data::MappedName temp = Data::MappedName::fromRawData(QByteArray("TESTTEST", 8)); temp.append("ABCDEFGHIJKLM"); //postfix - -/* This block is OK - EXPECT_EQ(temp.isRaw(), true); - EXPECT_EQ(temp.empty(), false); - EXPECT_EQ(temp.size(), 21); - EXPECT_EQ(temp.dataBytes(), QByteArray("TESTTEST", 8)); - EXPECT_EQ(temp.postfixBytes(), QByteArray("ABCDEFGHIJKLM")); -*/ + temp.compact(); //Always call compact before accessing data! // Act Data::MappedName mappedName = Data::MappedName::fromRawData(temp, 2, 13); @@ -258,9 +251,6 @@ TEST(MappedName, fromRawDataCopyStartposAndSize) //FIXME EXPECT_EQ(mappedName.isRaw(), true); EXPECT_EQ(mappedName.empty(), false); EXPECT_EQ(mappedName.size(), 13); - //next line fails with TEST\0T != STTEST - //funny thing if i uncomment the block above, which does nothing, now the next line - //fails with TEST\0H != STTEST EXPECT_EQ(mappedName.dataBytes(), QByteArray("STTEST", 6)); EXPECT_EQ(mappedName.postfixBytes(), QByteArray("ABCDEFG")); } @@ -649,40 +639,26 @@ TEST(MappedName, rfind) EXPECT_EQ(mappedName.rfind("STPO"), -1); //sentence must be fully contained in data or postfix EXPECT_EQ(mappedName.rfind("POST"), 4); - - //FIXME looks broken EXPECT_EQ(mappedName.rfind("ST"), 13); EXPECT_EQ(mappedName.rfind("ST", 0), -1); EXPECT_EQ(mappedName.rfind("ST", 1), -1); EXPECT_EQ(mappedName.rfind("ST", 2), 2); EXPECT_EQ(mappedName.rfind("ST", 3), 2); EXPECT_EQ(mappedName.rfind("ST", 4), 2); - EXPECT_EQ(mappedName.rfind("ST", 5), -1); - EXPECT_EQ(mappedName.rfind("ST", 6), -1); - EXPECT_EQ(mappedName.rfind("ST", 7), -1); - EXPECT_EQ(mappedName.rfind("ST", 8), -1); - EXPECT_EQ(mappedName.rfind("ST", 9), -1); - EXPECT_EQ(mappedName.rfind("ST", 10), -1); - EXPECT_EQ(mappedName.rfind("ST", 11), -1); - EXPECT_EQ(mappedName.rfind("ST", 12), 2); - EXPECT_EQ(mappedName.rfind("ST", 13), 6); - EXPECT_EQ(mappedName.rfind("ST", 14), 6); - EXPECT_EQ(mappedName.rfind("ST", 15), 6); - EXPECT_EQ(mappedName.rfind("ST", 16), 6); - EXPECT_EQ(mappedName.rfind("ST", 17), 6); - EXPECT_EQ(mappedName.rfind("ST", 18), 6); - EXPECT_EQ(mappedName.rfind("ST", 19), 6); - EXPECT_EQ(mappedName.rfind("ST", 20), 13); - EXPECT_EQ(mappedName.rfind("ST", 21), 13); - EXPECT_EQ(mappedName.rfind("ST", 22), 13); - EXPECT_EQ(mappedName.rfind("ST", 23), 2); - EXPECT_EQ(mappedName.rfind("ST", 24), 2); - EXPECT_EQ(mappedName.rfind("ST", 25), 2); - EXPECT_EQ(mappedName.rfind("ST", 26), 2); - EXPECT_EQ(mappedName.rfind("ST", 27), 2); - EXPECT_EQ(mappedName.rfind("ST", 28), 2); - //EXPECT_EQ(mappedName.rfind("POST", 7), 4); - //EXPECT_EQ(mappedName.rfind("POST", 8), -1); + EXPECT_EQ(mappedName.rfind("ST", 5), 2); + EXPECT_EQ(mappedName.rfind("ST", 6), 6); + EXPECT_EQ(mappedName.rfind("ST", 7), 6); + EXPECT_EQ(mappedName.rfind("ST", 8), 6); + EXPECT_EQ(mappedName.rfind("ST", 9), 6); + EXPECT_EQ(mappedName.rfind("ST", 10), 6); + EXPECT_EQ(mappedName.rfind("ST", 11), 6); + EXPECT_EQ(mappedName.rfind("ST", 12), 6); + EXPECT_EQ(mappedName.rfind("ST", 13), 13); + EXPECT_EQ(mappedName.rfind("ST", 14), 13); + EXPECT_EQ(mappedName.rfind("ST", 15), 13); + + EXPECT_EQ(mappedName.rfind("POST", 4), 4); + EXPECT_EQ(mappedName.rfind("POST", 3), -1); EXPECT_EQ(mappedName.rfind(std::string("")), mappedName.size()); } From f1f1590639c654e26f20863c5239c76b96b43e8c Mon Sep 17 00:00:00 2001 From: Pesc0 Date: Sun, 19 Mar 2023 00:41:13 +0100 Subject: [PATCH 09/12] Remove use of = operator in object construction --- tests/src/App/MappedName.cpp | 105 +++++++++++++++++------------------ 1 file changed, 51 insertions(+), 54 deletions(-) diff --git a/tests/src/App/MappedName.cpp b/tests/src/App/MappedName.cpp index 9ebeb7d41b..aa959a4665 100644 --- a/tests/src/App/MappedName.cpp +++ b/tests/src/App/MappedName.cpp @@ -14,7 +14,7 @@ TEST(MappedName, defaultConstruction) { // Act - Data::MappedName mappedName = Data::MappedName(); + Data::MappedName mappedName; // Assert EXPECT_EQ(mappedName.isRaw(), false); @@ -27,7 +27,7 @@ TEST(MappedName, defaultConstruction) TEST(MappedName, namedConstruction) { // Act - Data::MappedName mappedName = Data::MappedName("TEST"); + Data::MappedName mappedName("TEST"); // Assert EXPECT_EQ(mappedName.isRaw(), false); @@ -40,7 +40,7 @@ TEST(MappedName, namedConstruction) TEST(MappedName, namedConstructionWithMaxSize) { // Act - Data::MappedName mappedName = Data::MappedName("TEST", 2); + Data::MappedName mappedName("TEST", 2); // Assert EXPECT_EQ(mappedName.isRaw(), false); @@ -56,7 +56,7 @@ TEST(MappedName, namedConstructionDiscardPrefix) std::string name = Data::ComplexGeoData::elementMapPrefix() + "TEST"; // Act - Data::MappedName mappedName = Data::MappedName(name.c_str()); + Data::MappedName mappedName(name.c_str()); // Assert EXPECT_EQ(mappedName.isRaw(), false); @@ -69,7 +69,7 @@ TEST(MappedName, namedConstructionDiscardPrefix) TEST(MappedName, stringNamedConstruction) { // Act - Data::MappedName mappedName = Data::MappedName(std::string("TEST")); + Data::MappedName mappedName(std::string("TEST")); // Assert EXPECT_EQ(mappedName.isRaw(), false); @@ -85,7 +85,7 @@ TEST(MappedName, stringNamedConstructionDiscardPrefix) std::string name = Data::ComplexGeoData::elementMapPrefix() + "TEST"; // Act - Data::MappedName mappedName = Data::MappedName(name); + Data::MappedName mappedName(name); // Assert EXPECT_EQ(mappedName.isRaw(), false); @@ -98,10 +98,10 @@ TEST(MappedName, stringNamedConstructionDiscardPrefix) TEST(MappedName, copyConstructor) { // Arrange - Data::MappedName temp = Data::MappedName("TEST"); + Data::MappedName temp("TEST"); // Act - Data::MappedName mappedName = Data::MappedName(temp); + Data::MappedName mappedName(temp); // Assert EXPECT_EQ(mappedName.isRaw(), false); @@ -114,10 +114,10 @@ TEST(MappedName, copyConstructor) TEST(MappedName, copyConstructorWithPostfix) { // Arrange - Data::MappedName temp = Data::MappedName("TEST"); + Data::MappedName temp("TEST"); // Act - Data::MappedName mappedName = Data::MappedName(temp, "POSTFIXTEST"); + Data::MappedName mappedName(temp, "POSTFIXTEST"); // Assert EXPECT_EQ(mappedName.isRaw(), false); @@ -126,27 +126,24 @@ TEST(MappedName, copyConstructorWithPostfix) EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POSTFIXTEST")); - // Arrange - temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); - // Act - mappedName = Data::MappedName(temp, "ANOTHERPOSTFIX"); + Data::MappedName mappedName2(mappedName, "ANOTHERPOSTFIX"); // Assert - EXPECT_EQ(mappedName.isRaw(), false); - EXPECT_EQ(mappedName.empty(), false); - EXPECT_EQ(mappedName.size(), 29); - EXPECT_EQ(mappedName.dataBytes(), QByteArray("TESTPOSTFIXTEST")); - EXPECT_EQ(mappedName.postfixBytes(), QByteArray("ANOTHERPOSTFIX")); + EXPECT_EQ(mappedName2.isRaw(), false); + EXPECT_EQ(mappedName2.empty(), false); + EXPECT_EQ(mappedName2.size(), 29); + EXPECT_EQ(mappedName2.dataBytes(), QByteArray("TESTPOSTFIXTEST")); + EXPECT_EQ(mappedName2.postfixBytes(), QByteArray("ANOTHERPOSTFIX")); } TEST(MappedName, copyConstructorStartpos) { // Arrange - Data::MappedName temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName temp(Data::MappedName("TEST"), "POSTFIXTEST"); // Act - Data::MappedName mappedName = Data::MappedName(temp, 2, -1); + Data::MappedName mappedName(temp, 2, -1); // Assert EXPECT_EQ(mappedName.isRaw(), false); @@ -159,10 +156,10 @@ TEST(MappedName, copyConstructorStartpos) TEST(MappedName, copyConstructorStartposAndSize) { // Arrange - Data::MappedName temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName temp(Data::MappedName("TEST"), "POSTFIXTEST"); // Act - Data::MappedName mappedName = Data::MappedName(temp, 2, 6); + Data::MappedName mappedName(temp, 2, 6); // Assert EXPECT_EQ(mappedName.isRaw(), false); @@ -175,10 +172,10 @@ TEST(MappedName, copyConstructorStartposAndSize) TEST(MappedName, moveConstructor) { // Arrange - Data::MappedName temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName temp(Data::MappedName("TEST"), "POSTFIXTEST"); // Act - Data::MappedName mappedName = Data::MappedName(std::move(temp)); + Data::MappedName mappedName(std::move(temp)); // Assert EXPECT_EQ(mappedName.isRaw(), false); @@ -258,7 +255,7 @@ TEST(MappedName, fromRawDataCopyStartposAndSize) TEST(MappedName, assignmentOperator) { // Arrange - Data::MappedName temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName temp(Data::MappedName("TEST"), "POSTFIXTEST"); // Act Data::MappedName mappedName = temp; @@ -306,7 +303,7 @@ TEST(MappedName, assignmentOperatorConstCharPtr) TEST(MappedName, assignmentOperatorMove) { // Arrange - Data::MappedName temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName temp(Data::MappedName("TEST"), "POSTFIXTEST"); // Act Data::MappedName mappedName = std::move(temp); @@ -328,7 +325,7 @@ TEST(MappedName, assignmentOperatorMove) TEST(MappedName, streamInsertionOperator) { // Arrange - Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName(Data::MappedName("TEST"), "POSTFIXTEST"); // Act std::stringstream ss; @@ -341,10 +338,10 @@ TEST(MappedName, streamInsertionOperator) TEST(MappedName, comparisonOperators) { // Arrange - Data::MappedName mappedName1 = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); - Data::MappedName mappedName2 = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); - Data::MappedName mappedName3 = Data::MappedName(Data::MappedName("TESTPOST"), "FIXTEST"); - Data::MappedName mappedName4 = Data::MappedName(Data::MappedName("THIS"), "ISDIFFERENT"); + Data::MappedName mappedName1(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName2(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName3(Data::MappedName("TESTPOST"), "FIXTEST"); + Data::MappedName mappedName4(Data::MappedName("THIS"), "ISDIFFERENT"); // Act & Assert EXPECT_EQ(mappedName1 == mappedName1, true); @@ -361,7 +358,7 @@ TEST(MappedName, comparisonOperators) TEST(MappedName, additionOperators) { // Arrange - Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName(Data::MappedName("TEST"), "POSTFIXTEST"); // Act mappedName += "POST1"; @@ -396,7 +393,7 @@ TEST(MappedName, additionOperators) TEST(MappedName, append) { // Arrange - Data::MappedName mappedName = Data::MappedName(); + Data::MappedName mappedName; // Act mappedName.append("TEST"); @@ -432,8 +429,8 @@ TEST(MappedName, append) TEST(MappedName, appendMappedNameObj) { // Arrange - Data::MappedName mappedName = Data::MappedName(); - Data::MappedName temp = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName; + Data::MappedName temp(Data::MappedName("TEST"), "POSTFIXTEST"); // Act mappedName.append(temp); @@ -459,7 +456,7 @@ TEST(MappedName, appendMappedNameObj) TEST(MappedName, toString) { // Arrange - Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName(Data::MappedName("TEST"), "POSTFIXTEST"); // Act & Assert EXPECT_EQ(mappedName.toString(0), "TESTPOSTFIXTEST"); @@ -471,7 +468,7 @@ TEST(MappedName, toString) TEST(MappedName, toConstString) { // Arrange - Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName(Data::MappedName("TEST"), "POSTFIXTEST"); int size; // Act @@ -492,7 +489,7 @@ TEST(MappedName, toConstString) TEST(MappedName, toRawBytes) { // Arrange - Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName(Data::MappedName("TEST"), "POSTFIXTEST"); // Act & Assert EXPECT_EQ(mappedName.toRawBytes(), QByteArray("TESTPOSTFIXTEST")); @@ -504,7 +501,7 @@ TEST(MappedName, toRawBytes) TEST(MappedName, toBytes) { // Arrange - Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName(Data::MappedName("TEST"), "POSTFIXTEST"); // Act & Assert EXPECT_EQ(mappedName.toBytes(), QByteArray("TESTPOSTFIXTEST")); @@ -513,12 +510,12 @@ TEST(MappedName, toBytes) TEST(MappedName, compare) { // Arrange - Data::MappedName mappedName1 = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); - Data::MappedName mappedName2 = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); - Data::MappedName mappedName3 = Data::MappedName(Data::MappedName("TESTPOST"), "FIXTEST"); - Data::MappedName mappedName4 = Data::MappedName(Data::MappedName("THIS"), "ISDIFFERENT"); - Data::MappedName mappedName5 = Data::MappedName(Data::MappedName("SH"), "ORTHER"); - Data::MappedName mappedName6 = Data::MappedName(Data::MappedName("VERYVERYVERY"), "VERYMUCHLONGER"); + Data::MappedName mappedName1(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName2(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName3(Data::MappedName("TESTPOST"), "FIXTEST"); + Data::MappedName mappedName4(Data::MappedName("THIS"), "ISDIFFERENT"); + Data::MappedName mappedName5(Data::MappedName("SH"), "ORTHER"); + Data::MappedName mappedName6(Data::MappedName("VERYVERYVERY"), "VERYMUCHLONGER"); // Act & Assert EXPECT_EQ(mappedName1.compare(mappedName1), 0); @@ -539,7 +536,7 @@ TEST(MappedName, compare) TEST(MappedName, subscriptOperator) { // Arrange - Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName(Data::MappedName("TEST"), "POSTFIXTEST"); // Act & Assert EXPECT_EQ(mappedName[0], 'T'); @@ -557,7 +554,7 @@ TEST(MappedName, subscriptOperator) TEST(MappedName, copy) { // Arrange - Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName(Data::MappedName("TEST"), "POSTFIXTEST"); // Act Data::MappedName mappedName2 = mappedName.copy(); @@ -585,7 +582,7 @@ TEST(MappedName, compact) TEST(MappedName, boolOperator) { // Arrange - Data::MappedName mappedName = Data::MappedName(); + Data::MappedName mappedName; // Act & Assert EXPECT_EQ((bool)mappedName, false); @@ -600,7 +597,7 @@ TEST(MappedName, boolOperator) TEST(MappedName, clear) { // Arrange - Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName(Data::MappedName("TEST"), "POSTFIXTEST"); // Act mappedName.clear(); @@ -612,7 +609,7 @@ TEST(MappedName, clear) TEST(MappedName, find) { // Arrange - Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName(Data::MappedName("TEST"), "POSTFIXTEST"); // Act & Assert EXPECT_EQ(mappedName.find(nullptr), -1); @@ -630,7 +627,7 @@ TEST(MappedName, find) TEST(MappedName, rfind) { // Arrange - Data::MappedName mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + Data::MappedName mappedName(Data::MappedName("TEST"), "POSTFIXTEST"); // Act & Assert EXPECT_EQ(mappedName.rfind(nullptr), -1); @@ -666,7 +663,7 @@ TEST(MappedName, rfind) TEST(MappedName, endswith) { // Arrange - Data::MappedName mappedName = Data::MappedName("TEST"); + Data::MappedName mappedName("TEST"); // Act & Assert EXPECT_EQ(mappedName.endsWith(nullptr), false); @@ -687,7 +684,7 @@ TEST(MappedName, endswith) TEST(MappedName, startsWith) { // Arrange - Data::MappedName mappedName = Data::MappedName("TEST"); + Data::MappedName mappedName("TEST"); // Act & Assert EXPECT_EQ(mappedName.startsWith(QByteArray()), true); From 6b3d99fbbd6b4d726cae0db71fee5226b73d2623 Mon Sep 17 00:00:00 2001 From: Pesc0 Date: Sun, 19 Mar 2023 01:32:29 +0100 Subject: [PATCH 10/12] Improved some tests --- tests/src/App/MappedName.cpp | 56 +++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/tests/src/App/MappedName.cpp b/tests/src/App/MappedName.cpp index aa959a4665..f50b7caa34 100644 --- a/tests/src/App/MappedName.cpp +++ b/tests/src/App/MappedName.cpp @@ -222,6 +222,7 @@ TEST(MappedName, fromRawDataCopy) // Arrange Data::MappedName temp = Data::MappedName::fromRawData(QByteArray("TESTTEST", 10)); temp.append("TESTPOSTFIX"); + temp.compact(); //Always call compact before accessing data! // Act Data::MappedName mappedName = Data::MappedName::fromRawData(temp, 0); @@ -326,9 +327,9 @@ TEST(MappedName, streamInsertionOperator) { // Arrange Data::MappedName mappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + std::stringstream ss; // Act - std::stringstream ss; ss << mappedName; // Assert @@ -614,14 +615,30 @@ TEST(MappedName, find) // Act & Assert EXPECT_EQ(mappedName.find(nullptr), -1); EXPECT_EQ(mappedName.find(""), 0); + EXPECT_EQ(mappedName.find(std::string("")), 0); EXPECT_EQ(mappedName.find("TEST"), 0); EXPECT_EQ(mappedName.find("STPO"), -1); //sentence must be fully contained in data or postfix EXPECT_EQ(mappedName.find("POST"), 4); - EXPECT_EQ(mappedName.find("ST", 3), 6); //found in postfix EXPECT_EQ(mappedName.find("POST", 4), 4); EXPECT_EQ(mappedName.find("POST", 5), -1); - - EXPECT_EQ(mappedName.find(std::string("")), 0); + + EXPECT_EQ(mappedName.rfind("ST"), 13); + EXPECT_EQ(mappedName.rfind("ST", 15), 13); + EXPECT_EQ(mappedName.rfind("ST", 14), 13); + EXPECT_EQ(mappedName.rfind("ST", 13), 13); + EXPECT_EQ(mappedName.rfind("ST", 12), 6); + EXPECT_EQ(mappedName.rfind("ST", 11), 6); + EXPECT_EQ(mappedName.rfind("ST", 10), 6); + EXPECT_EQ(mappedName.rfind("ST", 9), 6); + EXPECT_EQ(mappedName.rfind("ST", 8), 6); + EXPECT_EQ(mappedName.rfind("ST", 7), 6); + EXPECT_EQ(mappedName.rfind("ST", 6), 6); + EXPECT_EQ(mappedName.rfind("ST", 5), 2); + EXPECT_EQ(mappedName.rfind("ST", 4), 2); + EXPECT_EQ(mappedName.rfind("ST", 3), 2); + EXPECT_EQ(mappedName.rfind("ST", 2), 2); + EXPECT_EQ(mappedName.rfind("ST", 1), -1); + EXPECT_EQ(mappedName.rfind("ST", 0), -1); } TEST(MappedName, rfind) @@ -632,9 +649,12 @@ TEST(MappedName, rfind) // Act & Assert EXPECT_EQ(mappedName.rfind(nullptr), -1); EXPECT_EQ(mappedName.rfind(""), mappedName.size()); + EXPECT_EQ(mappedName.rfind(std::string("")), mappedName.size()); EXPECT_EQ(mappedName.rfind("TEST"), 11); EXPECT_EQ(mappedName.rfind("STPO"), -1); //sentence must be fully contained in data or postfix EXPECT_EQ(mappedName.rfind("POST"), 4); + EXPECT_EQ(mappedName.rfind("POST", 4), 4); + EXPECT_EQ(mappedName.rfind("POST", 3), -1); EXPECT_EQ(mappedName.rfind("ST"), 13); EXPECT_EQ(mappedName.rfind("ST", 0), -1); @@ -653,11 +673,6 @@ TEST(MappedName, rfind) EXPECT_EQ(mappedName.rfind("ST", 13), 13); EXPECT_EQ(mappedName.rfind("ST", 14), 13); EXPECT_EQ(mappedName.rfind("ST", 15), 13); - - EXPECT_EQ(mappedName.rfind("POST", 4), 4); - EXPECT_EQ(mappedName.rfind("POST", 3), -1); - - EXPECT_EQ(mappedName.rfind(std::string("")), mappedName.size()); } TEST(MappedName, endswith) @@ -668,9 +683,8 @@ TEST(MappedName, endswith) // Act & Assert EXPECT_EQ(mappedName.endsWith(nullptr), false); EXPECT_EQ(mappedName.endsWith("TEST"), true); - EXPECT_EQ(mappedName.endsWith("WASD"), false); - EXPECT_EQ(mappedName.endsWith(std::string("TEST")), true); + EXPECT_EQ(mappedName.endsWith("WASD"), false); // Arrange mappedName.append("POSTFIX"); @@ -684,16 +698,24 @@ TEST(MappedName, endswith) TEST(MappedName, startsWith) { // Arrange - Data::MappedName mappedName("TEST"); - + Data::MappedName mappedName; + // Act & Assert + EXPECT_EQ(mappedName.startsWith(nullptr), false); + EXPECT_EQ(mappedName.startsWith(QByteArray()), true); + EXPECT_EQ(mappedName.startsWith(""), true); + EXPECT_EQ(mappedName.startsWith(std::string("")), true); + EXPECT_EQ(mappedName.startsWith("WASD"), false); + + // Arrange + mappedName.append("TEST"); + + // Act & Assert + EXPECT_EQ(mappedName.startsWith(nullptr), false); EXPECT_EQ(mappedName.startsWith(QByteArray()), true); EXPECT_EQ(mappedName.startsWith("TEST"), true); - EXPECT_EQ(mappedName.startsWith("WASD"), false); - - EXPECT_EQ(mappedName.startsWith(nullptr), false); - EXPECT_EQ(mappedName.startsWith("TEST"), true); EXPECT_EQ(mappedName.startsWith(std::string("TEST")), true); + EXPECT_EQ(mappedName.startsWith("WASD"), false); } //TODO test hash function From a920d5109f012c457a25df46861ca4e4b985d4aa Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Sat, 18 Mar 2023 20:13:22 -0400 Subject: [PATCH 11/12] App/Toponaming: Add IndexedName tests for MappedName class --- tests/src/App/MappedName.cpp | 81 +++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 19 deletions(-) diff --git a/tests/src/App/MappedName.cpp b/tests/src/App/MappedName.cpp index f50b7caa34..feb16c63d0 100644 --- a/tests/src/App/MappedName.cpp +++ b/tests/src/App/MappedName.cpp @@ -6,11 +6,9 @@ #include "App/ComplexGeoData.h" #include -#include +// NOLINTBEGIN(readability-magic-numbers) - -// clang-format off TEST(MappedName, defaultConstruction) { // Act @@ -95,6 +93,31 @@ TEST(MappedName, stringNamedConstructionDiscardPrefix) EXPECT_EQ(mappedName.postfixBytes(), QByteArray()); } +TEST(MappedName, constructFromIndexedNameNoIndex) +{ + // Arrange + Data::IndexedName indexedName {"INDEXED_NAME"}; + + // Act + Data::MappedName mappedName {indexedName}; + + // Assert + EXPECT_EQ(mappedName.dataBytes().constData(), indexedName.getType()); // shared memory +} + +TEST(MappedName, constructFromIndexedNameWithIndex) +{ + // Arrange + Data::IndexedName indexedName {"INDEXED_NAME", 1}; + + // Act + Data::MappedName mappedName {indexedName}; + + // Assert + EXPECT_NE(mappedName.dataBytes().constData(), indexedName.getType()); // NOT shared memory + EXPECT_EQ(mappedName.toString(), indexedName.toString()); +} + TEST(MappedName, copyConstructor) { // Arrange @@ -183,12 +206,6 @@ TEST(MappedName, moveConstructor) EXPECT_EQ(mappedName.size(), 15); EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POSTFIXTEST")); - - EXPECT_EQ(temp.isRaw(), false); - EXPECT_EQ(temp.empty(), true); - EXPECT_EQ(temp.size(), 0); - EXPECT_EQ(temp.dataBytes(), QByteArray()); - EXPECT_EQ(temp.postfixBytes(), QByteArray()); } TEST(MappedName, fromRawData) @@ -315,12 +332,6 @@ TEST(MappedName, assignmentOperatorMove) EXPECT_EQ(mappedName.size(), 15); EXPECT_EQ(mappedName.dataBytes(), QByteArray("TEST")); EXPECT_EQ(mappedName.postfixBytes(), QByteArray("POSTFIXTEST")); - - EXPECT_EQ(temp.isRaw(), false); - EXPECT_EQ(temp.empty(), true); - EXPECT_EQ(temp.size(), 0); - EXPECT_EQ(temp.dataBytes(), QByteArray()); - EXPECT_EQ(temp.postfixBytes(), QByteArray()); } TEST(MappedName, streamInsertionOperator) @@ -470,7 +481,7 @@ TEST(MappedName, toConstString) { // Arrange Data::MappedName mappedName(Data::MappedName("TEST"), "POSTFIXTEST"); - int size; + int size{0}; // Act const char *temp = mappedName.toConstString(0, size); @@ -499,6 +510,40 @@ TEST(MappedName, toRawBytes) EXPECT_EQ(mappedName.toRawBytes(502, 5), QByteArray()); } +TEST(MappedName, toIndexedNameASCIIOnly) +{ + // Arrange + Data::MappedName mappedName {"MAPPED_NAME"}; + + // Act + auto indexedName = mappedName.toIndexedName(); + + // Assert + EXPECT_FALSE(indexedName.isNull()); +} + +TEST(MappedName, toIndexedNameInvalid) +{ + // Arrange + Data::MappedName mappedName {"MAPPED-NAME"}; + + // Act + auto indexedName = mappedName.toIndexedName(); + + // Assert + EXPECT_TRUE(indexedName.isNull()); +} + +TEST(MappedName, toPrefixedString) +{ + // TODO Write this test +} + +TEST(MappedName, appendToBufferWithPrefix) +{ + // TODO Write this test +} + TEST(MappedName, toBytes) { // Arrange @@ -719,7 +764,5 @@ TEST(MappedName, startsWith) } //TODO test hash function -//TODO test indexedName functions - -// clang-format on \ No newline at end of file +// NOLINTEND(readability-magic-numbers) From 6354c370412eb8dc11a6edc9483860b60981b3f4 Mon Sep 17 00:00:00 2001 From: Pesc0 Date: Sun, 19 Mar 2023 02:55:24 +0100 Subject: [PATCH 12/12] Added all tests and minor fixes --- src/App/MappedName.cpp | 7 ++-- src/App/MappedName.h | 16 +++++--- tests/src/App/MappedName.cpp | 72 ++++++++++++++++++++++++++++++++++-- 3 files changed, 82 insertions(+), 13 deletions(-) diff --git a/src/App/MappedName.cpp b/src/App/MappedName.cpp index f7620ff7c8..ba9b90c2ac 100644 --- a/src/App/MappedName.cpp +++ b/src/App/MappedName.cpp @@ -33,13 +33,12 @@ using namespace Data; -void MappedName::compact() const +void MappedName::compact() { - auto self = const_cast(this); if (this->raw) { - self->data = QByteArray(self->data.constData(), self->data.size()); - self->raw = false; + this->data = QByteArray(this->data.constData(), this->data.size()); + this->raw = false; } #if 0 diff --git a/src/App/MappedName.h b/src/App/MappedName.h index 90172b9c99..84a6ca6927 100644 --- a/src/App/MappedName.h +++ b/src/App/MappedName.h @@ -89,11 +89,12 @@ public: /// is appended as text to the MappedName. In that case the memory is *not* shared between the /// original IndexedName and the MappedName. explicit MappedName(const IndexedName& element) - : data(element.getType()), - raw(false) + : data(QByteArray::fromRawData(element.getType(), qstrlen(element.getType()))), + raw(true) { if (element.getIndex() > 0) { - data += QByteArray::number(element.getIndex()); + this->data += QByteArray::number(element.getIndex()); + this->raw = false; } } @@ -664,8 +665,13 @@ public: /// continuing through postfix. No bounds checking is performed when compiled in release mode. char operator[](int index) const { - // FIXME overflow underflow checks? + if (index < 0) { + index = 0; + } if (index >= this->data.size()) { + if (index - this->data.size() > this->postfix.size() - 1) { + index = this->postfix.size() - 1; + } return this->postfix[index - this->data.size()]; } return this->data[index]; @@ -708,7 +714,7 @@ public: } /// Ensure that this data is unshared, making a copy if necessary. - void compact() const; + void compact(); /// Boolean conversion is the inverse of empty(), returning true if there is data in either the /// data or postfix, and false if there is nothing in either. diff --git a/tests/src/App/MappedName.cpp b/tests/src/App/MappedName.cpp index feb16c63d0..99f833782c 100644 --- a/tests/src/App/MappedName.cpp +++ b/tests/src/App/MappedName.cpp @@ -103,6 +103,7 @@ TEST(MappedName, constructFromIndexedNameNoIndex) // Assert EXPECT_EQ(mappedName.dataBytes().constData(), indexedName.getType()); // shared memory + EXPECT_EQ(mappedName.isRaw(), true); } TEST(MappedName, constructFromIndexedNameWithIndex) @@ -115,6 +116,7 @@ TEST(MappedName, constructFromIndexedNameWithIndex) // Assert EXPECT_NE(mappedName.dataBytes().constData(), indexedName.getType()); // NOT shared memory + EXPECT_EQ(mappedName.isRaw(), false); EXPECT_EQ(mappedName.toString(), indexedName.toString()); } @@ -534,14 +536,69 @@ TEST(MappedName, toIndexedNameInvalid) EXPECT_TRUE(indexedName.isNull()); } -TEST(MappedName, toPrefixedString) +TEST(MappedName, appendToBuffer) { - // TODO Write this test + // Arrange + Data::MappedName mappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + std::string buffer("STUFF"); + + // Act + mappedName.appendToBuffer(buffer); + + // Assert + EXPECT_EQ(buffer, std::string("STUFFTESTPOSTFIXTEST")); + + // Act + mappedName.appendToBuffer(buffer, 2, 7); + + // Assert + EXPECT_EQ(buffer, std::string("STUFFTESTPOSTFIXTESTSTPOSTF")); } TEST(MappedName, appendToBufferWithPrefix) { - // TODO Write this test + // Arrange + Data::MappedName mappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + std::string buffer("STUFF"); + std::string elemMapPrefix = Data::ComplexGeoData::elementMapPrefix(); + + // Act + mappedName.appendToBufferWithPrefix(buffer); + + // Assert + EXPECT_EQ(buffer, std::string("STUFF") + elemMapPrefix + std::string("TESTPOSTFIXTEST")); + + // Arrange + Data::MappedName mappedName2("TEST"); //If mappedName does not have a postfix and is a valid indexedName: prefix is not added + + // Act + mappedName2.appendToBufferWithPrefix(buffer); + + // Assert + EXPECT_EQ(buffer, std::string("STUFF") + elemMapPrefix + std::string("TESTPOSTFIXTEST") + /*missing prefix*/ std::string("TEST")); +} + +TEST(MappedName, toPrefixedString) +{ + // Arrange + Data::MappedName mappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + std::string buffer("STUFF"); + std::string elemMapPrefix = Data::ComplexGeoData::elementMapPrefix(); + + // Act + buffer += mappedName.toPrefixedString(); + + // Assert + EXPECT_EQ(buffer, std::string("STUFF") + elemMapPrefix + std::string("TESTPOSTFIXTEST")); + + // Arrange + Data::MappedName mappedName2("TEST"); //If mappedName does not have a postfix and is a valid indexedName: prefix is not added + + // Act + buffer += mappedName2.toPrefixedString(); + + // Assert + EXPECT_EQ(buffer, std::string("STUFF") + elemMapPrefix + std::string("TESTPOSTFIXTEST") + /*missing prefix*/ std::string("TEST")); } TEST(MappedName, toBytes) @@ -763,6 +820,13 @@ TEST(MappedName, startsWith) EXPECT_EQ(mappedName.startsWith("WASD"), false); } -//TODO test hash function +TEST(MappedName, hash) +{ + // Arrange + Data::MappedName mappedName(Data::MappedName("TEST"), "POSTFIXTEST"); + + // Act & Assert + EXPECT_EQ(mappedName.hash(), qHash(QByteArray("TEST"), qHash(QByteArray("POSTFIXTEST")))); +} // NOLINTEND(readability-magic-numbers)