Skip to content

Commit ac0e818

Browse files
committed
SERVER-41495 upgrade libfmt to fix a %g issue
update and run fmt/scripts/import.sh rewrite HostAndPort formatter to avoid now-internal fmt::writer fix merge
1 parent 2bc1da6 commit ac0e818

File tree

16 files changed

+1374
-1482
lines changed

16 files changed

+1374
-1482
lines changed

src/mongo/db/pipeline/document_source_merge.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "mongo/db/pipeline/document_source_merge.h"
3535

3636
#include <fmt/format.h>
37+
#include <fmt/ostream.h>
3738
#include <map>
3839

3940
#include "mongo/db/curop_failpoint_helpers.h"

src/third_party/fmt/dist/include/fmt/chrono.h

Lines changed: 154 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ inline std::tm localtime(std::time_t time) {
4242
return handle(localtime_r(&time_, &tm_));
4343
}
4444

45-
bool handle(std::tm* tm) { return tm != FMT_NULL; }
45+
bool handle(std::tm* tm) { return tm != nullptr; }
4646

4747
bool handle(internal::null<>) {
4848
using namespace fmt::internal;
@@ -56,7 +56,7 @@ inline std::tm localtime(std::time_t time) {
5656
using namespace fmt::internal;
5757
std::tm* tm = std::localtime(&time_);
5858
if (tm) tm_ = *tm;
59-
return tm != FMT_NULL;
59+
return tm != nullptr;
6060
}
6161
#endif
6262
};
@@ -79,7 +79,7 @@ inline std::tm gmtime(std::time_t time) {
7979
return handle(gmtime_r(&time_, &tm_));
8080
}
8181

82-
bool handle(std::tm* tm) { return tm != FMT_NULL; }
82+
bool handle(std::tm* tm) { return tm != nullptr; }
8383

8484
bool handle(internal::null<>) {
8585
using namespace fmt::internal;
@@ -92,7 +92,7 @@ inline std::tm gmtime(std::time_t time) {
9292
bool fallback(internal::null<>) {
9393
std::tm* tm = std::gmtime(&time_);
9494
if (tm) tm_ = *tm;
95-
return tm != FMT_NULL;
95+
return tm != nullptr;
9696
}
9797
#endif
9898
};
@@ -157,7 +157,7 @@ template <typename Char> struct formatter<std::tm, Char> {
157157

158158
namespace internal {
159159
template <typename Period> FMT_CONSTEXPR const char* get_units() {
160-
return FMT_NULL;
160+
return nullptr;
161161
}
162162
template <> FMT_CONSTEXPR const char* get_units<std::atto>() { return "as"; }
163163
template <> FMT_CONSTEXPR const char* get_units<std::femto>() { return "fs"; }
@@ -348,59 +348,107 @@ FMT_CONSTEXPR const Char* parse_chrono_format(const Char* begin,
348348
}
349349

350350
struct chrono_format_checker {
351-
void report_no_date() { FMT_THROW(format_error("no date")); }
351+
FMT_NORETURN void report_no_date() { FMT_THROW(format_error("no date")); }
352352

353353
template <typename Char> void on_text(const Char*, const Char*) {}
354-
void on_abbr_weekday() { report_no_date(); }
355-
void on_full_weekday() { report_no_date(); }
356-
void on_dec0_weekday(numeric_system) { report_no_date(); }
357-
void on_dec1_weekday(numeric_system) { report_no_date(); }
358-
void on_abbr_month() { report_no_date(); }
359-
void on_full_month() { report_no_date(); }
354+
FMT_NORETURN void on_abbr_weekday() { report_no_date(); }
355+
FMT_NORETURN void on_full_weekday() { report_no_date(); }
356+
FMT_NORETURN void on_dec0_weekday(numeric_system) { report_no_date(); }
357+
FMT_NORETURN void on_dec1_weekday(numeric_system) { report_no_date(); }
358+
FMT_NORETURN void on_abbr_month() { report_no_date(); }
359+
FMT_NORETURN void on_full_month() { report_no_date(); }
360360
void on_24_hour(numeric_system) {}
361361
void on_12_hour(numeric_system) {}
362362
void on_minute(numeric_system) {}
363363
void on_second(numeric_system) {}
364-
void on_datetime(numeric_system) { report_no_date(); }
365-
void on_loc_date(numeric_system) { report_no_date(); }
366-
void on_loc_time(numeric_system) { report_no_date(); }
367-
void on_us_date() { report_no_date(); }
368-
void on_iso_date() { report_no_date(); }
364+
FMT_NORETURN void on_datetime(numeric_system) { report_no_date(); }
365+
FMT_NORETURN void on_loc_date(numeric_system) { report_no_date(); }
366+
FMT_NORETURN void on_loc_time(numeric_system) { report_no_date(); }
367+
FMT_NORETURN void on_us_date() { report_no_date(); }
368+
FMT_NORETURN void on_iso_date() { report_no_date(); }
369369
void on_12_hour_time() {}
370370
void on_24_hour_time() {}
371371
void on_iso_time() {}
372372
void on_am_pm() {}
373373
void on_duration_value() {}
374374
void on_duration_unit() {}
375-
void on_utc_offset() { report_no_date(); }
376-
void on_tz_name() { report_no_date(); }
375+
FMT_NORETURN void on_utc_offset() { report_no_date(); }
376+
FMT_NORETURN void on_tz_name() { report_no_date(); }
377377
};
378378

379-
template <typename Int> inline int to_int(Int value) {
380-
FMT_ASSERT(value >= (std::numeric_limits<int>::min)() &&
381-
value <= (std::numeric_limits<int>::max)(),
382-
"invalid value");
379+
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
380+
inline bool isnan(T) {
381+
return false;
382+
}
383+
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
384+
inline bool isnan(T value) {
385+
return std::isnan(value);
386+
}
387+
388+
// Convers value to int and checks that it's in the range [0, upper).
389+
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
390+
inline int to_nonnegative_int(T value, int upper) {
391+
FMT_ASSERT(value >= 0 && value <= upper, "invalid value");
392+
(void)upper;
393+
return static_cast<int>(value);
394+
}
395+
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
396+
inline int to_nonnegative_int(T value, int upper) {
397+
FMT_ASSERT(
398+
std::isnan(value) || (value >= 0 && value <= static_cast<T>(upper)),
399+
"invalid value");
400+
(void)upper;
383401
return static_cast<int>(value);
384402
}
385403

404+
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
405+
inline T mod(T x, int y) {
406+
return x % y;
407+
}
408+
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
409+
inline T mod(T x, int y) {
410+
return std::fmod(x, y);
411+
}
412+
413+
// If T is an integral type, maps T to its unsigned counterpart, otherwise
414+
// leaves it unchanged (unlike std::make_unsigned).
415+
template <typename T, bool INTEGRAL = std::is_integral<T>::value>
416+
struct make_unsigned_or_unchanged {
417+
using type = T;
418+
};
419+
420+
template <typename T> struct make_unsigned_or_unchanged<T, true> {
421+
using type = typename std::make_unsigned<T>::type;
422+
};
423+
424+
template <typename Rep, typename Period,
425+
FMT_ENABLE_IF(std::is_integral<Rep>::value)>
426+
inline std::chrono::duration<Rep, std::milli> get_milliseconds(
427+
std::chrono::duration<Rep, Period> d) {
428+
auto s = std::chrono::duration_cast<std::chrono::seconds>(d);
429+
return std::chrono::duration_cast<std::chrono::milliseconds>(d - s);
430+
}
431+
432+
template <typename Rep, typename Period,
433+
FMT_ENABLE_IF(std::is_floating_point<Rep>::value)>
434+
inline std::chrono::duration<Rep, std::milli> get_milliseconds(
435+
std::chrono::duration<Rep, Period> d) {
436+
auto ms = mod(d.count() * Period::num / Period::den * 1000, 1000);
437+
return std::chrono::duration<Rep, std::milli>(static_cast<Rep>(ms));
438+
}
439+
386440
template <typename Rep, typename OutputIt>
387-
OutputIt static format_chrono_duration_value(OutputIt out, Rep val,
388-
int precision) {
389-
if (precision < 0) {
390-
return format_to(out, std::is_floating_point<Rep>::value ? "{:g}" : "{}",
391-
val);
392-
}
393-
return format_to(out, "{:.{}f}", val, precision);
441+
OutputIt format_chrono_duration_value(OutputIt out, Rep val, int precision) {
442+
if (precision >= 0) return format_to(out, "{:.{}f}", val, precision);
443+
return format_to(out, std::is_floating_point<Rep>::value ? "{:g}" : "{}",
444+
val);
394445
}
395446

396447
template <typename Period, typename OutputIt>
397448
static OutputIt format_chrono_duration_unit(OutputIt out) {
398-
if (const char* unit = get_units<Period>())
399-
return format_to(out, "{}", unit);
400-
else if (Period::den == 1)
401-
return format_to(out, "[{}]s", Period::num);
402-
else
403-
return format_to(out, "[{}/{}]s", Period::num, Period::den);
449+
if (const char* unit = get_units<Period>()) return format_to(out, "{}", unit);
450+
if (Period::den == 1) return format_to(out, "[{}]s", Period::num);
451+
return format_to(out, "[{}/{}]s", Period::num, Period::den);
404452
}
405453

406454
template <typename FormatContext, typename OutputIt, typename Rep,
@@ -409,48 +457,69 @@ struct chrono_formatter {
409457
FormatContext& context;
410458
OutputIt out;
411459
int precision;
412-
Rep val;
413-
typedef std::chrono::duration<Rep, std::milli> milliseconds;
414-
std::chrono::seconds s;
415-
milliseconds ms;
460+
// rep is unsigned to avoid overflow.
461+
using rep =
462+
conditional_t<std::is_integral<Rep>::value && sizeof(Rep) < sizeof(int),
463+
unsigned, typename make_unsigned_or_unchanged<Rep>::type>;
464+
rep val;
465+
typedef std::chrono::duration<rep> seconds;
466+
seconds s;
467+
typedef std::chrono::duration<rep, std::milli> milliseconds;
468+
bool negative;
416469

417470
typedef typename FormatContext::char_type char_type;
418471

419472
explicit chrono_formatter(FormatContext& ctx, OutputIt o,
420473
std::chrono::duration<Rep, Period> d)
421-
: context(ctx),
422-
out(o),
423-
val(d.count()),
424-
s(std::chrono::duration_cast<std::chrono::seconds>(d)),
425-
ms(std::chrono::duration_cast<milliseconds>(d - s)) {}
474+
: context(ctx), out(o), val(d.count()), negative(false) {
475+
if (d.count() < 0) {
476+
val = -val;
477+
negative = true;
478+
}
479+
s = std::chrono::duration_cast<seconds>(
480+
std::chrono::duration<rep, Period>(val));
481+
}
426482

427-
int hour() const { return to_int((s.count() / 3600) % 24); }
483+
Rep hour() const { return static_cast<Rep>(mod((s.count() / 3600), 24)); }
428484

429-
int hour12() const {
430-
auto hour = to_int((s.count() / 3600) % 12);
431-
return hour > 0 ? hour : 12;
485+
Rep hour12() const {
486+
Rep hour = static_cast<Rep>(mod((s.count() / 3600), 12));
487+
return hour <= 0 ? 12 : hour;
432488
}
433489

434-
int minute() const { return to_int((s.count() / 60) % 60); }
435-
int second() const { return to_int(s.count() % 60); }
490+
Rep minute() const { return static_cast<Rep>(mod((s.count() / 60), 60)); }
491+
Rep second() const { return static_cast<Rep>(mod(s.count(), 60)); }
436492

437493
std::tm time() const {
438494
auto time = std::tm();
439-
time.tm_hour = hour();
440-
time.tm_min = minute();
441-
time.tm_sec = second();
495+
time.tm_hour = to_nonnegative_int(hour(), 24);
496+
time.tm_min = to_nonnegative_int(minute(), 60);
497+
time.tm_sec = to_nonnegative_int(second(), 60);
442498
return time;
443499
}
444500

445-
void write(int value, int width) {
501+
void write_sign() {
502+
if (negative) {
503+
*out++ = '-';
504+
negative = false;
505+
}
506+
}
507+
508+
void write(Rep value, int width) {
509+
write_sign();
510+
if (isnan(value)) return write_nan();
446511
typedef typename int_traits<int>::main_type main_type;
447-
main_type n = to_unsigned(value);
512+
main_type n = to_unsigned(
513+
to_nonnegative_int(value, (std::numeric_limits<int>::max)()));
448514
int num_digits = internal::count_digits(n);
449515
if (width > num_digits) out = std::fill_n(out, width - num_digits, '0');
450516
out = format_decimal<char_type>(out, n, num_digits);
451517
}
452518

519+
void write_nan() { std::copy_n("nan", 3, out); }
520+
453521
void format_localized(const tm& time, const char* format) {
522+
if (isnan(val)) return write_nan();
454523
auto locale = context.locale().template get<std::locale>();
455524
auto& facet = std::use_facet<std::time_put<char_type>>(locale);
456525
std::basic_ostringstream<char_type> os;
@@ -482,35 +551,36 @@ struct chrono_formatter {
482551
void on_24_hour(numeric_system ns) {
483552
if (ns == numeric_system::standard) return write(hour(), 2);
484553
auto time = tm();
485-
time.tm_hour = hour();
554+
time.tm_hour = to_nonnegative_int(hour(), 24);
486555
format_localized(time, "%OH");
487556
}
488557

489558
void on_12_hour(numeric_system ns) {
490559
if (ns == numeric_system::standard) return write(hour12(), 2);
491560
auto time = tm();
492-
time.tm_hour = hour();
561+
time.tm_hour = to_nonnegative_int(hour12(), 12);
493562
format_localized(time, "%OI");
494563
}
495564

496565
void on_minute(numeric_system ns) {
497566
if (ns == numeric_system::standard) return write(minute(), 2);
498567
auto time = tm();
499-
time.tm_min = minute();
568+
time.tm_min = to_nonnegative_int(minute(), 60);
500569
format_localized(time, "%OM");
501570
}
502571

503572
void on_second(numeric_system ns) {
504573
if (ns == numeric_system::standard) {
505574
write(second(), 2);
575+
auto ms = get_milliseconds(std::chrono::duration<Rep, Period>(val));
506576
if (ms != std::chrono::milliseconds(0)) {
507577
*out++ = '.';
508-
write(to_int(ms.count()), 3);
578+
write(ms.count(), 3);
509579
}
510580
return;
511581
}
512582
auto time = tm();
513-
time.tm_sec = second();
583+
time.tm_sec = to_nonnegative_int(second(), 60);
514584
format_localized(time, "%OS");
515585
}
516586

@@ -531,6 +601,7 @@ struct chrono_formatter {
531601
void on_am_pm() { format_localized(time(), "%p"); }
532602

533603
void on_duration_value() {
604+
write_sign();
534605
out = format_chrono_duration_value(out, val, precision);
535606
}
536607

@@ -585,28 +656,39 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
585656
}
586657
};
587658

588-
public:
589-
formatter() : spec(), precision(-1) {}
659+
typedef typename basic_parse_context<Char>::iterator iterator;
660+
struct parse_range {
661+
iterator begin;
662+
iterator end;
663+
};
590664

591-
FMT_CONSTEXPR auto parse(basic_parse_context<Char>& ctx)
592-
-> decltype(ctx.begin()) {
665+
FMT_CONSTEXPR parse_range do_parse(basic_parse_context<Char>& ctx) {
593666
auto begin = ctx.begin(), end = ctx.end();
594-
if (begin == end) return begin;
667+
if (begin == end || *begin == '}') return {begin, begin};
595668
spec_handler handler{*this, ctx, format_str};
596669
begin = internal::parse_align(begin, end, handler);
597-
if (begin == end) return begin;
670+
if (begin == end) return {begin, begin};
598671
begin = internal::parse_width(begin, end, handler);
599-
if (begin == end) return begin;
672+
if (begin == end) return {begin, begin};
600673
if (*begin == '.') {
601674
if (std::is_floating_point<Rep>::value)
602675
begin = internal::parse_precision(begin, end, handler);
603676
else
604677
handler.on_error("precision not allowed for this argument type");
605678
}
606679
end = parse_chrono_format(begin, end, internal::chrono_format_checker());
607-
format_str =
608-
basic_string_view<Char>(&*begin, internal::to_unsigned(end - begin));
609-
return end;
680+
return {begin, end};
681+
}
682+
683+
public:
684+
formatter() : spec(), precision(-1) {}
685+
686+
FMT_CONSTEXPR auto parse(basic_parse_context<Char>& ctx)
687+
-> decltype(ctx.begin()) {
688+
auto range = do_parse(ctx);
689+
format_str = basic_string_view<Char>(
690+
&*range.begin, internal::to_unsigned(range.end - range.begin));
691+
return range.end;
610692
}
611693

612694
template <typename FormatContext>
@@ -616,7 +698,7 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
616698
// is not specified.
617699
basic_memory_buffer<Char> buf;
618700
auto out = std::back_inserter(buf);
619-
typedef output_range<decltype(ctx.out()), Char> range;
701+
using range = internal::output_range<decltype(ctx.out()), Char>;
620702
basic_writer<range> w(range(ctx.out()));
621703
internal::handle_dynamic_spec<internal::width_checker>(
622704
spec.width_, width_ref, ctx, format_str.begin());

0 commit comments

Comments
 (0)