|
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 #include "gfxSkipChars.h" |
|
7 |
|
8 void |
|
9 gfxSkipCharsIterator::SetOriginalOffset(int32_t aOffset) |
|
10 { |
|
11 aOffset += mOriginalStringToSkipCharsOffset; |
|
12 NS_ASSERTION(uint32_t(aOffset) <= mSkipChars->mCharCount, |
|
13 "Invalid offset"); |
|
14 |
|
15 mOriginalStringOffset = aOffset; |
|
16 |
|
17 uint32_t rangeCount = mSkipChars->mRanges.Length(); |
|
18 if (rangeCount == 0) { |
|
19 mSkippedStringOffset = aOffset; |
|
20 return; |
|
21 } |
|
22 |
|
23 // at start of string? |
|
24 if (aOffset == 0) { |
|
25 mSkippedStringOffset = 0; |
|
26 mCurrentRangeIndex = |
|
27 rangeCount && mSkipChars->mRanges[0].Start() == 0 ? 0 : -1; |
|
28 return; |
|
29 } |
|
30 |
|
31 // find the range that includes or precedes aOffset |
|
32 uint32_t lo = 0, hi = rangeCount; |
|
33 const gfxSkipChars::SkippedRange* ranges = mSkipChars->mRanges.Elements(); |
|
34 while (lo < hi) { |
|
35 uint32_t mid = (lo + hi) / 2; |
|
36 if (uint32_t(aOffset) < ranges[mid].Start()) { |
|
37 hi = mid; |
|
38 } else { |
|
39 lo = mid + 1; |
|
40 } |
|
41 } |
|
42 |
|
43 if (lo == rangeCount) { |
|
44 mCurrentRangeIndex = rangeCount - 1; |
|
45 } else if (uint32_t(aOffset) < ranges[lo].Start()) { |
|
46 mCurrentRangeIndex = lo - 1; |
|
47 if (mCurrentRangeIndex == -1) { |
|
48 mSkippedStringOffset = aOffset; |
|
49 return; |
|
50 } |
|
51 } else { |
|
52 mCurrentRangeIndex = lo; |
|
53 } |
|
54 |
|
55 const gfxSkipChars::SkippedRange& r = ranges[mCurrentRangeIndex]; |
|
56 if (uint32_t(aOffset) < r.End()) { |
|
57 mSkippedStringOffset = r.SkippedOffset(); |
|
58 return; |
|
59 } |
|
60 |
|
61 mSkippedStringOffset = aOffset - r.NextDelta(); |
|
62 } |
|
63 |
|
64 void |
|
65 gfxSkipCharsIterator::SetSkippedOffset(uint32_t aOffset) |
|
66 { |
|
67 NS_ASSERTION((mSkipChars->mRanges.IsEmpty() && |
|
68 aOffset <= mSkipChars->mCharCount) || |
|
69 (aOffset <= mSkipChars->LastRange().SkippedOffset() + |
|
70 mSkipChars->mCharCount - |
|
71 mSkipChars->LastRange().End()), |
|
72 "Invalid skipped offset"); |
|
73 mSkippedStringOffset = aOffset; |
|
74 |
|
75 uint32_t rangeCount = mSkipChars->mRanges.Length(); |
|
76 if (rangeCount == 0) { |
|
77 mOriginalStringOffset = aOffset; |
|
78 return; |
|
79 } |
|
80 |
|
81 uint32_t lo = 0, hi = rangeCount; |
|
82 const gfxSkipChars::SkippedRange* ranges = mSkipChars->mRanges.Elements(); |
|
83 while (lo < hi) { |
|
84 uint32_t mid = (lo + hi) / 2; |
|
85 if (aOffset < ranges[mid].SkippedOffset()) { |
|
86 hi = mid; |
|
87 } else { |
|
88 lo = mid + 1; |
|
89 } |
|
90 } |
|
91 |
|
92 if (lo == rangeCount) { |
|
93 mCurrentRangeIndex = rangeCount - 1; |
|
94 } else if (aOffset < ranges[lo].SkippedOffset()) { |
|
95 mCurrentRangeIndex = lo - 1; |
|
96 if (mCurrentRangeIndex == -1) { |
|
97 mOriginalStringOffset = aOffset; |
|
98 return; |
|
99 } |
|
100 } else { |
|
101 mCurrentRangeIndex = lo; |
|
102 } |
|
103 |
|
104 const gfxSkipChars::SkippedRange& r = ranges[mCurrentRangeIndex]; |
|
105 mOriginalStringOffset = r.End() + aOffset - r.SkippedOffset(); |
|
106 } |
|
107 |
|
108 bool |
|
109 gfxSkipCharsIterator::IsOriginalCharSkipped(int32_t* aRunLength) const |
|
110 { |
|
111 if (mCurrentRangeIndex == -1) { |
|
112 // we're before the first skipped range (if any) |
|
113 if (aRunLength) { |
|
114 uint32_t end = mSkipChars->mRanges.IsEmpty() ? |
|
115 mSkipChars->mCharCount : mSkipChars->mRanges[0].Start(); |
|
116 *aRunLength = end - mOriginalStringOffset; |
|
117 } |
|
118 return mSkipChars->mCharCount == uint32_t(mOriginalStringOffset); |
|
119 } |
|
120 |
|
121 const gfxSkipChars::SkippedRange& range = |
|
122 mSkipChars->mRanges[mCurrentRangeIndex]; |
|
123 |
|
124 if (uint32_t(mOriginalStringOffset) < range.End()) { |
|
125 if (aRunLength) { |
|
126 *aRunLength = range.End() - mOriginalStringOffset; |
|
127 } |
|
128 return true; |
|
129 } |
|
130 |
|
131 if (aRunLength) { |
|
132 uint32_t end = |
|
133 uint32_t(mCurrentRangeIndex) + 1 < mSkipChars->mRanges.Length() ? |
|
134 mSkipChars->mRanges[mCurrentRangeIndex + 1].Start() : |
|
135 mSkipChars->mCharCount; |
|
136 *aRunLength = end - mOriginalStringOffset; |
|
137 } |
|
138 |
|
139 return mSkipChars->mCharCount == uint32_t(mOriginalStringOffset); |
|
140 } |