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