123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- #include "format.h"
- #include "output.h"
- #include <util/generic/ymath.h>
- #include <util/string/cast.h>
- namespace NFormatPrivate {
- static inline i64 Round(double value) {
- double res1 = floor(value);
- double res2 = ceil(value);
- return (value - res1 < res2 - value) ? (i64)res1 : (i64)res2;
- }
- static inline IOutputStream& PrintDoubleShortly(IOutputStream& os, const double& d) {
- // General case: request 3 significant digits
- // Side-effect: allows exponential representation
- EFloatToStringMode mode = PREC_NDIGITS;
- int ndigits = 3;
- if (IsValidFloat(d) && Abs(d) < 1e12) {
- // For reasonably-sized finite values, it's better to avoid
- // exponential representation.
- // Use compact fixed representation and determine
- // precision based on magnitude.
- mode = PREC_POINT_DIGITS_STRIP_ZEROES;
- if (i64(Abs(d) * 100) < 1000) {
- ndigits = 2;
- } else if (i64(Abs(d) * 10) < 1000) {
- ndigits = 1;
- } else {
- ndigits = 0;
- }
- }
- return os << Prec(d, mode, ndigits);
- }
- }
- template <>
- void Out<NFormatPrivate::THumanReadableSize>(IOutputStream& stream, const NFormatPrivate::THumanReadableSize& value) {
- ui64 base = value.Format == SF_BYTES ? 1024 : 1000;
- ui64 base2 = base * base;
- ui64 base3 = base * base2;
- ui64 base4 = base * base3;
- double v = value.Value;
- if (v < 0) {
- stream << "-";
- v = -v;
- }
- if (v < base) {
- NFormatPrivate::PrintDoubleShortly(stream, v);
- } else if (v < base2) {
- NFormatPrivate::PrintDoubleShortly(stream, v / (double)base) << 'K';
- } else if (v < base3) {
- NFormatPrivate::PrintDoubleShortly(stream, v / (double)base2) << 'M';
- } else if (v < base4) {
- NFormatPrivate::PrintDoubleShortly(stream, v / (double)base3) << 'G';
- } else {
- NFormatPrivate::PrintDoubleShortly(stream, v / (double)base4) << 'T';
- }
- if (value.Format == SF_BYTES) {
- if (v < base) {
- stream << "B";
- } else {
- stream << "iB";
- }
- }
- }
- template <>
- void Out<NFormatPrivate::THumanReadableDuration>(IOutputStream& os, const NFormatPrivate::THumanReadableDuration& hr) {
- TTempBuf buf;
- TMemoryOutput ss(buf.Data(), buf.Size());
- do {
- ui64 microSeconds = hr.Value.MicroSeconds();
- if (microSeconds < 1000) {
- ss << microSeconds << "us";
- break;
- }
- if (microSeconds < 1000 * 1000) {
- NFormatPrivate::PrintDoubleShortly(ss, (double)microSeconds / 1000.0) << "ms";
- break;
- }
- double seconds = (double)(hr.Value.MilliSeconds()) / 1000.0;
- if (seconds < 60) {
- NFormatPrivate::PrintDoubleShortly(ss, seconds) << 's';
- break;
- }
- ui64 s = NFormatPrivate::Round(seconds * 1000 + 0.5) / 1000;
- ui64 m = s / 60;
- s = s % 60;
- ui64 h = m / 60;
- m = m % 60;
- ui64 d = h / 24;
- h = h % 24;
- ui64 times[] = {d, h, m, s};
- char names[] = {'d', 'h', 'm', 's'};
- bool first = true;
- for (size_t i = 0; i < Y_ARRAY_SIZE(times); ++i) {
- if (times[i] > 0) {
- if (!first) {
- ss << ' ';
- }
- ss << times[i] << names[i];
- first = false;
- }
- }
- } while (false);
- size_t written = buf.Size() - ss.Avail();
- os.Write(buf.Data(), written);
- }
- void Time(IOutputStream& l) {
- l << millisec();
- }
- void TimeHumanReadable(IOutputStream& l) {
- char timeStr[30];
- const time_t t = time(nullptr);
- l << ctime_r(&t, timeStr);
- }
|