aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNeil <nyamatongwe@gmail.com>2019-12-01 20:41:27 +1100
committerNeil <nyamatongwe@gmail.com>2019-12-01 20:41:27 +1100
commitda8c1844da6e593644f6ae056560553bb409b354 (patch)
tree201528b619cf13de885ae7b9a08acf3acdb5f7b0
parent1e5534dde930d2b7eb2580f2c459d1553f3a5971 (diff)
downloadscintilla-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.h39
-rw-r--r--test/unit/testContractionState.cxx6
-rw-r--r--test/unit/testSparseVector.cxx65
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") {