diff options
Diffstat (limited to 'src/SparseVector.h')
-rw-r--r-- | src/SparseVector.h | 105 |
1 files changed, 38 insertions, 67 deletions
diff --git a/src/SparseVector.h b/src/SparseVector.h index ce38d0da1..230871ccc 100644 --- a/src/SparseVector.h +++ b/src/SparseVector.h @@ -19,45 +19,18 @@ class SparseVector { private: std::unique_ptr<Partitioning> starts; std::unique_ptr<SplitVector<T>> values; + T empty; // Deleted so SparseVector objects can not be copied. SparseVector(const SparseVector &) = delete; void operator=(const SparseVector &) = delete; void ClearValue(int partition) { values->SetValueAt(partition, T()); } - void CommonSetValueAt(int position, T value) { - // Do the work of setting the value to allow for specialization of SetValueAt. - assert(position < Length()); - const int partition = starts->PartitionFromPosition(position); - const int startPartition = starts->PositionFromPartition(partition); - if (value == T()) { - // Setting the empty value is equivalent to deleting the position - if (position == 0) { - ClearValue(partition); - } else if (position == startPartition) { - // Currently an element at this position, so remove - ClearValue(partition); - starts->RemovePartition(partition); - values->Delete(partition); - } - // Else element remains empty - } else { - if (position == startPartition) { - // Already a value at this position, so replace - ClearValue(partition); - values->SetValueAt(partition, value); - } else { - // Insert a new element - starts->InsertPartition(partition + 1, position); - values->InsertValue(partition + 1, 1, value); - } - } - } public: - SparseVector() { + SparseVector() : empty() { starts.reset(new Partitioning(8)); values.reset(new SplitVector<T>()); - values->InsertValue(0, 2, T()); + values->InsertEmpty(0, 2); } ~SparseVector() { starts.reset(); @@ -76,39 +49,60 @@ public: int PositionOfElement(int element) const { return starts->PositionFromPartition(element); } - T ValueAt(int position) const { + const T& ValueAt(int position) const { assert(position < Length()); const int partition = starts->PartitionFromPosition(position); const int startPartition = starts->PositionFromPartition(partition); if (startPartition == position) { return values->ValueAt(partition); } else { - return T(); + return empty; } } - void SetValueAt(int position, T value) { - CommonSetValueAt(position, value); + template <typename ParamType> + void SetValueAt(int position, ParamType &&value) { + assert(position < Length()); + const int partition = starts->PartitionFromPosition(position); + const int startPartition = starts->PositionFromPartition(partition); + if (value == T()) { + // Setting the empty value is equivalent to deleting the position + if (position == 0) { + ClearValue(partition); + } else if (position == startPartition) { + // Currently an element at this position, so remove + ClearValue(partition); + starts->RemovePartition(partition); + values->Delete(partition); + } + // Else element remains empty + } else { + if (position == startPartition) { + // Already a value at this position, so replace + ClearValue(partition); + values->SetValueAt(partition, std::move(value)); + } else { + // Insert a new element + starts->InsertPartition(partition + 1, position); + values->Insert(partition + 1, std::move(value)); + } + } } void InsertSpace(int position, int insertLength) { assert(position <= Length()); // Only operation that works at end. const int partition = starts->PartitionFromPosition(position); const int startPartition = starts->PositionFromPartition(partition); if (startPartition == position) { - T valueCurrent = values->ValueAt(partition); + const bool positionOccupied = values->ValueAt(partition) != T(); // Inserting at start of run so make previous longer if (partition == 0) { - // Inserting at start of document so ensure 0 - if (valueCurrent != T()) { - // Since valueCurrent is needed again, should not ClearValue - values->SetValueAt(0, T()); + // Inserting at start of document so ensure start empty + if (positionOccupied) { starts->InsertPartition(1, 0); - values->InsertValue(1, 1, valueCurrent); - starts->InsertText(0, insertLength); - } else { - starts->InsertText(partition, insertLength); + values->InsertEmpty(0, 1); } + starts->InsertText(partition, insertLength); } else { - if (valueCurrent != T()) { + if (positionOccupied) { starts->InsertText(partition - 1, insertLength); } else { // Insert at end of run so do not extend style @@ -157,29 +151,6 @@ public: } }; -// The specialization for const char * makes copies and deletes them as needed. - -template<> -inline void SparseVector<const char *>::ClearValue(int partition) { - const char *value = values->ValueAt(partition); - delete []value; - value = nullptr; - values->SetValueAt(partition, value); -} - -template<> -inline void SparseVector<const char *>::SetValueAt(int position, const char *value) { - // Make a copy of the string - if (value) { - const size_t len = strlen(value); - char *valueCopy = new char[len + 1](); - std::copy(value, value + len, valueCopy); - CommonSetValueAt(position, valueCopy); - } else { - CommonSetValueAt(position, nullptr); - } -} - #ifdef SCI_NAMESPACE } #endif |