You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
3.0 KiB
107 lines
3.0 KiB
// Scintilla source code edit control |
|
/** @file SparseState.h |
|
** Hold lexer state that may change rarely. |
|
** This is often per-line state such as whether a particular type of section has been entered. |
|
** A state continues until it is changed. |
|
**/ |
|
// Copyright 2011 by Neil Hodgson <neilh@scintilla.org> |
|
// The License.txt file describes the conditions under which this software may be distributed. |
|
|
|
#ifndef SPARSESTATE_H |
|
#define SPARSESTATE_H |
|
|
|
namespace Lexilla { |
|
|
|
template <typename T> |
|
class SparseState { |
|
struct State { |
|
Sci_Position position; |
|
T value; |
|
constexpr State(Sci_Position position_, T value_) noexcept : |
|
position(position_), value(std::move(value_)) { |
|
} |
|
inline bool operator<(const State &other) const noexcept { |
|
return position < other.position; |
|
} |
|
inline bool operator==(const State &other) const noexcept { |
|
return (position == other.position) && (value == other.value); |
|
} |
|
}; |
|
Sci_Position positionFirst; |
|
typedef std::vector<State> stateVector; |
|
stateVector states; |
|
|
|
typename stateVector::iterator Find(Sci_Position position) { |
|
const State searchValue(position, T()); |
|
return std::lower_bound(states.begin(), states.end(), searchValue); |
|
} |
|
|
|
public: |
|
explicit SparseState(Sci_Position positionFirst_=-1) { |
|
positionFirst = positionFirst_; |
|
} |
|
void Set(Sci_Position position, T value) { |
|
Delete(position); |
|
if (states.empty() || (value != states[states.size()-1].value)) { |
|
states.push_back(State(position, value)); |
|
} |
|
} |
|
T ValueAt(Sci_Position position) { |
|
if (states.empty()) |
|
return T(); |
|
if (position < states[0].position) |
|
return T(); |
|
typename stateVector::iterator low = Find(position); |
|
if (low == states.end()) { |
|
return states[states.size()-1].value; |
|
} else { |
|
if (low->position > position) { |
|
--low; |
|
} |
|
return low->value; |
|
} |
|
} |
|
bool Delete(Sci_Position position) { |
|
typename stateVector::iterator low = Find(position); |
|
if (low != states.end()) { |
|
states.erase(low, states.end()); |
|
return true; |
|
} |
|
return false; |
|
} |
|
size_t size() const { |
|
return states.size(); |
|
} |
|
|
|
// Returns true if Merge caused a significant change |
|
bool Merge(const SparseState<T> &other, Sci_Position ignoreAfter) { |
|
// Changes caused beyond ignoreAfter are not significant |
|
Delete(ignoreAfter+1); |
|
|
|
bool different = true; |
|
bool changed = false; |
|
typename stateVector::iterator low = Find(other.positionFirst); |
|
if (static_cast<size_t>(states.end() - low) == other.states.size()) { |
|
// Same number in other as after positionFirst in this |
|
different = !std::equal(low, states.end(), other.states.begin()); |
|
} |
|
if (different) { |
|
if (low != states.end()) { |
|
states.erase(low, states.end()); |
|
changed = true; |
|
} |
|
typename stateVector::const_iterator startOther = other.states.begin(); |
|
if (!states.empty() && !other.states.empty() && states.back().value == startOther->value) |
|
++startOther; |
|
if (startOther != other.states.end()) { |
|
states.insert(states.end(), startOther, other.states.end()); |
|
changed = true; |
|
} |
|
} |
|
return changed; |
|
} |
|
}; |
|
|
|
} |
|
|
|
#endif
|
|
|