diff --git a/io/entry.cpp b/io/entry.cpp index 33fe954..28a0bd7 100644 --- a/io/entry.cpp +++ b/io/entry.cpp @@ -1,6 +1,7 @@ #include "./entry.h" #include "./parsingexception.h" +#include #include #include @@ -58,7 +59,7 @@ Entry::~Entry() } /*! - * \brief Internally called to make the label unique. + * \brief Internally called to make the entry's label unique within the parent. * \sa setLabel() */ void Entry::makeLabelUnique() @@ -66,23 +67,22 @@ void Entry::makeLabelUnique() if (!m_parent) { return; } - int index = 1; - string currentLabel(label()); -checkLabel: - for (Entry *sibling : m_parent->children()) { - if (sibling == this || currentLabel != sibling->label()) { - continue; + string newLabel(label()); + for (unsigned int index = 2;; ++index) { + bool needsNewLabel = false; + for (Entry *const sibling : m_parent->children()) { + if (sibling == this || newLabel != sibling->label()) { + continue; + } + needsNewLabel = true; + newLabel = argsToString(label(), ' ', index); + break; } - stringstream newLabel(currentLabel); - newLabel.seekp(0, ios_base::end); - if (newLabel.tellp()) { - newLabel << ' '; + if (!needsNewLabel) { + break; } - newLabel << ++index; - currentLabel = newLabel.str(); - goto checkLabel; } - m_label = currentLabel; + m_label.swap(newLabel); } /*! diff --git a/tests/entrytests.cpp b/tests/entrytests.cpp index 4a7a6bf..6e9d430 100644 --- a/tests/entrytests.cpp +++ b/tests/entrytests.cpp @@ -35,6 +35,7 @@ class EntryTests : public TestFixture { CPPUNIT_TEST(testNewEntryCorrectlyInitialized); CPPUNIT_TEST(testNesting); CPPUNIT_TEST(testEntryByPath); + CPPUNIT_TEST(testUniqueLabels); CPPUNIT_TEST_SUITE_END(); public: @@ -44,6 +45,7 @@ public: void testNewEntryCorrectlyInitialized(); void testNesting(); void testEntryByPath(); + void testUniqueLabels(); }; CPPUNIT_TEST_SUITE_REGISTRATION(EntryTests); @@ -196,3 +198,14 @@ void EntryTests::testEntryByPath() CPPUNIT_ASSERT_EQUAL_MESSAGE( "path actually correct", list{ "root" CPP_UTILITIES_PP_COMMA "node" CPP_UTILITIES_PP_COMMA "foo" }, nestedAccount->path()); } + +void EntryTests::testUniqueLabels() +{ + NodeEntry root("root"); + const auto *const fooEntry = new AccountEntry("foo", &root); + VAR_UNUSED(fooEntry) + const auto *const foo2Entry = new AccountEntry("foo", &root); + CPPUNIT_ASSERT_EQUAL_MESSAGE("2nd foo renamed to foo 2", "foo 2"s, foo2Entry->label()); + const auto *const foo3Entry = new AccountEntry("foo", &root); + CPPUNIT_ASSERT_EQUAL_MESSAGE("3rd foo renamed to foo 3", "foo 3"s, foo3Entry->label()); +}