]> sigrok.org Git - libsigrok.git/blob - bindings/cxx/ConfigKey_methods.cpp
output/csv: use intermediate time_t var, silence compiler warning
[libsigrok.git] / bindings / cxx / ConfigKey_methods.cpp
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 }