tor-browser

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

MeasureUnit.cpp (3305B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "mozilla/intl/MeasureUnit.h"
      6 
      7 #include "unicode/udata.h"
      8 #include "unicode/ures.h"
      9 #include "unicode/utypes.h"
     10 
     11 namespace mozilla::intl {
     12 
     13 void MeasureUnit::UResourceBundleDeleter::operator()(UResourceBundle* aPtr) {
     14  ures_close(aPtr);
     15 }
     16 
     17 MeasureUnit::Enumeration::Enumeration(UniqueUResourceBundle aRootLocale,
     18                                      UniqueUResourceBundle aUnits)
     19    : mRootLocale(std::move(aRootLocale)), mUnits(std::move(aUnits)) {
     20  mUnitsSize = ures_getSize(mUnits.get());
     21 }
     22 
     23 MeasureUnit::Enumeration::Iterator::value_type
     24 MeasureUnit::Enumeration::Iterator::operator*() const {
     25  // Return an error result after an ICU error has occurred.
     26  if (mHasError) {
     27    return Err(InternalError{});
     28  }
     29 
     30  // Otherwise return the name of the current measurement unit.
     31  const char* unitIdentifier = ures_getKey(mSubtype.get());
     32  MOZ_ASSERT(unitIdentifier);
     33  return MakeStringSpan(unitIdentifier);
     34 }
     35 
     36 void MeasureUnit::Enumeration::Iterator::advance() {
     37  // Reject any attempts to modify this iterator after an error has occurred.
     38  if (mHasError) {
     39    return;
     40  }
     41 
     42  while (true) {
     43    // Read the next measurement unit in the types table.
     44    if (mTypePos < mTypeSize) {
     45      UErrorCode status = U_ZERO_ERROR;
     46      UResourceBundle* rawSubtype =
     47          ures_getByIndex(mType.get(), mTypePos, nullptr, &status);
     48      if (U_FAILURE(status)) {
     49        mHasError = true;
     50        return;
     51      }
     52 
     53      mTypePos += 1;
     54      mSubtype.reset(rawSubtype);
     55      return;
     56    }
     57 
     58    // Read the next measurement unit type in the "units" table.
     59    if (mUnitsPos < mEnumeration.mUnitsSize) {
     60      UErrorCode status = U_ZERO_ERROR;
     61      UResourceBundle* rawType = ures_getByIndex(mEnumeration.mUnits.get(),
     62                                                 mUnitsPos, nullptr, &status);
     63      if (U_FAILURE(status)) {
     64        mHasError = true;
     65        return;
     66      }
     67 
     68      mUnitsPos += 1;
     69      mType.reset(rawType);
     70      mTypeSize = ures_getSize(rawType);
     71      mTypePos = 0;
     72      continue;
     73    }
     74 
     75    // All measurement units have been processed. Reset the two |mType*| fields
     76    // to zero to match the end-iterator state and then return.
     77    MOZ_ASSERT(mUnitsPos == mEnumeration.mUnitsSize);
     78    mTypePos = 0;
     79    mTypeSize = 0;
     80    return;
     81  }
     82 }
     83 
     84 Result<MeasureUnit::Enumeration, ICUError>
     85 MeasureUnit::Enumeration::TryCreate() {
     86  // Look up the available measurement units in the resource bundle of the root
     87  // locale.
     88 
     89  static const char packageName[] =
     90      U_ICUDATA_NAME U_TREE_SEPARATOR_STRING "unit";
     91  static const char rootLocale[] = "";
     92 
     93  UErrorCode status = U_ZERO_ERROR;
     94  UResourceBundle* rawRes = ures_open(packageName, rootLocale, &status);
     95  if (U_FAILURE(status)) {
     96    return Err(ToICUError(status));
     97  }
     98  UniqueUResourceBundle res(rawRes);
     99 
    100  UResourceBundle* rawUnits =
    101      ures_getByKey(res.get(), "units", nullptr, &status);
    102  if (U_FAILURE(status)) {
    103    return Err(ToICUError(status));
    104  }
    105  UniqueUResourceBundle units(rawUnits);
    106 
    107  return MeasureUnit::Enumeration(std::move(res), std::move(units));
    108 }
    109 
    110 }  // namespace mozilla::intl