diff options
| author | Neil <nyamatongwe@gmail.com> | 2019-12-01 19:53:48 +1100 | 
|---|---|---|
| committer | Neil <nyamatongwe@gmail.com> | 2019-12-01 19:53:48 +1100 | 
| commit | 1e5534dde930d2b7eb2580f2c459d1553f3a5971 (patch) | |
| tree | 23dff96fa1a4b856388ce42f420ed4a9797b7108 | |
| parent | 7daa6e47979594525c3dd82bb1afce44ac28b246 (diff) | |
| download | scintilla-mirror-1e5534dde930d2b7eb2580f2c459d1553f3a5971.tar.gz | |
Fix a bug with deleting the first element in SparseVector that left an extra
empty partition.
Add extra checking to Partitioning and turn on checking for UnitTester.
| -rw-r--r-- | src/Partitioning.h | 32 | ||||
| -rw-r--r-- | src/SparseVector.h | 18 | ||||
| -rw-r--r-- | test/unit/UnitTester.vcxproj | 8 | ||||
| -rw-r--r-- | test/unit/testSparseVector.cxx | 16 | 
4 files changed, 64 insertions, 10 deletions
| diff --git a/src/Partitioning.h b/src/Partitioning.h index c6951388e..608a3a58c 100644 --- a/src/Partitioning.h +++ b/src/Partitioning.h @@ -110,6 +110,10 @@ public:  		return static_cast<T>(body->Length())-1;  	} +	T Length() const noexcept { +		return PositionFromPartition(Partitions()); +	} +  	void InsertPartition(T partition, T pos) {  		if (stepPartition < partition) {  			ApplyStep(partition); @@ -196,6 +200,34 @@ public:  	void DeleteAll() {  		Allocate(body->GetGrowSize());  	} + +	void Check() const { +#ifdef CHECK_CORRECTNESS +		if (Length() < 0) { +			throw std::runtime_error("Partitioning: Length can not be negative."); +		} +		if (Partitions() < 1) { +			throw std::runtime_error("Partitioning: Must always have 1 or more partitions."); +		} +		if (Length() == 0) { +			if ((PositionFromPartition(0) != 0) || (PositionFromPartition(1) != 0)) { +				throw std::runtime_error("Partitioning: Invalid empty partitioning."); +			} +		} else { +			// Positions should be a strictly ascending sequence +			for (T i = 0; i < Partitions(); i++) { +				const T pos = PositionFromPartition(i); +				const T posNext = PositionFromPartition(i+1); +				if (pos > posNext) { +					throw std::runtime_error("Partitioning: Negative partition."); +				} else if (pos == posNext) { +					throw std::runtime_error("Partitioning: Empty partition."); +				} +			} +		} +#endif +	} +  }; diff --git a/src/SparseVector.h b/src/SparseVector.h index 2d3e9cfae..97e35d342 100644 --- a/src/SparseVector.h +++ b/src/SparseVector.h @@ -120,6 +120,14 @@ public:  		if (startPartition == position) {  			if (partition == 0) {  				ClearValue(0); +				if (starts->PositionFromPartition(1) == 1) { +					// Removing all space of first partition, so remove next partition +					// and move value if not last +					if (Elements() > 1) { +						starts->RemovePartition(partition + 1); +						values->Delete(partition); +					} +				}  			} else if (partition == starts->Partitions()) {  				// This should not be possible  				ClearValue(partition); @@ -133,14 +141,11 @@ public:  			}  		}  		starts->InsertText(partition, -1); +		Check();  	}  	void Check() const { -		if (Length() < 0) { -			throw std::runtime_error("SparseVector: Length can not be negative."); -		} -		if (starts->Partitions() < 1) { -			throw std::runtime_error("SparseVector: Must always have 1 or more partitions."); -		} +#ifdef CHECK_CORRECTNESS +		starts->Check();  		if (starts->Partitions() != values->Length() - 1) {  			throw std::runtime_error("SparseVector: Partitions and values different lengths.");  		} @@ -148,6 +153,7 @@ public:  		if (values->ValueAt(values->Length() - 1) != T()) {  			throw std::runtime_error("SparseVector: Unused style at end changed.");  		} +#endif  	}  }; diff --git a/test/unit/UnitTester.vcxproj b/test/unit/UnitTester.vcxproj index 0c4d2fb5f..361f41083 100644 --- a/test/unit/UnitTester.vcxproj +++ b/test/unit/UnitTester.vcxproj @@ -87,7 +87,7 @@        </PrecompiledHeader>
        <WarningLevel>Level3</WarningLevel>
        <Optimization>Disabled</Optimization>
 -      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS=1;_HAS_AUTO_PTR_ETC=1;_SCL_SECURE_NO_WARNINGS=1;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
 +      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS=1;_HAS_AUTO_PTR_ETC=1;_SCL_SECURE_NO_WARNINGS=1;CHECK_CORRECTNESS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
        <AdditionalIncludeDirectories>..\..\include\;..\..\src\;..\..\lexlib\</AdditionalIncludeDirectories>
        <LanguageStandard>stdcpp17</LanguageStandard>
      </ClCompile>
 @@ -102,7 +102,7 @@        </PrecompiledHeader>
        <WarningLevel>Level3</WarningLevel>
        <Optimization>Disabled</Optimization>
 -      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS=1;_HAS_AUTO_PTR_ETC=1;_SCL_SECURE_NO_WARNINGS=1;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
 +      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS=1;_HAS_AUTO_PTR_ETC=1;_SCL_SECURE_NO_WARNINGS=1;CHECK_CORRECTNESS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
        <AdditionalIncludeDirectories>..\..\include\;..\..\src\;..\..\lexlib\</AdditionalIncludeDirectories>
        <LanguageStandard>stdcpp17</LanguageStandard>
      </ClCompile>
 @@ -119,7 +119,7 @@        <Optimization>MaxSpeed</Optimization>
        <FunctionLevelLinking>true</FunctionLevelLinking>
        <IntrinsicFunctions>true</IntrinsicFunctions>
 -      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS=1;_HAS_AUTO_PTR_ETC=1;_SCL_SECURE_NO_WARNINGS=1;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
 +      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS=1;_HAS_AUTO_PTR_ETC=1;_SCL_SECURE_NO_WARNINGS=1;CHECK_CORRECTNESS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
        <AdditionalIncludeDirectories>..\..\include\;..\..\src\;..\..\lexlib\</AdditionalIncludeDirectories>
        <LanguageStandard>stdcpp17</LanguageStandard>
      </ClCompile>
 @@ -138,7 +138,7 @@        <Optimization>MaxSpeed</Optimization>
        <FunctionLevelLinking>true</FunctionLevelLinking>
        <IntrinsicFunctions>true</IntrinsicFunctions>
 -      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS=1;_HAS_AUTO_PTR_ETC=1;_SCL_SECURE_NO_WARNINGS=1;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
 +      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS=1;_HAS_AUTO_PTR_ETC=1;_SCL_SECURE_NO_WARNINGS=1;CHECK_CORRECTNESS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
        <AdditionalIncludeDirectories>..\..\include\;..\..\src\;..\..\lexlib\</AdditionalIncludeDirectories>
        <LanguageStandard>stdcpp17</LanguageStandard>
      </ClCompile>
 diff --git a/test/unit/testSparseVector.cxx b/test/unit/testSparseVector.cxx index 5bc710744..7f2a9e9af 100644 --- a/test/unit/testSparseVector.cxx +++ b/test/unit/testSparseVector.cxx @@ -165,6 +165,22 @@ TEST_CASE("SparseVector") {  		st.Check();  	} +	SECTION("CheckDeletionLeavesOrdered") { +		REQUIRE(1 == st.Elements()); +		st.InsertSpace(0, 1); +		st.SetValueAt(0, UniqueStringCopy("1")); +		REQUIRE("1" == Representation(st)); +		REQUIRE(1 == st.Elements()); +		st.InsertSpace(1, 1); +		st.SetValueAt(1, UniqueStringCopy("2")); +		REQUIRE("12" == Representation(st)); +		st.DeletePosition(0); +		REQUIRE("2" == Representation(st)); +		REQUIRE(1 == st.Elements()); +		st.DeletePosition(0); +		REQUIRE("" == Representation(st)); +	} +  	SECTION("DeleteAll") {  		REQUIRE(1 == st.Elements());  		st.InsertSpace(0, 10); | 
