tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

gfxSkipChars.cpp (4688B)


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