File: SparseState.h

package info (click to toggle)
codequery 0.26.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 9,332 kB
  • sloc: cpp: 106,043; xml: 16,576; python: 4,187; perl: 244; makefile: 11
file content (106 lines) | stat: -rw-r--r-- 3,046 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// 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 Scintilla {

template <typename T>
class SparseState {
	struct State {
		Sci_Position position;
		T value;
		constexpr State(Sci_Position position_, T value_) noexcept : position(position_), value(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