tor-browser

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

ListFormat.cpp (3855B)


      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 #include "mozilla/intl/ListFormat.h"
      5 
      6 #include "ScopedICUObject.h"
      7 
      8 namespace mozilla::intl {
      9 
     10 /*static*/ Result<UniquePtr<ListFormat>, ICUError> ListFormat::TryCreate(
     11    mozilla::Span<const char> aLocale, const Options& aOptions) {
     12  UListFormatterType utype = ToUListFormatterType(aOptions.mType);
     13  UListFormatterWidth uwidth = ToUListFormatterWidth(aOptions.mStyle);
     14 
     15  UErrorCode status = U_ZERO_ERROR;
     16  UListFormatter* fmt =
     17      ulistfmt_openForType(IcuLocale(aLocale), utype, uwidth, &status);
     18  if (U_FAILURE(status)) {
     19    return Err(ICUError::InternalError);
     20  }
     21 
     22  return UniquePtr<ListFormat>(new ListFormat(fmt));
     23 }
     24 
     25 ListFormat::~ListFormat() {
     26  if (mListFormatter) {
     27    ulistfmt_close(mListFormatter.GetMut());
     28  }
     29 }
     30 
     31 /* static */ UListFormatterType ListFormat::ToUListFormatterType(Type type) {
     32  switch (type) {
     33    case Type::Conjunction:
     34      return ULISTFMT_TYPE_AND;
     35    case Type::Disjunction:
     36      return ULISTFMT_TYPE_OR;
     37    case Type::Unit:
     38      return ULISTFMT_TYPE_UNITS;
     39  }
     40  MOZ_ASSERT_UNREACHABLE();
     41  return ULISTFMT_TYPE_AND;
     42 }
     43 
     44 /* static */ UListFormatterWidth ListFormat::ToUListFormatterWidth(
     45    Style style) {
     46  switch (style) {
     47    case Style::Long:
     48      return ULISTFMT_WIDTH_WIDE;
     49    case Style::Short:
     50      return ULISTFMT_WIDTH_SHORT;
     51    case Style::Narrow:
     52      return ULISTFMT_WIDTH_NARROW;
     53  }
     54  MOZ_ASSERT_UNREACHABLE();
     55  return ULISTFMT_WIDTH_WIDE;
     56 }
     57 
     58 ICUResult ListFormat::FormattedToParts(const UFormattedValue* formattedValue,
     59                                       size_t formattedSize,
     60                                       PartVector& parts) {
     61  size_t lastEndIndex = 0;
     62 
     63  auto AppendPart = [&](PartType type, size_t endIndex) {
     64    if (!parts.emplaceBack(type, endIndex)) {
     65      return false;
     66    }
     67 
     68    lastEndIndex = endIndex;
     69    return true;
     70  };
     71 
     72  UErrorCode status = U_ZERO_ERROR;
     73  UConstrainedFieldPosition* fpos = ucfpos_open(&status);
     74  if (U_FAILURE(status)) {
     75    return Err(ICUError::InternalError);
     76  }
     77  ScopedICUObject<UConstrainedFieldPosition, ucfpos_close> toCloseFpos(fpos);
     78 
     79  // We're only interested in ULISTFMT_ELEMENT_FIELD fields.
     80  ucfpos_constrainField(fpos, UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD,
     81                        &status);
     82  if (U_FAILURE(status)) {
     83    return Err(ICUError::InternalError);
     84  }
     85 
     86  while (true) {
     87    bool hasMore = ufmtval_nextPosition(formattedValue, fpos, &status);
     88    if (U_FAILURE(status)) {
     89      return Err(ICUError::InternalError);
     90    }
     91    if (!hasMore) {
     92      break;
     93    }
     94 
     95    int32_t beginIndexInt, endIndexInt;
     96    ucfpos_getIndexes(fpos, &beginIndexInt, &endIndexInt, &status);
     97    if (U_FAILURE(status)) {
     98      return Err(ICUError::InternalError);
     99    }
    100 
    101    MOZ_ASSERT(beginIndexInt <= endIndexInt,
    102               "field iterator returning invalid range");
    103 
    104    size_t beginIndex = AssertedCast<size_t>(beginIndexInt);
    105    size_t endIndex = AssertedCast<size_t>(endIndexInt);
    106 
    107    // Indices are guaranteed to be returned in order (from left to right).
    108    MOZ_ASSERT(lastEndIndex <= beginIndex,
    109               "field iteration didn't return fields in order start to "
    110               "finish as expected");
    111 
    112    if (lastEndIndex < beginIndex) {
    113      if (!AppendPart(PartType::Literal, beginIndex)) {
    114        return Err(ICUError::InternalError);
    115      }
    116    }
    117 
    118    if (!AppendPart(PartType::Element, endIndex)) {
    119      return Err(ICUError::InternalError);
    120    }
    121  }
    122 
    123  // Append any final literal.
    124  if (lastEndIndex < formattedSize) {
    125    if (!AppendPart(PartType::Literal, formattedSize)) {
    126      return Err(ICUError::InternalError);
    127    }
    128  }
    129 
    130  return Ok();
    131 }
    132 }  // namespace mozilla::intl