llvm.org GIT mirror llvm / 6f3190d
[Support] Add FormatVariadic support for chrono types Summary: The formatter has three knobs: - the user can choose which time unit to use for formatting (default: whatever is the unit of the input) - he can choose whether the unit gets displayed (default: yes) - he can affect the way the number itself is formatted via standard number formatting options (default:default) Reviewers: zturner, inglorion Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D29481 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@294326 91177308-0d34-0410-b5e6-96231b3b80d8 Pavel Labath 3 years ago
3 changed file(s) with 139 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
1010 #define LLVM_SUPPORT_CHRONO_H
1111
1212 #include "llvm/Support/Compiler.h"
13 #include "llvm/Support/FormatProviders.h"
1314
1415 #include
1516 #include
4950
5051 raw_ostream &operator<<(raw_ostream &OS, sys::TimePoint<> TP);
5152
53 /// Implementation of format_provider for duration types.
54 ///
55 /// The options string of a duration type has the grammar:
56 ///
57 /// duration_options ::= [unit][show_unit [number_options]]
58 /// unit ::= `h`|`m`|`s`|`ms|`us`|`ns`
59 /// show_unit ::= `+` | `-`
60 /// number_options ::= options string for a integral or floating point type
61 ///
62 /// Examples
63 /// =================================
64 /// | options | Input | Output |
65 /// =================================
66 /// | "" | 1s | 1 s |
67 /// | "ms" | 1s | 1000 ms |
68 /// | "ms-" | 1s | 1000 |
69 /// | "ms-n" | 1s | 1,000 |
70 /// | "" | 1.0s | 1.00 s |
71 /// =================================
72 ///
73 /// If the unit of the duration type is not one of the units specified above,
74 /// it is still possible to format it, provided you explicitly request a
75 /// display unit or you request that the unit is not displayed.
76
77 namespace detail {
78 template struct unit { static constexpr char value[] = ""; };
79 template constexpr char unit::value[];
80
81 template <> struct unit> {
82 static constexpr char value[] = "h";
83 };
84
85 template <> struct unit> {
86 static constexpr char value[] = "m";
87 };
88
89 template <> struct unit> { static constexpr char value[] = "s"; };
90 template <> struct unit { static constexpr char value[] = "ms"; };
91 template <> struct unit { static constexpr char value[] = "us"; };
92 template <> struct unit { static constexpr char value[] = "ns"; };
93 } // namespace detail
94
95 template
96 struct format_provider> {
97 private:
98 typedef std::chrono::duration Dur;
99 typedef typename std::conditional<
100 std::chrono::treat_as_floating_point::value, double, intmax_t>::type
101 InternalRep;
102
103 template static InternalRep getAs(const Dur &D) {
104 using namespace std::chrono;
105 return duration_cast>(D).count();
106 }
107
108 static std::pair consumeUnit(StringRef &Style,
109 const Dur &D) {
110 using namespace std::chrono;
111 if (Style.consume_front("ns"))
112 return {getAs(D), "ns"};
113 if (Style.consume_front("us"))
114 return {getAs(D), "us"};
115 if (Style.consume_front("ms"))
116 return {getAs(D), "ms"};
117 if (Style.consume_front("s"))
118 return {getAs>(D), "s"};
119 if (Style.consume_front("m"))
120 return {getAs>(D), "m"};
121 if (Style.consume_front("h"))
122 return {getAs>(D), "h"};
123 return {D.count(), detail::unit::value};
124 }
125
126 static bool consumeShowUnit(StringRef &Style) {
127 if (Style.empty())
128 return true;
129 if (Style.consume_front("-"))
130 return false;
131 if (Style.consume_front("+"))
132 return true;
133 assert(0 && "Unrecognised duration format");
134 return true;
135 }
136
137 public:
138 static void format(const Dur &D, llvm::raw_ostream &Stream, StringRef Style) {
139 InternalRep count;
140 StringRef unit;
141 std::tie(count, unit) = consumeUnit(Style, D);
142 bool show_unit = consumeShowUnit(Style);
143
144 format_provider::format(count, Stream, Style);
145
146 if (show_unit) {
147 assert(!unit.empty());
148 Stream << " " << unit;
149 }
150 }
151 };
152
52153 } // namespace llvm
53154
54155 #endif // LLVM_SUPPORT_CHRONO_H
1414 namespace llvm {
1515
1616 using namespace sys;
17
18 constexpr char detail::unit>::value[];
19 constexpr char detail::unit>::value[];
20 constexpr char detail::unit>::value[];
21 constexpr char detail::unit::value[];
22 constexpr char detail::unit::value[];
23 constexpr char detail::unit::value[];
1724
1825 static inline struct tm getStructTM(TimePoint<> TP) {
1926 struct tm Storage;
88
99 #include "llvm/Support/Chrono.h"
1010 #include "llvm/ADT/SmallVector.h"
11 #include "llvm/Support/FormatVariadic.h"
1112 #include "gtest/gtest.h"
1213
1314 using namespace llvm;
7576 EXPECT_EQ(TimeT, toTimeT(Nano));
7677 }
7778
79 TEST(Chrono, DurationFormat) {
80 EXPECT_EQ("1 h", formatv("{0}", hours(1)).str());
81 EXPECT_EQ("1 m", formatv("{0}", minutes(1)).str());
82 EXPECT_EQ("1 s", formatv("{0}", seconds(1)).str());
83 EXPECT_EQ("1 ms", formatv("{0}", milliseconds(1)).str());
84 EXPECT_EQ("1 us", formatv("{0}", microseconds(1)).str());
85 EXPECT_EQ("1 ns", formatv("{0}", nanoseconds(1)).str());
86
87 EXPECT_EQ("1 s", formatv("{0:+}", seconds(1)).str());
88 EXPECT_EQ("1", formatv("{0:-}", seconds(1)).str());
89
90 EXPECT_EQ("1000 ms", formatv("{0:ms}", seconds(1)).str());
91 EXPECT_EQ("1000000 us", formatv("{0:us}", seconds(1)).str());
92 EXPECT_EQ("1000", formatv("{0:ms-}", seconds(1)).str());
93
94 EXPECT_EQ("1,000 ms", formatv("{0:+n}", milliseconds(1000)).str());
95 EXPECT_EQ("0x3e8", formatv("{0:-x}", milliseconds(1000)).str());
96 EXPECT_EQ("010", formatv("{0:-3}", milliseconds(10)).str());
97 EXPECT_EQ("10,000", formatv("{0:ms-n}", seconds(10)).str());
98
99 EXPECT_EQ("1.00 s", formatv("{0}", duration(1)).str());
100 EXPECT_EQ("0.123 s", formatv("{0:+3}", duration(0.123f)).str());
101 EXPECT_EQ("1.230e-01 s", formatv("{0:+e3}", duration(0.123f)).str());
102
103 typedef duration>
104 microfortnights;
105 EXPECT_EQ("1.00", formatv("{0:-}", microfortnights(1)).str());
106 EXPECT_EQ("1209.60 ms", formatv("{0:ms}", microfortnights(1)).str());
107 }
108
78109 } // anonymous namespace