tor-browser

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

DateTimePatternGenerator.h (5636B)


      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 #ifndef intl_components_DateTimePatternGenerator_h_
      5 #define intl_components_DateTimePatternGenerator_h_
      6 
      7 #include "unicode/udatpg.h"
      8 #include "mozilla/EnumSet.h"
      9 #include "mozilla/Result.h"
     10 #include "mozilla/Span.h"
     11 #include "mozilla/UniquePtr.h"
     12 #include "mozilla/intl/ICU4CGlue.h"
     13 #include "mozilla/intl/ICUError.h"
     14 
     15 namespace mozilla::intl {
     16 
     17 class DisplayNames;
     18 
     19 /**
     20 * The DateTimePatternGenerator is the machinery used to work with DateTime
     21 * pattern manipulation. It is expensive to create one, and so generally it is
     22 * created once and then cached. It may be needed to be passed in as an argument
     23 * for different mozilla::intl APIs.
     24 */
     25 class DateTimePatternGenerator final {
     26 public:
     27  explicit DateTimePatternGenerator(UDateTimePatternGenerator* aGenerator)
     28      : mGenerator(aGenerator) {
     29    MOZ_ASSERT(aGenerator);
     30  };
     31 
     32  // Transfer ownership of the UDateTimePatternGenerator in the move
     33  // constructor.
     34  DateTimePatternGenerator(DateTimePatternGenerator&& other) noexcept;
     35 
     36  // Transfer ownership of the UEnumeration in the move assignment operator.
     37  DateTimePatternGenerator& operator=(
     38      DateTimePatternGenerator&& other) noexcept;
     39 
     40  // Disallow copy.
     41  DateTimePatternGenerator(const DateTimePatternGenerator&) = delete;
     42  DateTimePatternGenerator& operator=(const DateTimePatternGenerator&) = delete;
     43 
     44  ~DateTimePatternGenerator();
     45 
     46  static Result<UniquePtr<DateTimePatternGenerator>, ICUError> TryCreate(
     47      const char* aLocale);
     48 
     49  enum class PatternMatchOption {
     50    /**
     51     * Adjust the 'hour' field in the resolved pattern to match the input
     52     * skeleton width.
     53     */
     54    HourField,
     55 
     56    /**
     57     * Adjust the 'minute' field in the resolved pattern to match the input
     58     * skeleton width.
     59     */
     60    MinuteField,
     61 
     62    /**
     63     * Adjust the 'second' field in the resolved pattern to match the input
     64     * skeleton width.
     65     */
     66    SecondField,
     67  };
     68 
     69  /**
     70   * Given a skeleton (a string with unordered datetime fields), get a best
     71   * pattern that will fit for that locale. This pattern will be filled into the
     72   * buffer. e.g. The skeleton "yMd" would return the pattern "M/d/y" for en-US,
     73   * or "dd/MM/y" for en-GB.
     74   */
     75  template <typename B>
     76  ICUResult GetBestPattern(Span<const char16_t> aSkeleton, B& aBuffer,
     77                           EnumSet<PatternMatchOption> options = {}) {
     78    return FillBufferWithICUCall(
     79        aBuffer, [&](UChar* target, int32_t length, UErrorCode* status) {
     80          return udatpg_getBestPatternWithOptions(
     81              mGenerator.GetMut(), aSkeleton.data(),
     82              static_cast<int32_t>(aSkeleton.Length()),
     83              toUDateTimePatternMatchOptions(options), target, length, status);
     84        });
     85  }
     86 
     87  /**
     88   * Get a skeleton (a string with unordered datetime fields) from a pattern.
     89   * For example, both "MMM-dd" and "dd/MMM" produce the skeleton "MMMdd".
     90   */
     91  template <typename B>
     92  static ICUResult GetSkeleton(Span<const char16_t> aPattern, B& aBuffer) {
     93    // At one time udatpg_getSkeleton required a UDateTimePatternGenerator*, but
     94    // now it is valid to pass in a nullptr.
     95    return FillBufferWithICUCall(
     96        aBuffer, [&](UChar* target, int32_t length, UErrorCode* status) {
     97          return udatpg_getSkeleton(nullptr, aPattern.data(),
     98                                    static_cast<int32_t>(aPattern.Length()),
     99                                    target, length, status);
    100        });
    101  }
    102 
    103  /**
    104   * Get a pattern of the form "{1} {0}" to combine separate date and time
    105   * patterns into a single pattern. The "{0}" part is the placeholder for the
    106   * time pattern and "{1}" is the placeholder for the date pattern.
    107   *
    108   * See dateTimeFormat from
    109   * https://unicode.org/reports/tr35/tr35-dates.html#dateTimeFormat
    110   *
    111   * Note:
    112   * In CLDR, it's called Date-Time Combined Format
    113   * https://cldr.unicode.org/translation/date-time/datetime-patterns#h.x7ca7qwzh4m
    114   *
    115   * The naming 'placeholder pattern' is from ICU4X.
    116   * https://unicode-org.github.io/icu4x-docs/doc/icu_pattern/index.html
    117   */
    118  Span<const char16_t> GetPlaceholderPattern() const {
    119    int32_t length;
    120    const char16_t* combined =
    121        udatpg_getDateTimeFormat(mGenerator.GetConst(), &length);
    122    return Span{combined, static_cast<size_t>(length)};
    123  }
    124 
    125 private:
    126  // Allow other mozilla::intl components to access the underlying
    127  // UDateTimePatternGenerator.
    128  friend class DisplayNames;
    129 
    130  UDateTimePatternGenerator* GetUDateTimePatternGenerator() {
    131    return mGenerator.GetMut();
    132  }
    133 
    134  ICUPointer<UDateTimePatternGenerator> mGenerator =
    135      ICUPointer<UDateTimePatternGenerator>(nullptr);
    136 
    137  static UDateTimePatternMatchOptions toUDateTimePatternMatchOptions(
    138      EnumSet<PatternMatchOption> options) {
    139    struct OptionMap {
    140      PatternMatchOption from;
    141      UDateTimePatternMatchOptions to;
    142    } static constexpr map[] = {
    143        {PatternMatchOption::HourField, UDATPG_MATCH_HOUR_FIELD_LENGTH},
    144 #ifndef U_HIDE_INTERNAL_API
    145        {PatternMatchOption::MinuteField, UDATPG_MATCH_MINUTE_FIELD_LENGTH},
    146        {PatternMatchOption::SecondField, UDATPG_MATCH_SECOND_FIELD_LENGTH},
    147 #endif
    148    };
    149 
    150    UDateTimePatternMatchOptions result = UDATPG_MATCH_NO_OPTIONS;
    151    for (const auto& entry : map) {
    152      if (options.contains(entry.from)) {
    153        result = UDateTimePatternMatchOptions(result | entry.to);
    154      }
    155    }
    156    return result;
    157  }
    158 };
    159 
    160 }  // namespace mozilla::intl
    161 #endif