зеркало из https://github.com/mozilla/gecko-dev.git
155 строки
4.9 KiB
C++
155 строки
4.9 KiB
C++
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "gfxSkipChars.h"
|
|
#include "mozilla/BinarySearch.h"
|
|
#include "mozilla/gfx/Logging.h"
|
|
|
|
struct SkippedRangeStartComparator
|
|
{
|
|
const uint32_t mOffset;
|
|
explicit SkippedRangeStartComparator(const uint32_t aOffset) : mOffset(aOffset) {}
|
|
int operator()(const gfxSkipChars::SkippedRange& aRange) const {
|
|
return (mOffset < aRange.Start()) ? -1 : 1;
|
|
}
|
|
};
|
|
|
|
void
|
|
gfxSkipCharsIterator::SetOriginalOffset(int32_t aOffset)
|
|
{
|
|
aOffset += mOriginalStringToSkipCharsOffset;
|
|
if (MOZ_UNLIKELY(uint32_t(aOffset) > mSkipChars->mCharCount)) {
|
|
gfxCriticalError() <<
|
|
"invalid offset " << aOffset <<
|
|
" for gfxSkipChars length " << mSkipChars->mCharCount;
|
|
aOffset = mSkipChars->mCharCount;
|
|
}
|
|
|
|
mOriginalStringOffset = aOffset;
|
|
|
|
const uint32_t rangeCount = mSkipChars->mRanges.Length();
|
|
if (rangeCount == 0) {
|
|
mSkippedStringOffset = aOffset;
|
|
return;
|
|
}
|
|
|
|
// at start of string?
|
|
if (aOffset == 0) {
|
|
mSkippedStringOffset = 0;
|
|
mCurrentRangeIndex =
|
|
rangeCount && mSkipChars->mRanges[0].Start() == 0 ? 0 : -1;
|
|
return;
|
|
}
|
|
|
|
// find the range that includes or precedes aOffset
|
|
const nsTArray<gfxSkipChars::SkippedRange>& ranges = mSkipChars->mRanges;
|
|
size_t idx;
|
|
mozilla::BinarySearchIf(ranges, 0, rangeCount,
|
|
SkippedRangeStartComparator(aOffset),
|
|
&idx);
|
|
|
|
if (idx == rangeCount) {
|
|
mCurrentRangeIndex = rangeCount - 1;
|
|
} else if (uint32_t(aOffset) < ranges[idx].Start()) {
|
|
mCurrentRangeIndex = idx - 1;
|
|
if (mCurrentRangeIndex == -1) {
|
|
mSkippedStringOffset = aOffset;
|
|
return;
|
|
}
|
|
} else {
|
|
mCurrentRangeIndex = idx;
|
|
}
|
|
|
|
const gfxSkipChars::SkippedRange& r = ranges[mCurrentRangeIndex];
|
|
if (uint32_t(aOffset) < r.End()) {
|
|
mSkippedStringOffset = r.SkippedOffset();
|
|
return;
|
|
}
|
|
|
|
mSkippedStringOffset = aOffset - r.NextDelta();
|
|
}
|
|
|
|
struct SkippedRangeOffsetComparator
|
|
{
|
|
const uint32_t mOffset;
|
|
explicit SkippedRangeOffsetComparator(const uint32_t aOffset) : mOffset(aOffset) {}
|
|
int operator()(const gfxSkipChars::SkippedRange& aRange) const {
|
|
return (mOffset < aRange.SkippedOffset()) ? -1 : 1;
|
|
}
|
|
};
|
|
|
|
void
|
|
gfxSkipCharsIterator::SetSkippedOffset(uint32_t aOffset)
|
|
{
|
|
NS_ASSERTION((mSkipChars->mRanges.IsEmpty() &&
|
|
aOffset <= mSkipChars->mCharCount) ||
|
|
(aOffset <= mSkipChars->LastRange().SkippedOffset() +
|
|
mSkipChars->mCharCount -
|
|
mSkipChars->LastRange().End()),
|
|
"Invalid skipped offset");
|
|
mSkippedStringOffset = aOffset;
|
|
|
|
uint32_t rangeCount = mSkipChars->mRanges.Length();
|
|
if (rangeCount == 0) {
|
|
mOriginalStringOffset = aOffset;
|
|
return;
|
|
}
|
|
|
|
const nsTArray<gfxSkipChars::SkippedRange>& ranges = mSkipChars->mRanges;
|
|
size_t idx;
|
|
mozilla::BinarySearchIf(ranges, 0, rangeCount,
|
|
SkippedRangeOffsetComparator(aOffset),
|
|
&idx);
|
|
|
|
if (idx == rangeCount) {
|
|
mCurrentRangeIndex = rangeCount - 1;
|
|
} else if (aOffset < ranges[idx].SkippedOffset()) {
|
|
mCurrentRangeIndex = idx - 1;
|
|
if (mCurrentRangeIndex == -1) {
|
|
mOriginalStringOffset = aOffset;
|
|
return;
|
|
}
|
|
} else {
|
|
mCurrentRangeIndex = idx;
|
|
}
|
|
|
|
const gfxSkipChars::SkippedRange& r = ranges[mCurrentRangeIndex];
|
|
mOriginalStringOffset = r.End() + aOffset - r.SkippedOffset();
|
|
}
|
|
|
|
bool
|
|
gfxSkipCharsIterator::IsOriginalCharSkipped(int32_t* aRunLength) const
|
|
{
|
|
if (mCurrentRangeIndex == -1) {
|
|
// we're before the first skipped range (if any)
|
|
if (aRunLength) {
|
|
uint32_t end = mSkipChars->mRanges.IsEmpty() ?
|
|
mSkipChars->mCharCount : mSkipChars->mRanges[0].Start();
|
|
*aRunLength = end - mOriginalStringOffset;
|
|
}
|
|
return mSkipChars->mCharCount == uint32_t(mOriginalStringOffset);
|
|
}
|
|
|
|
const gfxSkipChars::SkippedRange& range =
|
|
mSkipChars->mRanges[mCurrentRangeIndex];
|
|
|
|
if (uint32_t(mOriginalStringOffset) < range.End()) {
|
|
if (aRunLength) {
|
|
*aRunLength = range.End() - mOriginalStringOffset;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if (aRunLength) {
|
|
uint32_t end =
|
|
uint32_t(mCurrentRangeIndex) + 1 < mSkipChars->mRanges.Length() ?
|
|
mSkipChars->mRanges[mCurrentRangeIndex + 1].Start() :
|
|
mSkipChars->mCharCount;
|
|
*aRunLength = end - mOriginalStringOffset;
|
|
}
|
|
|
|
return mSkipChars->mCharCount == uint32_t(mOriginalStringOffset);
|
|
}
|