1 #include "simgrid/Exception.hpp"
5 #include "xbt/parse_units.hpp"
7 #include <boost/algorithm/string.hpp>
8 #include <boost/algorithm/string/classification.hpp>
9 #include <boost/algorithm/string/split.hpp>
11 #include <unordered_map>
14 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(parse, xbt, "Parsing functions");
16 class unit_scale : public std::unordered_map<std::string, double> {
18 using std::unordered_map<std::string, double>::unordered_map;
19 // tuples are : <unit, value for unit, base (2 or 10), true if abbreviated>
20 explicit unit_scale(std::initializer_list<std::tuple<const std::string, double, int, bool>> generators);
23 unit_scale::unit_scale(std::initializer_list<std::tuple<const std::string, double, int, bool>> generators)
25 for (const auto& gen : generators) {
26 const std::string& unit = std::get<0>(gen);
27 double value = std::get<1>(gen);
28 const int base = std::get<2>(gen);
29 const bool abbrev = std::get<3>(gen);
31 std::vector<std::string> prefixes;
35 prefixes = abbrev ? std::vector<std::string>{"Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi"}
36 : std::vector<std::string>{"kibi", "mebi", "gibi", "tebi", "pebi", "exbi", "zebi", "yobi"};
40 prefixes = abbrev ? std::vector<std::string>{"k", "M", "G", "T", "P", "E", "Z", "Y"}
41 : std::vector<std::string>{"kilo", "mega", "giga", "tera", "peta", "exa", "zeta", "yotta"};
47 for (const auto& prefix : prefixes) {
49 emplace(prefix + unit, value);
54 /* Note: no warning is issued for unit-less values when `name' is empty. */
55 static double surf_parse_get_value_with_unit(const std::string& filename, int lineno, const char* string,
56 const unit_scale& units, const char* entity_kind, const std::string& name,
57 const char* error_msg, const char* default_unit)
61 double res = strtod(string, &endptr);
62 const char* ptr = endptr; // for const-correctness
64 throw simgrid::ParseError(filename, lineno, std::string("value out of range: ") + string);
66 throw simgrid::ParseError(filename, lineno, std::string("cannot parse number:") + string);
68 // Ok, 0 can be unit-less
69 if (res != 0 && not name.empty())
70 XBT_WARN("Deprecated unit-less value '%s' for %s %s. %s", string, entity_kind, name.c_str(), error_msg);
73 auto u = units.find(ptr);
75 throw simgrid::ParseError(filename, lineno, std::string("unknown unit: ") + ptr);
76 return res * u->second;
79 double xbt_parse_get_time(const std::string& filename, int lineno, const char* string, const char* entity_kind,
80 const std::string& name)
82 static const unit_scale units{std::make_pair("w", 7 * 24 * 60 * 60),
83 std::make_pair("d", 24 * 60 * 60),
84 std::make_pair("h", 60 * 60),
85 std::make_pair("m", 60),
86 std::make_pair("s", 1.0),
87 std::make_pair("ms", 1e-3),
88 std::make_pair("us", 1e-6),
89 std::make_pair("ns", 1e-9),
90 std::make_pair("ps", 1e-12)};
91 return surf_parse_get_value_with_unit(filename, lineno, string, units, entity_kind, name,
92 "Append 's' to your time to get seconds", "s");
95 double surf_parse_get_size(const std::string& filename, int lineno, const char* string, const char* entity_kind,
96 const std::string& name)
98 static const unit_scale units{std::make_tuple("b", 0.125, 2, true), std::make_tuple("b", 0.125, 10, true),
99 std::make_tuple("B", 1.0, 2, true), std::make_tuple("B", 1.0, 10, true)};
100 return surf_parse_get_value_with_unit(filename, lineno, string, units, entity_kind, name,
101 "Append 'B' to get bytes (or 'b' for bits but 1B = 8b).", "B");
104 double xbt_parse_get_bandwidth(const std::string& filename, int lineno, const char* string, const char* entity_kind,
105 const std::string& name)
107 static const unit_scale units{std::make_tuple("bps", 0.125, 2, true), std::make_tuple("bps", 0.125, 10, true),
108 std::make_tuple("Bps", 1.0, 2, true), std::make_tuple("Bps", 1.0, 10, true)};
109 return surf_parse_get_value_with_unit(filename, lineno, string, units, entity_kind, name,
110 "Append 'Bps' to get bytes per second (or 'bps' for bits but 1Bps = 8bps)",
114 std::vector<double> xbt_parse_get_bandwidths(const std::string& filename, int lineno, const char* string,
115 const char* entity_kind, const std::string& name)
117 static const unit_scale units{std::make_tuple("bps", 0.125, 2, true), std::make_tuple("bps", 0.125, 10, true),
118 std::make_tuple("Bps", 1.0, 2, true), std::make_tuple("Bps", 1.0, 10, true)};
120 std::vector<double> bandwidths;
121 std::vector<std::string> tokens;
122 boost::split(tokens, string, boost::is_any_of(";,"));
123 for (auto token : tokens) {
124 bandwidths.push_back(surf_parse_get_value_with_unit(
125 filename, lineno, token.c_str(), units, entity_kind, name,
126 "Append 'Bps' to get bytes per second (or 'bps' for bits but 1Bps = 8bps)", "Bps"));
132 double xbt_parse_get_speed(const std::string& filename, int lineno, const char* string, const char* entity_kind,
133 const std::string& name)
135 static const unit_scale units{std::make_tuple("f", 1.0, 10, true), std::make_tuple("flops", 1.0, 10, false)};
136 return surf_parse_get_value_with_unit(filename, lineno, string, units, entity_kind, name,
137 "Append 'f' or 'flops' to your speed to get flop per second", "f");
140 std::vector<double> xbt_parse_get_all_speeds(const std::string& filename, int lineno, char* speeds,
141 const char* entity_kind, const std::string& id)
143 std::vector<double> speed_per_pstate;
145 if (strchr(speeds, ',') == nullptr) {
146 double speed = xbt_parse_get_speed(filename, lineno, speeds, entity_kind, id);
147 speed_per_pstate.push_back(speed);
149 std::vector<std::string> pstate_list;
150 boost::split(pstate_list, speeds, boost::is_any_of(","));
151 for (auto speed_str : pstate_list) {
152 boost::trim(speed_str);
153 double speed = xbt_parse_get_speed(filename, lineno, speed_str.c_str(), entity_kind, id);
154 speed_per_pstate.push_back(speed);
155 XBT_DEBUG("Speed value: %f", speed);
158 return speed_per_pstate;