CCF
Loading...
Searching...
No Matches
unit_strings.h
Go to the documentation of this file.
1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the Apache 2.0 License.
3#pragma once
4
5#include "ccf/ds/logger.h"
6#include "ccf/ds/nonstd.h"
7
8#include <charconv>
9#include <cmath>
10#include <nlohmann/json.hpp>
11#include <string>
12
13namespace ccf::ds
14{
15 // Inspired by CLI11's AsNumberWithUnit
17 {
18 public:
19 template <class F, typename T>
20 static size_t convert(
21 const std::string_view& input,
22 std::map<std::string_view, T>& mapping,
23 F&& f)
24 {
25 if (input.empty())
26 {
27 throw std::logic_error("Cannot convert empty unit string");
28 }
29
30 auto unit_begin = input.end();
31 while (unit_begin > input.begin() && std::isalpha(*(unit_begin - 1)))
32 {
33 unit_begin--;
34 }
35
36 auto unit = std::string(unit_begin, input.end());
37 ccf::nonstd::to_lower(unit);
38 auto value = std::string(input.begin(), unit_begin);
39
40 size_t ret = 0;
41 auto res =
42 std::from_chars(value.data(), value.data() + value.size(), ret);
43 if (res.ec != std::errc())
44 {
45 throw std::logic_error(fmt::format(
46 "Could not convert value from size string \"{}\": {}",
47 value,
48 res.ec));
49 }
50
51 if (unit.empty())
52 {
53 return ret;
54 }
55
56 auto factor = mapping.find(unit);
57 if (factor == mapping.end())
58 {
59 // Return list of allowed units
60 std::string allowed_units_str;
61 for (auto it = mapping.begin(); it != mapping.end(); ++it)
62 {
63 allowed_units_str += it->first;
64 if (std::next(it) != mapping.end())
65 {
66 allowed_units_str += ", ";
67 }
68 }
69 throw std::logic_error(fmt::format(
70 "Unit {} is invalid. Allowed: {}", unit, allowed_units_str));
71 }
72
73 return f(ret, factor->second);
74 }
75 };
76
77 static size_t convert_size_string(const std::string_view& input)
78 {
79 std::map<std::string_view, size_t> size_suffix_to_power = {
80 {"b", 0}, {"kb", 1}, {"mb", 2}, {"gb", 3}, {"tb", 4}, {"pb", 5}};
81
83 input, size_suffix_to_power, [](size_t value, size_t power) {
84 return value * std::pow(1024, power);
85 });
86 }
87
88 static size_t convert_time_string(const std::string_view& input)
89 {
90 std::map<std::string_view, std::pair<size_t, size_t>> size_suffix_to_power =
91 {{"", {1, 0}},
92 {"us", {1, 0}},
93 {"ms", {1, 3}},
94 {"s", {1, 6}},
95 {"min", {60, 6}},
96 {"h", {36, 8}}};
97
99 input,
100 size_suffix_to_power,
101 [](size_t value, const std::pair<size_t, size_t>& factors) {
102 return value * factors.first * std::pow(10, factors.second);
103 });
104 }
105
107 {
108 std::string str;
109
110 UnitString() = default;
111 UnitString(const std::string_view& str_) : str(str_) {}
112
113 bool operator==(const UnitString&) const = default;
114 };
115
116 inline void to_json(nlohmann::json& j, const UnitString& s)
117 {
118 j = s.str;
119 }
120
122 {
123 size_t value;
124
125 SizeString() = default;
126 SizeString(const std::string_view& str_) :
127 UnitString(str_),
128 value(convert_size_string(str_))
129 {}
130
131 SizeString(const char* str_) :
132 UnitString(str_),
133 value(convert_size_string(str_))
134 {}
135
136 inline operator size_t() const
137 {
138 return value;
139 }
140 };
141
142 inline void from_json(const nlohmann::json& j, SizeString& s)
143 {
144 s = j.get<std::string_view>();
145 }
146
147 inline std::string schema_name(const SizeString*)
148 {
149 return "TimeString";
150 }
151
152 inline void fill_json_schema(nlohmann::json& schema, const SizeString*)
153 {
154 schema["type"] = "string";
155 schema["pattern"] = "^[0-9]+(B|KB|MB|GB|TB|PB)?$";
156 }
157
159 {
160 std::chrono::microseconds value;
161
162 TimeString() = default;
163 TimeString(const std::string_view& str_) :
164 UnitString(str_),
165 value(convert_time_string(str_))
166 {}
167
168 inline operator std::chrono::microseconds() const
169 {
170 return value;
171 }
172
173 inline operator std::chrono::milliseconds() const
174 {
175 return std::chrono::duration_cast<std::chrono::milliseconds>(
176 std::chrono::microseconds(*this));
177 }
178
179 inline operator std::chrono::seconds() const
180 {
181 return std::chrono::duration_cast<std::chrono::seconds>(
182 std::chrono::microseconds(*this));
183 }
184
185 size_t count_ms() const
186 {
187 return std::chrono::milliseconds(*this).count();
188 }
189
190 size_t count_s() const
191 {
192 return std::chrono::seconds(*this).count();
193 }
194 };
195
196 inline void from_json(const nlohmann::json& j, TimeString& s)
197 {
198 s = j.get<std::string_view>();
199 }
200
201 inline std::string schema_name(const TimeString*)
202 {
203 return "TimeString";
204 }
205
206 inline void fill_json_schema(nlohmann::json& schema, const TimeString*)
207 {
208 schema["type"] = "string";
209 schema["pattern"] = "^[0-9]+(us|ms|s|min|h)?$";
210 }
211}
212
213FMT_BEGIN_NAMESPACE
214template <>
215struct formatter<ccf::ds::SizeString>
216{
217 template <typename ParseContext>
218 constexpr auto parse(ParseContext& ctx)
219 {
220 return ctx.begin();
221 }
222
223 template <typename FormatContext>
224 auto format(const ccf::ds::SizeString& v, FormatContext& ctx) const
225 {
226 std::stringstream ss;
227 ss << v.str;
228 return format_to(ctx.out(), "{}", ss.str());
229 }
230};
231FMT_END_NAMESPACE
Definition unit_strings.h:17
static size_t convert(const std::string_view &input, std::map< std::string_view, T > &mapping, F &&f)
Definition unit_strings.h:20
Definition contiguous_set.h:12
std::string schema_name(const SizeString *)
Definition unit_strings.h:147
void from_json(const nlohmann::json &j, SizeString &s)
Definition unit_strings.h:142
void to_json(nlohmann::json &j, const UnitString &s)
Definition unit_strings.h:116
void fill_json_schema(nlohmann::json &schema, const SizeString *)
Definition unit_strings.h:152
Definition app_interface.h:14
Definition unit_strings.h:122
size_t value
Definition unit_strings.h:123
SizeString(const char *str_)
Definition unit_strings.h:131
SizeString(const std::string_view &str_)
Definition unit_strings.h:126
Definition unit_strings.h:159
size_t count_s() const
Definition unit_strings.h:190
std::chrono::microseconds value
Definition unit_strings.h:160
TimeString(const std::string_view &str_)
Definition unit_strings.h:163
size_t count_ms() const
Definition unit_strings.h:185
Definition unit_strings.h:107
UnitString(const std::string_view &str_)
Definition unit_strings.h:111
bool operator==(const UnitString &) const =default
std::string str
Definition unit_strings.h:108
auto format(const ccf::ds::SizeString &v, FormatContext &ctx) const
Definition unit_strings.h:224
constexpr auto parse(ParseContext &ctx)
Definition unit_strings.h:218