diff options
author | Neil <nyamatongwe@gmail.com> | 2019-12-01 20:41:27 +1100 |
---|---|---|
committer | Neil <nyamatongwe@gmail.com> | 2019-12-01 20:41:27 +1100 |
commit | da8c1844da6e593644f6ae056560553bb409b354 (patch) | |
tree | 201528b619cf13de885ae7b9a08acf3acdb5f7b0 | |
parent | 1e5534dde930d2b7eb2580f2c459d1553f3a5971 (diff) | |
download | scintilla-mirror-da8c1844da6e593644f6ae056560553bb409b354.tar.gz |
Allow setting value at end of a SparseVector.
Change representation of SparseVector in tests so last value can be seen.
-rw-r--r-- | src/SparseVector.h | 39 | ||||
-rw-r--r-- | test/unit/testContractionState.cxx | 6 | ||||
-rw-r--r-- | test/unit/testSparseVector.cxx | 65 |
3 files changed, 74 insertions, 36 deletions
diff --git a/src/SparseVector.h b/src/SparseVector.h index 97e35d342..e4e0e3f69 100644 --- a/src/SparseVector.h +++ b/src/SparseVector.h @@ -12,13 +12,17 @@ namespace Scintilla { // SparseVector is similar to RunStyles but is more efficient for cases where values occur // for one position instead of over a range of positions. +// There are always elements at the start and end, so the element type should have +// a reasonable empty value that will cause no problems. +// The element type should have a noexcept default constructor as that allows methods to +// be noexcept. template <typename T> class SparseVector { private: std::unique_ptr<Partitioning<Sci::Position>> starts; std::unique_ptr<SplitVector<T>> values; - T empty; - void ClearValue(Sci::Position partition) { + T empty; // Return from ValueAt when no element at a position. + void ClearValue(Sci::Position partition) noexcept { values->SetValueAt(partition, T()); } public: @@ -40,18 +44,25 @@ public: } values.reset(); } - Sci::Position Length() const { - return starts->PositionFromPartition(starts->Partitions()); + Sci::Position Length() const noexcept { + return starts->Length(); } - Sci::Position Elements() const { + Sci::Position Elements() const noexcept { return starts->Partitions(); } - Sci::Position PositionOfElement(int element) const { + Sci::Position PositionOfElement(Sci::Position element) const noexcept { return starts->PositionFromPartition(element); } - const T& ValueAt(Sci::Position position) const { - assert(position < Length()); - const Sci::Position partition = starts->PartitionFromPosition(position); + Sci::Position ElementFromPosition(Sci::Position position) const noexcept { + if (position < Length()) { + return starts->PartitionFromPosition(position); + } else { + return starts->Partitions(); + } + } + const T& ValueAt(Sci::Position position) const noexcept { + assert(position <= Length()); + const Sci::Position partition = ElementFromPosition(position); const Sci::Position startPartition = starts->PositionFromPartition(partition); if (startPartition == position) { return values->ValueAt(partition); @@ -61,8 +72,8 @@ public: } template <typename ParamType> void SetValueAt(Sci::Position position, ParamType &&value) { - assert(position < Length()); - const Sci::Position partition = starts->PartitionFromPosition(position); + assert(position <= Length()); + const Sci::Position partition = ElementFromPosition(position); const Sci::Position startPartition = starts->PositionFromPartition(partition); if (value == T()) { // Setting the empty value is equivalent to deleting the position @@ -88,7 +99,7 @@ public: } } void InsertSpace(Sci::Position position, Sci::Position insertLength) { - assert(position <= Length()); // Only operation that works at end. + assert(position <= Length()); const Sci::Position partition = starts->PartitionFromPosition(position); const Sci::Position startPartition = starts->PositionFromPartition(partition); if (startPartition == position) { @@ -149,10 +160,6 @@ public: if (starts->Partitions() != values->Length() - 1) { throw std::runtime_error("SparseVector: Partitions and values different lengths."); } - // The final element can not be set - if (values->ValueAt(values->Length() - 1) != T()) { - throw std::runtime_error("SparseVector: Unused style at end changed."); - } #endif } }; diff --git a/test/unit/testContractionState.cxx b/test/unit/testContractionState.cxx index bb45de3bc..524089f7d 100644 --- a/test/unit/testContractionState.cxx +++ b/test/unit/testContractionState.cxx @@ -148,12 +148,18 @@ TEST_CASE("ContractionState") { SECTION("SetFoldDisplayText") { pcs->InsertLines(0, 4); + REQUIRE(5 == pcs->LinesInDoc()); pcs->SetFoldDisplayText(1, "abc"); REQUIRE(strcmp(pcs->GetFoldDisplayText(1), "abc") == 0); pcs->SetFoldDisplayText(1, "def"); REQUIRE(strcmp(pcs->GetFoldDisplayText(1), "def") == 0); pcs->SetFoldDisplayText(1, nullptr); REQUIRE(static_cast<const char *>(nullptr) == pcs->GetFoldDisplayText(1)); + // At end + pcs->SetFoldDisplayText(5, "xyz"); + REQUIRE(strcmp(pcs->GetFoldDisplayText(5), "xyz") == 0); + pcs->DeleteLines(4, 1); + REQUIRE(strcmp(pcs->GetFoldDisplayText(4), "xyz") == 0); } } diff --git a/test/unit/testSparseVector.cxx b/test/unit/testSparseVector.cxx index 7f2a9e9af..67b8a05f8 100644 --- a/test/unit/testSparseVector.cxx +++ b/test/unit/testSparseVector.cxx @@ -28,7 +28,7 @@ using namespace Scintilla; // to simplify checks. static std::string Representation(const SparseVector<UniqueString> &st) { std::string ret; - for (int i = 0;i < st.Length();i++) { + for (int i = 0;i <= st.Length();i++) { const char *value = st.ValueAt(i).get(); if (value && *value) ret += value; @@ -45,6 +45,7 @@ TEST_CASE("SparseVector") { SECTION("IsEmptyInitially") { REQUIRE(1 == st.Elements()); REQUIRE(0 == st.Length()); + REQUIRE("-" == Representation(st)); st.Check(); } @@ -61,7 +62,7 @@ TEST_CASE("SparseVector") { st.InsertSpace(0, 5); st.SetValueAt(3, UniqueStringCopy("3")); REQUIRE(2 == st.Elements()); - REQUIRE("---3-" == Representation(st)); + REQUIRE("---3--" == Representation(st)); st.Check(); } @@ -75,7 +76,7 @@ TEST_CASE("SparseVector") { st.DeletePosition(3); REQUIRE(1 == st.Elements()); REQUIRE(4 == st.Length()); - REQUIRE("----" == Representation(st)); + REQUIRE("-----" == Representation(st)); st.Check(); } @@ -84,7 +85,13 @@ TEST_CASE("SparseVector") { st.InsertSpace(0, 5); st.SetValueAt(0, UniqueStringCopy("3")); REQUIRE(1 == st.Elements()); - REQUIRE("3----" == Representation(st)); + REQUIRE("3-----" == Representation(st)); + st.DeletePosition(0); + REQUIRE(1 == st.Elements()); + REQUIRE("-----" == Representation(st)); + st.SetValueAt(0, UniqueStringCopy("4")); + REQUIRE(1 == st.Elements()); + REQUIRE("4----" == Representation(st)); st.DeletePosition(0); REQUIRE(1 == st.Elements()); REQUIRE("----" == Representation(st)); @@ -102,10 +109,10 @@ TEST_CASE("SparseVector") { st.InsertSpace(0, 5); st.SetValueAt(0, UniqueStringCopy("3")); REQUIRE(1 == st.Elements()); - REQUIRE("3----" == Representation(st)); + REQUIRE("3-----" == Representation(st)); st.InsertSpace(0, 1); REQUIRE(2 == st.Elements()); - REQUIRE("-3----" == Representation(st)); + REQUIRE("-3-----" == Representation(st)); st.Check(); } @@ -114,10 +121,10 @@ TEST_CASE("SparseVector") { st.InsertSpace(0, 5); st.SetValueAt(1, UniqueStringCopy("1")); REQUIRE(2 == st.Elements()); - REQUIRE("-1---" == Representation(st)); + REQUIRE("-1----" == Representation(st)); st.InsertSpace(1, 1); REQUIRE(2 == st.Elements()); - REQUIRE("--1---" == Representation(st)); + REQUIRE("--1----" == Representation(st)); st.Check(); } @@ -126,10 +133,10 @@ TEST_CASE("SparseVector") { st.InsertSpace(0, 5); st.SetValueAt(1, UniqueStringCopy("9")); REQUIRE(2 == st.Elements()); - REQUIRE("-9---" == Representation(st)); + REQUIRE("-9----" == Representation(st)); st.InsertSpace(0, 1); REQUIRE(2 == st.Elements()); - REQUIRE("--9---" == Representation(st)); + REQUIRE("--9----" == Representation(st)); // Initial st has allocation of 9 values so this should cause reallocation const std::string letters("ABCDEFGHIJKLMNOP"); // 16 letters for (const char letter : letters) { @@ -137,7 +144,7 @@ TEST_CASE("SparseVector") { st.InsertSpace(0, 1); st.SetValueAt(1, UniqueStringCopy(sLetter)); } - REQUIRE("-PONMLKJIHGFEDCBA-9---" == Representation(st)); + REQUIRE("-PONMLKJIHGFEDCBA-9----" == Representation(st)); st.Check(); } @@ -146,10 +153,16 @@ TEST_CASE("SparseVector") { st.InsertSpace(0, 5); st.SetValueAt(4, UniqueStringCopy("5")); REQUIRE(2 == st.Elements()); - REQUIRE("----5" == Representation(st)); + REQUIRE("----5-" == Representation(st)); + st.SetValueAt(5, UniqueStringCopy("6")); + REQUIRE(2 == st.Elements()); + REQUIRE("----56" == Representation(st)); st.DeletePosition(4); REQUIRE(1 == st.Elements()); - REQUIRE("----" == Representation(st)); + REQUIRE("----6" == Representation(st)); + st.SetValueAt(4, UniqueStringCopy("7")); + REQUIRE(1 == st.Elements()); + REQUIRE("----7" == Representation(st)); st.Check(); } @@ -158,10 +171,10 @@ TEST_CASE("SparseVector") { st.InsertSpace(0, 5); st.SetValueAt(4, UniqueStringCopy("5")); REQUIRE(2 == st.Elements()); - REQUIRE("----5" == Representation(st)); + REQUIRE("----5-" == Representation(st)); st.SetValueAt(4, nullptr); REQUIRE(1 == st.Elements()); - REQUIRE("-----" == Representation(st)); + REQUIRE("------" == Representation(st)); st.Check(); } @@ -169,16 +182,16 @@ TEST_CASE("SparseVector") { REQUIRE(1 == st.Elements()); st.InsertSpace(0, 1); st.SetValueAt(0, UniqueStringCopy("1")); - REQUIRE("1" == Representation(st)); + REQUIRE("1-" == Representation(st)); REQUIRE(1 == st.Elements()); st.InsertSpace(1, 1); st.SetValueAt(1, UniqueStringCopy("2")); - REQUIRE("12" == Representation(st)); + REQUIRE("12-" == Representation(st)); st.DeletePosition(0); - REQUIRE("2" == Representation(st)); + REQUIRE("2-" == Representation(st)); REQUIRE(1 == st.Elements()); st.DeletePosition(0); - REQUIRE("" == Representation(st)); + REQUIRE("-" == Representation(st)); } SECTION("DeleteAll") { @@ -189,10 +202,22 @@ TEST_CASE("SparseVector") { st.SetValueAt(4, UniqueStringCopy("4")); st.SetValueAt(3, UniqueStringCopy("3")); REQUIRE(5 == st.Elements()); - REQUIRE("---34--7-9" == Representation(st)); + REQUIRE("---34--7-9-" == Representation(st)); st.Check(); } + SECTION("DeleteStarting") { + REQUIRE(1 == st.Elements()); + st.InsertSpace(0, 2); + st.SetValueAt(0, UniqueStringCopy("1")); + st.SetValueAt(1, UniqueStringCopy("2")); + REQUIRE("12-" == Representation(st)); + st.DeletePosition(0); + REQUIRE("2-" == Representation(st)); + st.DeletePosition(0); + REQUIRE("-" == Representation(st)); + } + } TEST_CASE("SparseTextInt") { |