/work/obj-fuzz/dist/include/gfxSkipChars.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
2 | | * This Source Code Form is subject to the terms of the Mozilla Public |
3 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
5 | | |
6 | | #ifndef GFX_SKIP_CHARS_H |
7 | | #define GFX_SKIP_CHARS_H |
8 | | |
9 | | #include "nsTArray.h" |
10 | | |
11 | | /* |
12 | | * gfxSkipChars is a data structure representing a list of characters that |
13 | | * have been skipped. The initial string is called the "original string" |
14 | | * and after skipping some characters, the result is called the "skipped string". |
15 | | * gfxSkipChars provides efficient ways to translate between offsets in the |
16 | | * original string and the skipped string. It is used by textrun code to keep |
17 | | * track of offsets before and after text transformations such as whitespace |
18 | | * compression and control code deletion. |
19 | | */ |
20 | | |
21 | | /** |
22 | | * The gfxSkipChars is represented as a sorted array of skipped ranges. |
23 | | * |
24 | | * A freshly-created gfxSkipChars means "all chars kept". |
25 | | */ |
26 | | class gfxSkipChars |
27 | | { |
28 | | friend struct SkippedRangeStartComparator; |
29 | | friend struct SkippedRangeOffsetComparator; |
30 | | |
31 | | private: |
32 | | class SkippedRange |
33 | | { |
34 | | public: |
35 | | SkippedRange(uint32_t aOffset, uint32_t aLength, uint32_t aDelta) |
36 | | : mOffset(aOffset), mLength(aLength), mDelta(aDelta) |
37 | 0 | { } |
38 | | |
39 | | uint32_t Start() const |
40 | 0 | { |
41 | 0 | return mOffset; |
42 | 0 | } |
43 | | |
44 | | uint32_t End() const |
45 | 0 | { |
46 | 0 | return mOffset + mLength; |
47 | 0 | } |
48 | | |
49 | | uint32_t Length() const |
50 | 0 | { |
51 | 0 | return mLength; |
52 | 0 | } |
53 | | |
54 | | uint32_t SkippedOffset() const |
55 | 0 | { |
56 | 0 | return mOffset - mDelta; |
57 | 0 | } |
58 | | |
59 | | uint32_t Delta() const |
60 | 0 | { |
61 | 0 | return mDelta; |
62 | 0 | } |
63 | | |
64 | | uint32_t NextDelta() const |
65 | 0 | { |
66 | 0 | return mDelta + mLength; |
67 | 0 | } |
68 | | |
69 | | void Extend(uint32_t aChars) |
70 | 0 | { |
71 | 0 | mLength += aChars; |
72 | 0 | } |
73 | | |
74 | | private: |
75 | | uint32_t mOffset; // original-string offset at which we want to skip |
76 | | uint32_t mLength; // number of skipped chars at this offset |
77 | | uint32_t mDelta; // sum of lengths of preceding skipped-ranges |
78 | | }; |
79 | | |
80 | | public: |
81 | | gfxSkipChars() |
82 | | : mCharCount(0) |
83 | | { } |
84 | | |
85 | | void SkipChars(uint32_t aChars) |
86 | 0 | { |
87 | 0 | NS_ASSERTION(mCharCount + aChars > mCharCount, |
88 | 0 | "Character count overflow"); |
89 | 0 | uint32_t rangeCount = mRanges.Length(); |
90 | 0 | uint32_t delta = 0; |
91 | 0 | if (rangeCount > 0) { |
92 | 0 | SkippedRange& lastRange = mRanges[rangeCount - 1]; |
93 | 0 | if (lastRange.End() == mCharCount) { |
94 | 0 | lastRange.Extend(aChars); |
95 | 0 | mCharCount += aChars; |
96 | 0 | return; |
97 | 0 | } |
98 | 0 | delta = lastRange.NextDelta(); |
99 | 0 | } |
100 | 0 | mRanges.AppendElement(SkippedRange(mCharCount, aChars, delta)); |
101 | 0 | mCharCount += aChars; |
102 | 0 | } |
103 | | |
104 | | void KeepChars(uint32_t aChars) |
105 | 0 | { |
106 | 0 | NS_ASSERTION(mCharCount + aChars > mCharCount, |
107 | 0 | "Character count overflow"); |
108 | 0 | mCharCount += aChars; |
109 | 0 | } |
110 | | |
111 | | void SkipChar() |
112 | 0 | { |
113 | 0 | SkipChars(1); |
114 | 0 | } |
115 | | |
116 | | void KeepChar() |
117 | 0 | { |
118 | 0 | KeepChars(1); |
119 | 0 | } |
120 | | |
121 | | void TakeFrom(gfxSkipChars* aSkipChars) |
122 | 0 | { |
123 | 0 | mRanges.SwapElements(aSkipChars->mRanges); |
124 | 0 | mCharCount = aSkipChars->mCharCount; |
125 | 0 | aSkipChars->mCharCount = 0; |
126 | 0 | } |
127 | | |
128 | | int32_t GetOriginalCharCount() const |
129 | 0 | { |
130 | 0 | return mCharCount; |
131 | 0 | } |
132 | | |
133 | | const SkippedRange& LastRange() const |
134 | 0 | { |
135 | 0 | // this is only valid if mRanges is non-empty; no assertion here |
136 | 0 | // because nsTArray will already assert if we abuse it |
137 | 0 | return mRanges[mRanges.Length() - 1]; |
138 | 0 | } |
139 | | |
140 | | friend class gfxSkipCharsIterator; |
141 | | |
142 | | private: |
143 | | nsTArray<SkippedRange> mRanges; |
144 | | uint32_t mCharCount; |
145 | | }; |
146 | | |
147 | | /** |
148 | | * A gfxSkipCharsIterator represents a position in the original string. It lets you |
149 | | * map efficiently to and from positions in the string after skipped characters |
150 | | * have been removed. You can also specify an offset that is added to all |
151 | | * incoming original string offsets and subtracted from all outgoing original |
152 | | * string offsets --- useful when the gfxSkipChars corresponds to something |
153 | | * offset from the original DOM coordinates, which it often does for gfxTextRuns. |
154 | | * |
155 | | * The current positions (in both the original and skipped strings) are |
156 | | * always constrained to be >= 0 and <= the string length. When the position |
157 | | * is equal to the string length, it is at the end of the string. The current |
158 | | * positions do not include any aOriginalStringToSkipCharsOffset. |
159 | | * |
160 | | * When the position in the original string corresponds to a skipped character, |
161 | | * the skipped-characters offset is the offset of the next unskipped character, |
162 | | * or the skipped-characters string length if there is no next unskipped character. |
163 | | */ |
164 | | class gfxSkipCharsIterator |
165 | | { |
166 | | public: |
167 | | /** |
168 | | * @param aOriginalStringToSkipCharsOffset add this to all incoming and |
169 | | * outgoing original string offsets |
170 | | */ |
171 | | gfxSkipCharsIterator(const gfxSkipChars& aSkipChars, |
172 | | int32_t aOriginalStringToSkipCharsOffset, |
173 | | int32_t aOriginalStringOffset) |
174 | | : mSkipChars(&aSkipChars), |
175 | | mOriginalStringOffset(0), |
176 | | mSkippedStringOffset(0), |
177 | | mCurrentRangeIndex(-1), |
178 | | mOriginalStringToSkipCharsOffset(aOriginalStringToSkipCharsOffset) |
179 | 0 | { |
180 | 0 | SetOriginalOffset(aOriginalStringOffset); |
181 | 0 | } |
182 | | |
183 | | explicit gfxSkipCharsIterator(const gfxSkipChars& aSkipChars, |
184 | | int32_t aOriginalStringToSkipCharsOffset = 0) |
185 | | : mSkipChars(&aSkipChars), |
186 | | mOriginalStringOffset(0), |
187 | | mSkippedStringOffset(0), |
188 | | mOriginalStringToSkipCharsOffset(aOriginalStringToSkipCharsOffset) |
189 | 0 | { |
190 | 0 | mCurrentRangeIndex = |
191 | 0 | mSkipChars->mRanges.IsEmpty() || |
192 | 0 | mSkipChars->mRanges[0].Start() > 0 ? -1 : 0; |
193 | 0 | } |
194 | | |
195 | | gfxSkipCharsIterator(const gfxSkipCharsIterator& aIterator) |
196 | | : mSkipChars(aIterator.mSkipChars), |
197 | | mOriginalStringOffset(aIterator.mOriginalStringOffset), |
198 | | mSkippedStringOffset(aIterator.mSkippedStringOffset), |
199 | | mCurrentRangeIndex(aIterator.mCurrentRangeIndex), |
200 | | mOriginalStringToSkipCharsOffset(aIterator.mOriginalStringToSkipCharsOffset) |
201 | 0 | { } |
202 | | |
203 | | /** |
204 | | * The empty constructor creates an object that is useless until it is assigned. |
205 | | */ |
206 | | gfxSkipCharsIterator() |
207 | | : mSkipChars(nullptr), |
208 | | mOriginalStringOffset(0), |
209 | | mSkippedStringOffset(0), |
210 | | mCurrentRangeIndex(0), |
211 | | mOriginalStringToSkipCharsOffset(0) |
212 | 0 | { } |
213 | | |
214 | | /** |
215 | | * Return true if this iterator is properly initialized and usable. |
216 | | */ |
217 | | bool IsInitialized() |
218 | 0 | { |
219 | 0 | return mSkipChars != nullptr; |
220 | 0 | } |
221 | | |
222 | | /** |
223 | | * Set the iterator to aOriginalStringOffset in the original string. |
224 | | * This can efficiently move forward or backward from the current position. |
225 | | * aOriginalStringOffset is clamped to [0,originalStringLength]. |
226 | | */ |
227 | | void SetOriginalOffset(int32_t aOriginalStringOffset); |
228 | | |
229 | | /** |
230 | | * Set the iterator to aSkippedStringOffset in the skipped string. |
231 | | * This can efficiently move forward or backward from the current position. |
232 | | * aSkippedStringOffset is clamped to [0,skippedStringLength]. |
233 | | */ |
234 | | void SetSkippedOffset(uint32_t aSkippedStringOffset); |
235 | | |
236 | | uint32_t ConvertOriginalToSkipped(int32_t aOriginalStringOffset) |
237 | 0 | { |
238 | 0 | SetOriginalOffset(aOriginalStringOffset); |
239 | 0 | return GetSkippedOffset(); |
240 | 0 | } |
241 | | |
242 | | int32_t ConvertSkippedToOriginal(uint32_t aSkippedStringOffset) |
243 | 0 | { |
244 | 0 | SetSkippedOffset(aSkippedStringOffset); |
245 | 0 | return GetOriginalOffset(); |
246 | 0 | } |
247 | | |
248 | | /** |
249 | | * Test if the character at the current position in the original string |
250 | | * is skipped or not. If aRunLength is non-null, then *aRunLength is set |
251 | | * to a number of characters all of which are either skipped or not, starting |
252 | | * at this character. When the current position is at the end of the original |
253 | | * string, we return true and *aRunLength is set to zero. |
254 | | */ |
255 | | bool IsOriginalCharSkipped(int32_t* aRunLength = nullptr) const; |
256 | | |
257 | | void AdvanceOriginal(int32_t aDelta) |
258 | 0 | { |
259 | 0 | SetOriginalOffset(GetOriginalOffset() + aDelta); |
260 | 0 | } |
261 | | |
262 | | void AdvanceSkipped(int32_t aDelta) |
263 | 0 | { |
264 | 0 | SetSkippedOffset(GetSkippedOffset() + aDelta); |
265 | 0 | } |
266 | | |
267 | | /** |
268 | | * @return the offset within the original string |
269 | | */ |
270 | | int32_t GetOriginalOffset() const |
271 | 0 | { |
272 | 0 | return mOriginalStringOffset - mOriginalStringToSkipCharsOffset; |
273 | 0 | } |
274 | | |
275 | | /** |
276 | | * @return the offset within the skipped string corresponding to the |
277 | | * current position in the original string. If the current position |
278 | | * in the original string is a character that is skipped, then we return |
279 | | * the position corresponding to the first non-skipped character in the |
280 | | * original string after the current position, or the length of the skipped |
281 | | * string if there is no such character. |
282 | | */ |
283 | | uint32_t GetSkippedOffset() const |
284 | 0 | { |
285 | 0 | return mSkippedStringOffset; |
286 | 0 | } |
287 | | |
288 | | int32_t GetOriginalEnd() const |
289 | 0 | { |
290 | 0 | return mSkipChars->GetOriginalCharCount() - |
291 | 0 | mOriginalStringToSkipCharsOffset; |
292 | 0 | } |
293 | | |
294 | | private: |
295 | | const gfxSkipChars* mSkipChars; |
296 | | |
297 | | // Current position |
298 | | int32_t mOriginalStringOffset; |
299 | | uint32_t mSkippedStringOffset; |
300 | | |
301 | | // Index of the last skippedRange that precedes or contains the current |
302 | | // position in the original string. |
303 | | // If index == -1 then we are before the first skipped char. |
304 | | int32_t mCurrentRangeIndex; |
305 | | |
306 | | // This offset is added to map from "skipped+unskipped characters in |
307 | | // the original DOM string" character space to "skipped+unskipped |
308 | | // characters in the textrun's gfxSkipChars" character space |
309 | | int32_t mOriginalStringToSkipCharsOffset; |
310 | | }; |
311 | | |
312 | | #endif /*GFX_SKIP_CHARS_H*/ |