diff options
-rw-r--r-- | src/Partitioning.h | 86 | ||||
-rw-r--r-- | test/unit/testPartitioning.cxx | 23 |
2 files changed, 35 insertions, 74 deletions
diff --git a/src/Partitioning.h b/src/Partitioning.h index 358fbd028..2836b66dd 100644 --- a/src/Partitioning.h +++ b/src/Partitioning.h @@ -10,65 +10,52 @@ namespace Scintilla::Internal { -/// A split vector of integers with a method for adding a value to all elements -/// in a range. -/// Used by the Partitioning class. +/// Divide an interval into multiple partitions. +/// Useful for breaking a document down into sections such as lines. +/// A 0 length interval has a single 0 length partition, numbered 0 +/// If interval not 0 length then each partition non-zero length +/// When needed, positions after the interval are considered part of the last partition +/// but the end of the last partition can be found with PositionFromPartition(last+1). template <typename T> -class SplitVectorWithRangeAdd : public SplitVector<T> { -public: - explicit SplitVectorWithRangeAdd(ptrdiff_t growSize_=8) { - this->SetGrowSize(growSize_); - this->ReAllocate(growSize_); - } +class Partitioning { +private: + // To avoid calculating all the partition positions whenever any text is inserted + // there may be a step somewhere in the list. + T stepPartition; + T stepLength; + SplitVector<T> body; + // Deleted so SplitVectorWithRangeAdd objects can not be copied. - SplitVectorWithRangeAdd(const SplitVectorWithRangeAdd &) = delete; - SplitVectorWithRangeAdd(SplitVectorWithRangeAdd &&) = delete; - SplitVectorWithRangeAdd &operator=(const SplitVectorWithRangeAdd &) = delete; - SplitVectorWithRangeAdd &operator=(SplitVectorWithRangeAdd &&) = default; - ~SplitVectorWithRangeAdd() { - } void RangeAddDelta(T start, T end, T delta) noexcept { // end is 1 past end, so end-start is number of elements to change - ptrdiff_t position = start; + const ptrdiff_t position = start; ptrdiff_t i = 0; const ptrdiff_t rangeLength = end - position; ptrdiff_t range1Length = rangeLength; - const ptrdiff_t part1Left = this->part1Length - position; + const ptrdiff_t part1Left = body.GapPosition() - position; if (range1Length > part1Left) range1Length = part1Left; + T *writer = &body[position]; while (i < range1Length) { - this->body[position++] += delta; + *writer += delta; + writer++; i++; } - position += this->gapLength; - while (i < rangeLength) { - this->body[position++] += delta; - i++; + if (i < rangeLength) { + T *writer2 = &body[position + i]; + while (i < rangeLength) { + *writer2 += delta; + writer2++; + i++; + } } } -}; - -/// Divide an interval into multiple partitions. -/// Useful for breaking a document down into sections such as lines. -/// A 0 length interval has a single 0 length partition, numbered 0 -/// If interval not 0 length then each partition non-zero length -/// When needed, positions after the interval are considered part of the last partition -/// but the end of the last partition can be found with PositionFromPartition(last+1). - -template <typename T> -class Partitioning { -private: - // To avoid calculating all the partition positions whenever any text is inserted - // there may be a step somewhere in the list. - T stepPartition; - T stepLength; - SplitVectorWithRangeAdd<T> body; // Move step forward void ApplyStep(T partitionUpTo) noexcept { if (stepLength != 0) { - body.RangeAddDelta(stepPartition+1, partitionUpTo + 1, stepLength); + RangeAddDelta(stepPartition+1, partitionUpTo + 1, stepLength); } stepPartition = partitionUpTo; if (stepPartition >= Partitions()) { @@ -80,24 +67,17 @@ private: // Move step backward void BackStep(T partitionDownTo) noexcept { if (stepLength != 0) { - body.RangeAddDelta(partitionDownTo+1, stepPartition+1, -stepLength); + RangeAddDelta(partitionDownTo+1, stepPartition+1, -stepLength); } stepPartition = partitionDownTo; } - void Allocate(ptrdiff_t growSize) { - body = SplitVectorWithRangeAdd<T>(growSize); - stepPartition = 0; - stepLength = 0; +public: + explicit Partitioning(size_t growSize=8) : stepPartition(0), stepLength(0), body(growSize) { body.Insert(0, 0); // This value stays 0 for ever body.Insert(1, 0); // This is the end of the first partition and will be the start of the second } -public: - explicit Partitioning(size_t growSize=8) : stepPartition(0), stepLength(0) { - Allocate(growSize); - } - // Deleted so Partitioning objects can not be copied. Partitioning(const Partitioning &) = delete; Partitioning(Partitioning &&) = delete; @@ -224,7 +204,11 @@ public: } void DeleteAll() { - Allocate(body.GetGrowSize()); + body.DeleteAll(); + stepPartition = 0; + stepLength = 0; + body.Insert(0, 0); // This value stays 0 for ever + body.Insert(1, 0); // This is the end of the first partition and will be the start of the second } void Check() const { diff --git a/test/unit/testPartitioning.cxx b/test/unit/testPartitioning.cxx index 7e12c2ff0..fc55b4da1 100644 --- a/test/unit/testPartitioning.cxx +++ b/test/unit/testPartitioning.cxx @@ -25,29 +25,6 @@ using namespace Scintilla::Internal; constexpr int lengthTestArray = 8; static const int testArray[lengthTestArray] = {3, 4, 5, 6, 7, 8, 9, 10}; -// Test SplitVectorWithRangeAdd. - -TEST_CASE("SplitVectorWithRangeAdd") { - - SplitVectorWithRangeAdd<int> svwra; - - SECTION("IsEmptyInitially") { - REQUIRE(0 == svwra.Length()); - } - - SECTION("IncrementExceptEnds") { - svwra.InsertFromArray(0, testArray, 0, lengthTestArray); - svwra.RangeAddDelta(1, lengthTestArray-1, 1); - for (int i=0; i<svwra.Length(); i++) { - if ((i == 0) || (i == lengthTestArray-1)) - REQUIRE((i+3) == svwra.ValueAt(i)); - else - REQUIRE((i+4) == svwra.ValueAt(i)); - } - } - -} - // Test Partitioning. TEST_CASE("Partitioning") { |