tor-browser

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

use-double-conversion.patch (7717B)


      1 diff --git a/include/fmt/format.h b/include/fmt/format.h
      2 --- a/include/fmt/format.h
      3 +++ b/include/fmt/format.h
      4 @@ -28,16 +28,18 @@
      5   of this Software are embedded into a machine-executable object form of such
      6   source code, you may redistribute such embedded portions in such object form
      7   without including the above copyright and permission notices.
      8  */
      9 
     10 #ifndef FMT_FORMAT_H_
     11 #define FMT_FORMAT_H_
     12 
     13 +#include "double-conversion/double-to-string.h"
     14 +
     15 #ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
     16 #  define _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
     17 #  define FMT_REMOVE_TRANSITIVE_INCLUDES
     18 #endif
     19 
     20 #include "base.h"
     21 
     22 #ifndef FMT_MODULE
     23 @@ -3141,16 +3143,23 @@ constexpr auto fractional_part_rounding_
     24   return U"\x9999999a\x828f5c29\x80418938\x80068db9\x8000a7c6\x800010c7"
     25          U"\x800001ae\x8000002b"[index];
     26 }
     27 
     28 template <typename Float>
     29 FMT_CONSTEXPR20 auto format_float(Float value, int precision,
     30                                   const format_specs& specs, bool binary32,
     31                                   buffer<char>& buf) -> int {
     32 +  // GCC and old clang seem to hit this even though this function isn't called.
     33 +  #ifdef __clang__
     34 +  #if __clang_major__ >= 17
     35 +    static_assert(false,
     36 +      "This method is not to be used in Gecko, use format_float_gecko");
     37 +  #endif
     38 +  #endif
     39   // float is passed as double to reduce the number of instantiations.
     40   static_assert(!std::is_same<Float, float>::value, "");
     41   auto converted_value = convert_float(value);
     42 
     43   const bool fixed = specs.type() == presentation_type::fixed;
     44   if (value == 0) {
     45     if (precision <= 0 || !fixed) {
     46       buf.push_back('0');
     47 @@ -3436,68 +3445,109 @@ FMT_CONSTEXPR20 auto format_float(Float
     48       --num_digits;
     49       ++exp;
     50     }
     51     buf.try_resize(num_digits);
     52   }
     53   return exp;
     54 }
     55 
     56 +// See https://bugzilla.mozilla.org/show_bug.cgi?id=1717448#c2 for the reason
     57 +// we're doing this. This copied from and should be kept in sync with
     58 +// PrintfTarget::cvt_f in Gecko's mozglue/misc/Printf.cpp.
     59 +template <typename Float>
     60 +auto format_float_gecko(Float value, int precision, format_specs specs,
     61 +                        buffer<char>& buf) -> int {
     62 +  FMT_ASSERT(detail::isfinite(value),
     63 +    "Non-finite values are to be handled ahead of calling this");
     64 +  using double_conversion::DoubleToStringConverter;
     65 +  using DTSC = DoubleToStringConverter;
     66 +  // Printf.cpp seem to use UNIQUE_ZERO here, but then adds its own `-` further
     67 +  // in the code.
     68 +  char e = specs.upper() ? 'E' : 'e';
     69 +  DTSC converter(DTSC::NO_TRAILING_ZERO |
     70 +                 DTSC::EMIT_POSITIVE_EXPONENT_SIGN,
     71 +                 "inf", "nan", e, 0, 0, 4, 0, 2);
     72 +  buf.try_resize(64);
     73 +  double_conversion::StringBuilder builder(buf.data(), buf.size());
     74 +  // Negative precision defaults to 6.
     75 +  if (precision == -1) { precision = 6; }
     76 +  bool success;
     77 +  if (specs.type() == presentation_type::exp) {
     78 +      success = converter.ToExponential(value, precision, &builder);
     79 +  } else if (specs.type() == presentation_type::fixed) {
     80 +      success = converter.ToFixed(value, precision, &builder);
     81 +  } else if (specs.type() == presentation_type::general ||
     82 +      specs.type() == presentation_type::none) {
     83 +      // "If an explicit precision is zero, it shall be taken as 1."
     84 +      success = converter.ToPrecision(value, precision ? precision : 1, &builder);
     85 +  } else {
     86 +    FMT_ASSERT(false, "Unhandled");
     87 +  }
     88 +  FMT_ASSERT(success, "");
     89 +  buf.try_resize(builder.position());
     90 +  return builder.position();
     91 +}
     92 +
     93 template <typename Char, typename OutputIt, typename T>
     94 FMT_CONSTEXPR20 auto write_float(OutputIt out, T value, format_specs specs,
     95                                  locale_ref loc) -> OutputIt {
     96   // Use signbit because value < 0 is false for NaN.
     97   sign s = detail::signbit(value) ? sign::minus : specs.sign();
     98 
     99   if (!detail::isfinite(value))
    100     return write_nonfinite<Char>(out, detail::isnan(value), specs, s);
    101 
    102   if (specs.align() == align::numeric && s != sign::none) {
    103     *out++ = detail::getsign<Char>(s);
    104     s = sign::none;
    105     if (specs.width != 0) --specs.width;
    106   }
    107 
    108   int precision = specs.precision;
    109 -  if (precision < 0) {
    110 -    if (specs.type() != presentation_type::none) {
    111 -      precision = 6;
    112 -    } else if (is_fast_float<T>::value && !is_constant_evaluated()) {
    113 -      // Use Dragonbox for the shortest format.
    114 -      using floaty = conditional_t<sizeof(T) >= sizeof(double), double, float>;
    115 -      auto dec = dragonbox::to_decimal(static_cast<floaty>(value));
    116 -      return write_float<Char>(out, dec, specs, s, loc);
    117 -    }
    118 -  }
    119 -
    120   memory_buffer buffer;
    121   if (specs.type() == presentation_type::hexfloat) {
    122     if (s != sign::none) buffer.push_back(detail::getsign<char>(s));
    123     format_hexfloat(convert_float(value), specs, buffer);
    124     return write_bytes<Char, align::right>(out, {buffer.data(), buffer.size()},
    125                                            specs);
    126   }
    127 
    128   if (specs.type() == presentation_type::exp) {
    129 -    if (precision == max_value<int>())
    130 -      report_error("number is too big");
    131 -    else
    132 -      ++precision;
    133     if (specs.precision != 0) specs.set_alt();
    134   } else if (specs.type() == presentation_type::fixed) {
    135     if (specs.precision != 0) specs.set_alt();
    136   } else if (precision == 0) {
    137     precision = 1;
    138   }
    139 -  int exp = format_float(convert_float(value), precision, specs,
    140 -                         std::is_same<T, float>(), buffer);
    141 
    142   specs.precision = precision;
    143 -  auto f = big_decimal_fp{buffer.data(), static_cast<int>(buffer.size()), exp};
    144 -  return write_float<Char>(out, f, specs, s, loc);
    145 +  value = abs(value);
    146 +  format_float_gecko(convert_float(value), precision, specs, buffer);
    147 +  size_t size = buffer.size();
    148 +  if (s != sign::none) {
    149 +    // Space for the sign, this influences the padding calculations below.
    150 +    size++;
    151 +    // If padding with zeros, the sign goes here, e.g. -0004.3
    152 +    if (*specs.fill<Char>() == '0') {
    153 +      *out++ = detail::getsign<Char>(s);
    154 +    }
    155 +  }
    156 +  return write_padded<Char, align::right>(
    157 +      out, specs, size, size, [s, &buffer, specs](reserve_iterator<OutputIt> it) {
    158 +        // If padding with something other than zeros, the sign goes here, e.g.
    159 +        // '   -4.3' (quotes added for clarity).
    160 +        if (s != sign::none) {
    161 +          if (*specs.fill<Char>() != '0') {
    162 +            *it++ = detail::getsign<Char>(s);
    163 +          }
    164 +        }
    165 +        const char* data = buffer.data();
    166 +        return copy<Char>(data, data + buffer.size(), it);
    167 +      });
    168 }
    169 
    170 template <typename Char, typename OutputIt, typename T,
    171           FMT_ENABLE_IF(is_floating_point<T>::value)>
    172 FMT_CONSTEXPR20 auto write(OutputIt out, T value, format_specs specs,
    173                            locale_ref loc = {}) -> OutputIt {
    174   return specs.localized() && write_loc(out, value, specs, loc)
    175              ? out
    176 @@ -3513,18 +3563,17 @@ FMT_CONSTEXPR20 auto write(OutputIt out,
    177 
    178   constexpr auto specs = format_specs();
    179   using floaty = conditional_t<sizeof(T) >= sizeof(double), double, float>;
    180   using floaty_uint = typename dragonbox::float_info<floaty>::carrier_uint;
    181   floaty_uint mask = exponent_mask<floaty>();
    182   if ((bit_cast<floaty_uint>(value) & mask) == mask)
    183     return write_nonfinite<Char>(out, std::isnan(value), specs, s);
    184 
    185 -  auto dec = dragonbox::to_decimal(static_cast<floaty>(value));
    186 -  return write_float<Char>(out, dec, specs, s, {});
    187 +  return write_float<Char>(out, value, specs, {});
    188 }
    189 
    190 template <typename Char, typename OutputIt, typename T,
    191           FMT_ENABLE_IF(is_floating_point<T>::value &&
    192                         !is_fast_float<T>::value)>
    193 inline auto write(OutputIt out, T value) -> OutputIt {
    194   return write<Char>(out, value, format_specs());
    195 }