michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "gfxSkipChars.h" michael@0: michael@0: void michael@0: gfxSkipCharsIterator::SetOriginalOffset(int32_t aOffset) michael@0: { michael@0: aOffset += mOriginalStringToSkipCharsOffset; michael@0: NS_ASSERTION(uint32_t(aOffset) <= mSkipChars->mCharCount, michael@0: "Invalid offset"); michael@0: michael@0: mOriginalStringOffset = aOffset; michael@0: michael@0: uint32_t rangeCount = mSkipChars->mRanges.Length(); michael@0: if (rangeCount == 0) { michael@0: mSkippedStringOffset = aOffset; michael@0: return; michael@0: } michael@0: michael@0: // at start of string? michael@0: if (aOffset == 0) { michael@0: mSkippedStringOffset = 0; michael@0: mCurrentRangeIndex = michael@0: rangeCount && mSkipChars->mRanges[0].Start() == 0 ? 0 : -1; michael@0: return; michael@0: } michael@0: michael@0: // find the range that includes or precedes aOffset michael@0: uint32_t lo = 0, hi = rangeCount; michael@0: const gfxSkipChars::SkippedRange* ranges = mSkipChars->mRanges.Elements(); michael@0: while (lo < hi) { michael@0: uint32_t mid = (lo + hi) / 2; michael@0: if (uint32_t(aOffset) < ranges[mid].Start()) { michael@0: hi = mid; michael@0: } else { michael@0: lo = mid + 1; michael@0: } michael@0: } michael@0: michael@0: if (lo == rangeCount) { michael@0: mCurrentRangeIndex = rangeCount - 1; michael@0: } else if (uint32_t(aOffset) < ranges[lo].Start()) { michael@0: mCurrentRangeIndex = lo - 1; michael@0: if (mCurrentRangeIndex == -1) { michael@0: mSkippedStringOffset = aOffset; michael@0: return; michael@0: } michael@0: } else { michael@0: mCurrentRangeIndex = lo; michael@0: } michael@0: michael@0: const gfxSkipChars::SkippedRange& r = ranges[mCurrentRangeIndex]; michael@0: if (uint32_t(aOffset) < r.End()) { michael@0: mSkippedStringOffset = r.SkippedOffset(); michael@0: return; michael@0: } michael@0: michael@0: mSkippedStringOffset = aOffset - r.NextDelta(); michael@0: } michael@0: michael@0: void michael@0: gfxSkipCharsIterator::SetSkippedOffset(uint32_t aOffset) michael@0: { michael@0: NS_ASSERTION((mSkipChars->mRanges.IsEmpty() && michael@0: aOffset <= mSkipChars->mCharCount) || michael@0: (aOffset <= mSkipChars->LastRange().SkippedOffset() + michael@0: mSkipChars->mCharCount - michael@0: mSkipChars->LastRange().End()), michael@0: "Invalid skipped offset"); michael@0: mSkippedStringOffset = aOffset; michael@0: michael@0: uint32_t rangeCount = mSkipChars->mRanges.Length(); michael@0: if (rangeCount == 0) { michael@0: mOriginalStringOffset = aOffset; michael@0: return; michael@0: } michael@0: michael@0: uint32_t lo = 0, hi = rangeCount; michael@0: const gfxSkipChars::SkippedRange* ranges = mSkipChars->mRanges.Elements(); michael@0: while (lo < hi) { michael@0: uint32_t mid = (lo + hi) / 2; michael@0: if (aOffset < ranges[mid].SkippedOffset()) { michael@0: hi = mid; michael@0: } else { michael@0: lo = mid + 1; michael@0: } michael@0: } michael@0: michael@0: if (lo == rangeCount) { michael@0: mCurrentRangeIndex = rangeCount - 1; michael@0: } else if (aOffset < ranges[lo].SkippedOffset()) { michael@0: mCurrentRangeIndex = lo - 1; michael@0: if (mCurrentRangeIndex == -1) { michael@0: mOriginalStringOffset = aOffset; michael@0: return; michael@0: } michael@0: } else { michael@0: mCurrentRangeIndex = lo; michael@0: } michael@0: michael@0: const gfxSkipChars::SkippedRange& r = ranges[mCurrentRangeIndex]; michael@0: mOriginalStringOffset = r.End() + aOffset - r.SkippedOffset(); michael@0: } michael@0: michael@0: bool michael@0: gfxSkipCharsIterator::IsOriginalCharSkipped(int32_t* aRunLength) const michael@0: { michael@0: if (mCurrentRangeIndex == -1) { michael@0: // we're before the first skipped range (if any) michael@0: if (aRunLength) { michael@0: uint32_t end = mSkipChars->mRanges.IsEmpty() ? michael@0: mSkipChars->mCharCount : mSkipChars->mRanges[0].Start(); michael@0: *aRunLength = end - mOriginalStringOffset; michael@0: } michael@0: return mSkipChars->mCharCount == uint32_t(mOriginalStringOffset); michael@0: } michael@0: michael@0: const gfxSkipChars::SkippedRange& range = michael@0: mSkipChars->mRanges[mCurrentRangeIndex]; michael@0: michael@0: if (uint32_t(mOriginalStringOffset) < range.End()) { michael@0: if (aRunLength) { michael@0: *aRunLength = range.End() - mOriginalStringOffset; michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: if (aRunLength) { michael@0: uint32_t end = michael@0: uint32_t(mCurrentRangeIndex) + 1 < mSkipChars->mRanges.Length() ? michael@0: mSkipChars->mRanges[mCurrentRangeIndex + 1].Start() : michael@0: mSkipChars->mCharCount; michael@0: *aRunLength = end - mOriginalStringOffset; michael@0: } michael@0: michael@0: return mSkipChars->mCharCount == uint32_t(mOriginalStringOffset); michael@0: }