tor-browser

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

Temporal.h (12275B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=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 #ifndef builtin_temporal_Temporal_h
      8 #define builtin_temporal_Temporal_h
      9 
     10 #include "mozilla/Assertions.h"
     11 
     12 #include <stdint.h>
     13 
     14 #include "jstypes.h"
     15 
     16 #include "builtin/temporal/TemporalRoundingMode.h"
     17 #include "builtin/temporal/TemporalUnit.h"
     18 #include "js/RootingAPI.h"
     19 #include "js/TypeDecls.h"
     20 #include "vm/Int128.h"
     21 #include "vm/NativeObject.h"
     22 
     23 namespace js {
     24 struct ClassSpec;
     25 }  // namespace js
     26 
     27 namespace js::temporal {
     28 
     29 class TemporalObject : public NativeObject {
     30 public:
     31  static const JSClass class_;
     32 
     33 private:
     34  static const ClassSpec classSpec_;
     35 };
     36 
     37 /**
     38 * Rounding increment, which is an integer in the range [1, 1'000'000'000].
     39 *
     40 * Temporal units are rounded to a multiple of the specified increment value.
     41 */
     42 class Increment final {
     43  uint32_t value_;
     44 
     45 public:
     46  constexpr explicit Increment(uint32_t value) : value_(value) {
     47    MOZ_ASSERT(1 <= value && value <= 1'000'000'000);
     48  }
     49 
     50  /**
     51   * Minimum allowed rounding increment.
     52   */
     53  static constexpr auto min() { return Increment{1}; }
     54 
     55  /**
     56   * Maximum allowed rounding increment.
     57   */
     58  static constexpr auto max() { return Increment{1'000'000'000}; }
     59 
     60  /**
     61   * The rounding increment's value.
     62   */
     63  uint32_t value() const { return value_; }
     64 
     65  bool operator==(const Increment& other) const {
     66    return value_ == other.value_;
     67  }
     68 
     69  bool operator<(const Increment& other) const { return value_ < other.value_; }
     70 
     71  // Other operators are implemented in terms of operator== and operator<.
     72  bool operator!=(const Increment& other) const { return !(*this == other); }
     73  bool operator>(const Increment& other) const { return other < *this; }
     74  bool operator<=(const Increment& other) const { return !(other < *this); }
     75  bool operator>=(const Increment& other) const { return !(*this < other); }
     76 };
     77 
     78 /**
     79 * GetRoundingIncrementOption ( normalizedOptions, dividend, inclusive )
     80 */
     81 bool GetRoundingIncrementOption(JSContext* cx, JS::Handle<JSObject*> options,
     82                                Increment* increment);
     83 
     84 /**
     85 * ValidateTemporalRoundingIncrement ( increment, dividend, inclusive )
     86 */
     87 bool ValidateTemporalRoundingIncrement(JSContext* cx, Increment increment,
     88                                       int64_t dividend, bool inclusive);
     89 
     90 /**
     91 * ValidateTemporalRoundingIncrement ( increment, dividend, inclusive )
     92 */
     93 inline bool ValidateTemporalRoundingIncrement(JSContext* cx,
     94                                              Increment increment,
     95                                              Increment dividend,
     96                                              bool inclusive) {
     97  return ValidateTemporalRoundingIncrement(cx, increment, dividend.value(),
     98                                           inclusive);
     99 }
    100 
    101 /**
    102 * MaximumTemporalDurationRoundingIncrement ( unit )
    103 */
    104 constexpr Increment MaximumTemporalDurationRoundingIncrement(
    105    TemporalUnit unit) {
    106  // Step 1. (Not applicable in our implementation.)
    107  MOZ_ASSERT(unit > TemporalUnit::Day);
    108 
    109  // Step 2.
    110  if (unit == TemporalUnit::Hour) {
    111    return Increment{24};
    112  }
    113 
    114  // Step 3.
    115  if (unit <= TemporalUnit::Second) {
    116    return Increment{60};
    117  }
    118 
    119  // Steps 4-5.
    120  return Increment{1000};
    121 }
    122 
    123 enum class TemporalUnitGroup {
    124  // Allow date units: "year", "month", "week", "day".
    125  Date,
    126 
    127  // Allow time units: "hour", "minute", "second", "milli-/micro-/nanoseconds".
    128  Time,
    129 
    130  // Allow date and time units.
    131  DateTime,
    132 
    133  // Allow "day" and time units.
    134  DayTime,
    135 };
    136 
    137 enum class TemporalUnitKey {
    138  SmallestUnit,
    139  LargestUnit,
    140  Unit,
    141 };
    142 
    143 /**
    144 * GetTemporalUnitValuedOption ( options, key, default )
    145 */
    146 bool GetTemporalUnitValuedOption(JSContext* cx, JS::Handle<JSObject*> options,
    147                                 TemporalUnitKey key, TemporalUnit* unit);
    148 
    149 /**
    150 * GetTemporalUnitValuedOption ( normalizedOptions, key, unitGroup, default [ ,
    151 * extraValues ] )
    152 */
    153 bool GetTemporalUnitValuedOption(JSContext* cx, JS::Handle<JSString*> value,
    154                                 TemporalUnitKey key, TemporalUnit* unit);
    155 
    156 /**
    157 * ValidateTemporalUnitValue ( value, unitGroup [ , extraValues ] )
    158 */
    159 bool ValidateTemporalUnitValue(JSContext* cx, TemporalUnitKey key,
    160                               TemporalUnit unit, TemporalUnitGroup unitGroup);
    161 
    162 /**
    163 * GetRoundingModeOption ( normalizedOptions, fallback )
    164 */
    165 bool GetRoundingModeOption(JSContext* cx, JS::Handle<JSObject*> options,
    166                           TemporalRoundingMode* mode);
    167 
    168 /**
    169 * RoundNumberToIncrement ( x, increment, roundingMode )
    170 */
    171 Int128 RoundNumberToIncrement(const Int128& numerator, int64_t denominator,
    172                              Increment increment,
    173                              TemporalRoundingMode roundingMode);
    174 
    175 /**
    176 * RoundNumberToIncrement ( x, increment, roundingMode )
    177 */
    178 int64_t RoundNumberToIncrement(int64_t x, int64_t increment,
    179                               TemporalRoundingMode roundingMode);
    180 
    181 /**
    182 * RoundNumberToIncrement ( x, increment, roundingMode )
    183 */
    184 inline int64_t RoundNumberToIncrement(int64_t x, Increment increment,
    185                                      TemporalRoundingMode roundingMode) {
    186  return RoundNumberToIncrement(x, int64_t(increment.value()), roundingMode);
    187 }
    188 
    189 /**
    190 * RoundNumberToIncrement ( x, increment, roundingMode )
    191 */
    192 Int128 RoundNumberToIncrement(const Int128& x, const Int128& increment,
    193                              TemporalRoundingMode roundingMode);
    194 
    195 /**
    196 * Return the double value of the fractional number `numerator / denominator`.
    197 */
    198 double FractionToDouble(int64_t numerator, int64_t denominator);
    199 
    200 /**
    201 * Return the double value of the fractional number `numerator / denominator`.
    202 */
    203 double FractionToDouble(const Int128& numerator, const Int128& denominator);
    204 
    205 enum class ShowCalendar { Auto, Always, Never, Critical };
    206 
    207 /**
    208 * GetTemporalShowCalendarNameOption ( normalizedOptions )
    209 */
    210 bool GetTemporalShowCalendarNameOption(JSContext* cx,
    211                                       JS::Handle<JSObject*> options,
    212                                       ShowCalendar* result);
    213 
    214 /**
    215 * Precision when displaying fractional seconds.
    216 */
    217 class Precision final {
    218  int8_t value_;
    219 
    220  enum class Tag {};
    221  constexpr Precision(int8_t value, Tag) : value_(value) {}
    222 
    223 public:
    224  constexpr explicit Precision(uint8_t value) : value_(int8_t(value)) {
    225    MOZ_ASSERT(value < 10);
    226  }
    227 
    228  bool operator==(const Precision& other) const {
    229    return value_ == other.value_;
    230  }
    231 
    232  bool operator!=(const Precision& other) const { return !(*this == other); }
    233 
    234  /**
    235   * Return the number of fractional second digits.
    236   */
    237  uint8_t value() const {
    238    MOZ_ASSERT(value_ >= 0, "auto and minute precision don't have a value");
    239    return uint8_t(value_);
    240  }
    241 
    242  /**
    243   * Limit the precision to trim off any trailing zeros.
    244   */
    245  static constexpr Precision Auto() { return {-1, Tag{}}; }
    246 
    247  /**
    248   * Limit the precision to minutes, i.e. don't display seconds and sub-seconds.
    249   */
    250  static constexpr Precision Minute() { return {-2, Tag{}}; }
    251 };
    252 
    253 /**
    254 * GetTemporalFractionalSecondDigitsOption ( normalizedOptions )
    255 */
    256 bool GetTemporalFractionalSecondDigitsOption(JSContext* cx,
    257                                             JS::Handle<JSObject*> options,
    258                                             Precision* precision);
    259 
    260 struct SecondsStringPrecision final {
    261  Precision precision = Precision{0};
    262  TemporalUnit unit = TemporalUnit::Unset;
    263  Increment increment = Increment{1};
    264 };
    265 
    266 /**
    267 * ToSecondsStringPrecisionRecord ( smallestUnit, fractionalDigitCount )
    268 */
    269 SecondsStringPrecision ToSecondsStringPrecision(TemporalUnit smallestUnit,
    270                                                Precision fractionalDigitCount);
    271 
    272 enum class TemporalOverflow { Constrain, Reject };
    273 
    274 /**
    275 * GetTemporalOverflowOption ( normalizedOptions )
    276 */
    277 bool GetTemporalOverflowOption(JSContext* cx, JS::Handle<JSObject*> options,
    278                               TemporalOverflow* result);
    279 
    280 enum class TemporalDisambiguation { Compatible, Earlier, Later, Reject };
    281 
    282 /**
    283 * GetTemporalDisambiguationOption ( options )
    284 */
    285 bool GetTemporalDisambiguationOption(JSContext* cx,
    286                                     JS::Handle<JSObject*> options,
    287                                     TemporalDisambiguation* disambiguation);
    288 
    289 enum class TemporalOffset { Prefer, Use, Ignore, Reject };
    290 
    291 /**
    292 * GetTemporalOffsetOption ( options, fallback )
    293 */
    294 bool GetTemporalOffsetOption(JSContext* cx, JS::Handle<JSObject*> options,
    295                             TemporalOffset* offset);
    296 
    297 enum class ShowTimeZoneName { Auto, Never, Critical };
    298 
    299 bool GetTemporalShowTimeZoneNameOption(JSContext* cx,
    300                                       JS::Handle<JSObject*> options,
    301                                       ShowTimeZoneName* result);
    302 
    303 enum class ShowOffset { Auto, Never };
    304 
    305 /**
    306 * GetTemporalShowOffsetOption ( normalizedOptions )
    307 */
    308 bool GetTemporalShowOffsetOption(JSContext* cx, JS::Handle<JSObject*> options,
    309                                 ShowOffset* result);
    310 
    311 enum class Direction { Next, Previous };
    312 
    313 /**
    314 * GetDirectionOption ( options )
    315 */
    316 bool GetDirectionOption(JSContext* cx, JS::Handle<JSObject*> options,
    317                        Direction* result);
    318 
    319 /**
    320 * GetDirectionOption ( options )
    321 */
    322 bool GetDirectionOption(JSContext* cx, JS::Handle<JSString*> direction,
    323                        Direction* result);
    324 
    325 /**
    326 * IsPartialTemporalObject ( object )
    327 *
    328 * Our implementation performs error reporting in this function instead of in
    329 * the caller to provide better error messages.
    330 */
    331 bool ThrowIfTemporalLikeObject(JSContext* cx, JS::Handle<JSObject*> object);
    332 
    333 /**
    334 * ToPositiveIntegerWithTruncation ( argument )
    335 */
    336 bool ToPositiveIntegerWithTruncation(JSContext* cx, JS::Handle<JS::Value> value,
    337                                     const char* name, double* result);
    338 
    339 /**
    340 * ToIntegerWithTruncation ( argument )
    341 */
    342 bool ToIntegerWithTruncation(JSContext* cx, JS::Handle<JS::Value> value,
    343                             const char* name, double* result);
    344 
    345 enum class TemporalDifference { Since, Until };
    346 
    347 inline const char* ToName(TemporalDifference difference) {
    348  return difference == TemporalDifference::Since ? "since" : "until";
    349 }
    350 
    351 enum class TemporalAddDuration { Add, Subtract };
    352 
    353 inline const char* ToName(TemporalAddDuration addDuration) {
    354  return addDuration == TemporalAddDuration::Add ? "add" : "subtract";
    355 }
    356 
    357 struct DifferenceSettings final {
    358  TemporalUnit smallestUnit = TemporalUnit::Unset;
    359  TemporalUnit largestUnit = TemporalUnit::Unset;
    360  TemporalRoundingMode roundingMode = TemporalRoundingMode::Trunc;
    361  Increment roundingIncrement = Increment{1};
    362 };
    363 
    364 /**
    365 * GetDifferenceSettings ( operation, options, unitGroup, disallowedUnits,
    366 * fallbackSmallestUnit, smallestLargestDefaultUnit )
    367 */
    368 bool GetDifferenceSettings(JSContext* cx, TemporalDifference operation,
    369                           JS::Handle<JSObject*> options,
    370                           TemporalUnitGroup unitGroup,
    371                           TemporalUnit smallestAllowedUnit,
    372                           TemporalUnit fallbackSmallestUnit,
    373                           TemporalUnit smallestLargestDefaultUnit,
    374                           DifferenceSettings* result);
    375 
    376 /**
    377 * GetDifferenceSettings ( operation, options, unitGroup, disallowedUnits,
    378 * fallbackSmallestUnit, smallestLargestDefaultUnit )
    379 */
    380 inline bool GetDifferenceSettings(JSContext* cx, TemporalDifference operation,
    381                                  JS::Handle<JSObject*> options,
    382                                  TemporalUnitGroup unitGroup,
    383                                  TemporalUnit fallbackSmallestUnit,
    384                                  TemporalUnit smallestLargestDefaultUnit,
    385                                  DifferenceSettings* result) {
    386  return GetDifferenceSettings(cx, operation, options, unitGroup,
    387                               TemporalUnit::Nanosecond, fallbackSmallestUnit,
    388                               smallestLargestDefaultUnit, result);
    389 }
    390 
    391 } /* namespace js::temporal */
    392 
    393 #endif /* builtin_temporal_Temporal_h */