]>
Commit | Line | Data |
---|---|---|
1 | #include <config.h> | |
2 | ||
3 | const DataType *ConfigKey::data_type() const | |
4 | { | |
5 | const struct sr_key_info *info = sr_key_info_get(SR_KEY_CONFIG, id()); | |
6 | if (!info) | |
7 | throw Error(SR_ERR_NA); | |
8 | return DataType::get(info->datatype); | |
9 | } | |
10 | ||
11 | std::string ConfigKey::identifier() const | |
12 | { | |
13 | const struct sr_key_info *info = sr_key_info_get(SR_KEY_CONFIG, id()); | |
14 | if (!info) | |
15 | throw Error(SR_ERR_NA); | |
16 | return valid_string(info->id); | |
17 | } | |
18 | ||
19 | std::string ConfigKey::description() const | |
20 | { | |
21 | const struct sr_key_info *info = sr_key_info_get(SR_KEY_CONFIG, id()); | |
22 | if (!info) | |
23 | throw Error(SR_ERR_NA); | |
24 | return valid_string(info->name); | |
25 | } | |
26 | ||
27 | const ConfigKey *ConfigKey::get_by_identifier(std::string identifier) | |
28 | { | |
29 | const struct sr_key_info *info = sr_key_info_name_get(SR_KEY_CONFIG, identifier.c_str()); | |
30 | if (!info) | |
31 | throw Error(SR_ERR_ARG); | |
32 | return get(info->key); | |
33 | } | |
34 | ||
35 | #ifndef HAVE_STOI_STOD | |
36 | ||
37 | /* Fallback implementation of stoi and stod */ | |
38 | ||
39 | #include <cstdlib> | |
40 | #include <cerrno> | |
41 | #include <stdexcept> | |
42 | #include <limits> | |
43 | ||
44 | static inline int stoi( const std::string& str ) | |
45 | { | |
46 | char *endptr; | |
47 | errno = 0; | |
48 | const long ret = std::strtol(str.c_str(), &endptr, 10); | |
49 | if (endptr == str.c_str()) | |
50 | throw std::invalid_argument("stoi"); | |
51 | else if (errno == ERANGE || | |
52 | ret < std::numeric_limits<int>::min() || | |
53 | ret > std::numeric_limits<int>::max()) | |
54 | throw std::out_of_range("stoi"); | |
55 | else | |
56 | return ret; | |
57 | } | |
58 | ||
59 | static inline double stod( const std::string& str ) | |
60 | { | |
61 | char *endptr; | |
62 | errno = 0; | |
63 | const double ret = std::strtod(str.c_str(), &endptr); | |
64 | if (endptr == str.c_str()) | |
65 | throw std::invalid_argument("stod"); | |
66 | else if (errno == ERANGE) | |
67 | throw std::out_of_range("stod"); | |
68 | else | |
69 | return ret; | |
70 | } | |
71 | #endif | |
72 | ||
73 | #ifndef HAVE_STOUL | |
74 | ||
75 | /* Fallback implementation of stoul. */ | |
76 | ||
77 | #include <cerrno> | |
78 | #include <cstdlib> | |
79 | #include <limits> | |
80 | #include <stdexcept> | |
81 | ||
82 | static inline unsigned long stoul(const std::string &str) | |
83 | { | |
84 | char *endptr; | |
85 | unsigned long ret; | |
86 | errno = 0; | |
87 | ret = std::strtoul(str.c_str(), &endptr, 10); | |
88 | if (endptr == str.c_str()) | |
89 | throw std::invalid_argument("stoul"); | |
90 | /* | |
91 | * TODO Convert to a larger/wider intermediate data type? | |
92 | * Because after conversion into the very target type, the | |
93 | * range check is assumed to be ineffective. | |
94 | */ | |
95 | if (errno == ERANGE || | |
96 | ret < std::numeric_limits<unsigned long>::min() || | |
97 | ret > std::numeric_limits<unsigned long>::max()) | |
98 | throw std::out_of_range("stoul"); | |
99 | return ret; | |
100 | } | |
101 | #endif | |
102 | ||
103 | // Conversion from text to uint32_t, including a range check. | |
104 | // This is sigrok specific, _not_ part of any C++ standard library. | |
105 | static uint32_t stou32(const std::string &str) | |
106 | { | |
107 | unsigned long ret; | |
108 | errno = 0; | |
109 | ret = stoul(str); | |
110 | if (errno == ERANGE) | |
111 | throw std::out_of_range("stou32"); | |
112 | if (ret > std::numeric_limits<uint32_t>::max()) | |
113 | throw std::out_of_range("stou32"); | |
114 | return ret; | |
115 | } | |
116 | ||
117 | Glib::VariantBase ConfigKey::parse_string(std::string value, enum sr_datatype dt) | |
118 | { | |
119 | GVariant *variant; | |
120 | uint64_t p, q; | |
121 | ||
122 | switch (dt) | |
123 | { | |
124 | case SR_T_UINT64: | |
125 | check(sr_parse_sizestring(value.c_str(), &p)); | |
126 | variant = g_variant_new_uint64(p); | |
127 | break; | |
128 | case SR_T_STRING: | |
129 | variant = g_variant_new_string(value.c_str()); | |
130 | break; | |
131 | case SR_T_BOOL: | |
132 | variant = g_variant_new_boolean(sr_parse_boolstring(value.c_str())); | |
133 | break; | |
134 | case SR_T_FLOAT: | |
135 | try { | |
136 | variant = g_variant_new_double(stod(value)); | |
137 | } catch (invalid_argument&) { | |
138 | throw Error(SR_ERR_ARG); | |
139 | } | |
140 | break; | |
141 | case SR_T_RATIONAL_PERIOD: | |
142 | check(sr_parse_period(value.c_str(), &p, &q)); | |
143 | variant = g_variant_new("(tt)", p, q); | |
144 | break; | |
145 | case SR_T_RATIONAL_VOLT: | |
146 | check(sr_parse_voltage(value.c_str(), &p, &q)); | |
147 | variant = g_variant_new("(tt)", p, q); | |
148 | break; | |
149 | case SR_T_INT32: | |
150 | try { | |
151 | variant = g_variant_new_int32(stoi(value)); | |
152 | } catch (invalid_argument&) { | |
153 | throw Error(SR_ERR_ARG); | |
154 | } | |
155 | break; | |
156 | case SR_T_UINT32: | |
157 | try { | |
158 | variant = g_variant_new_uint32(stou32(value)); | |
159 | } catch (invalid_argument&) { | |
160 | throw Error(SR_ERR_ARG); | |
161 | } | |
162 | break; | |
163 | default: | |
164 | throw Error(SR_ERR_BUG); | |
165 | } | |
166 | ||
167 | return Glib::VariantBase(variant, false); | |
168 | } | |
169 | ||
170 | Glib::VariantBase ConfigKey::parse_string(std::string value) const | |
171 | { | |
172 | enum sr_datatype dt = (enum sr_datatype)(data_type()->id()); | |
173 | return parse_string(value, dt); | |
174 | } |