tor-browser

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

DOMtoATK.cpp (4299B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "DOMtoATK.h"
      8 #include "nsUTF8Utils.h"
      9 
     10 namespace mozilla {
     11 namespace a11y {
     12 
     13 namespace DOMtoATK {
     14 
     15 void AddBOMs(nsACString& aDest, const nsACString& aSource) {
     16  uint32_t destlength = 0;
     17 
     18  // First compute how much room we will need.
     19  for (uint32_t srci = 0; srci < aSource.Length();) {
     20    int bytes = UTF8traits::bytes(aSource[srci]);
     21    if (bytes >= 4) {
     22      // Non-BMP character, will add a BOM after it.
     23      destlength += 3;
     24    }
     25    // Skip whole character encoding.
     26    srci += bytes;
     27    destlength += bytes;
     28  }
     29 
     30  uint32_t desti = 0;  // Index within aDest.
     31 
     32  // Add BOMs after non-BMP characters.
     33  aDest.SetLength(destlength);
     34  for (uint32_t srci = 0; srci < aSource.Length();) {
     35    uint32_t bytes = UTF8traits::bytes(aSource[srci]);
     36 
     37    MOZ_ASSERT(bytes <= aSource.Length() - srci,
     38               "We should have the whole sequence");
     39 
     40    // Copy whole sequence.
     41    aDest.Replace(desti, bytes, Substring(aSource, srci, bytes));
     42    desti += bytes;
     43    srci += bytes;
     44 
     45    if (bytes >= 4) {
     46      // More than 4 bytes in UTF-8 encoding exactly means more than 16 encoded
     47      // bits.  This is thus a non-BMP character which needed a surrogate
     48      // pair to get encoded in UTF-16, add a BOM after it.
     49 
     50      // And add a BOM after it.
     51      aDest.Replace(desti, 3, "\xEF\xBB\xBF");
     52      desti += 3;
     53    }
     54  }
     55  MOZ_ASSERT(desti == destlength,
     56             "Incoherency between computed length"
     57             "and actually translated length");
     58 }
     59 
     60 void ATKStringConverterHelper::AdjustOffsets(gint* aStartOffset,
     61                                             gint* aEndOffset, gint count) {
     62  MOZ_ASSERT(!mAdjusted,
     63             "DOMtoATK::ATKStringConverterHelper::AdjustOffsets needs to be "
     64             "called only once");
     65 
     66  if (*aStartOffset > 0) {
     67    (*aStartOffset)--;
     68    mStartShifted = true;
     69  }
     70 
     71  if (*aEndOffset >= 0 && *aEndOffset < count) {
     72    (*aEndOffset)++;
     73    mEndShifted = true;
     74  }
     75 
     76 #ifdef DEBUG
     77  mAdjusted = true;
     78 #endif
     79 }
     80 
     81 gchar* ATKStringConverterHelper::FinishUTF16toUTF8(nsCString& aStr) {
     82  int skip = 0;
     83 
     84  if (mStartShifted) {
     85    // AdjustOffsets added a leading character.
     86 
     87    MOZ_ASSERT(aStr.Length() > 0, "There should be a leading character");
     88    MOZ_ASSERT(
     89        static_cast<int>(aStr.Length()) >= UTF8traits::bytes(aStr.CharAt(0)),
     90        "The leading character should be complete");
     91 
     92    // drop first character
     93    skip = UTF8traits::bytes(aStr.CharAt(0));
     94  }
     95 
     96  if (mEndShifted) {
     97    // AdjustOffsets added a trailing character.
     98 
     99    MOZ_ASSERT(aStr.Length() > 0, "There should be a trailing character");
    100 
    101    int trail = -1;
    102    // Find beginning of last character.
    103    for (trail = aStr.Length() - 1; trail >= 0; trail--) {
    104      if (!UTF8traits::isInSeq(aStr.CharAt(trail))) {
    105        break;
    106      }
    107    }
    108    MOZ_ASSERT(trail >= 0,
    109               "There should be at least a whole trailing character");
    110    MOZ_ASSERT(trail + UTF8traits::bytes(aStr.CharAt(trail)) ==
    111                   static_cast<int>(aStr.Length()),
    112               "The trailing character should be complete");
    113 
    114    // Drop the last character.
    115    aStr.Truncate(trail);
    116  }
    117 
    118  // copy and return, libspi will free it
    119  return g_strdup(aStr.get() + skip);
    120 }
    121 
    122 gchar* ATKStringConverterHelper::ConvertAdjusted(const nsAString& aStr) {
    123  MOZ_ASSERT(mAdjusted,
    124             "DOMtoATK::ATKStringConverterHelper::AdjustOffsets needs to be "
    125             "called before ATKStringConverterHelper::ConvertAdjusted");
    126 
    127  NS_ConvertUTF16toUTF8 cautoStr(aStr);
    128  if (!cautoStr.get()) {
    129    return nullptr;
    130  }
    131 
    132  nsAutoCString cautoStrBOMs;
    133  AddBOMs(cautoStrBOMs, cautoStr);
    134  return FinishUTF16toUTF8(cautoStrBOMs);
    135 }
    136 
    137 gchar* Convert(const nsAString& aStr) {
    138  NS_ConvertUTF16toUTF8 cautoStr(aStr);
    139  if (!cautoStr.get()) {
    140    return nullptr;
    141  }
    142 
    143  nsAutoCString cautoStrBOMs;
    144  AddBOMs(cautoStrBOMs, cautoStr);
    145  return g_strdup(cautoStrBOMs.get());
    146 }
    147 
    148 }  // namespace DOMtoATK
    149 
    150 }  // namespace a11y
    151 }  // namespace mozilla