X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=bindings%2Fcxx%2FConfigKey_methods.cpp;h=d899ddcc2a18d2053470a346051e6f4e5ccca27f;hb=HEAD;hp=9c3668ffbb35e9ee4337b7951c0dc7cac08215e2;hpb=0875f11de44e337397d13af3daf616ec48df6b76;p=libsigrok.git diff --git a/bindings/cxx/ConfigKey_methods.cpp b/bindings/cxx/ConfigKey_methods.cpp index 9c3668ff..d899ddcc 100644 --- a/bindings/cxx/ConfigKey_methods.cpp +++ b/bindings/cxx/ConfigKey_methods.cpp @@ -8,7 +8,7 @@ const DataType *ConfigKey::data_type() const return DataType::get(info->datatype); } -string ConfigKey::identifier() const +std::string ConfigKey::identifier() const { const struct sr_key_info *info = sr_key_info_get(SR_KEY_CONFIG, id()); if (!info) @@ -16,7 +16,7 @@ string ConfigKey::identifier() const return valid_string(info->id); } -string ConfigKey::description() const +std::string ConfigKey::description() const { const struct sr_key_info *info = sr_key_info_get(SR_KEY_CONFIG, id()); if (!info) @@ -24,7 +24,7 @@ string ConfigKey::description() const return valid_string(info->name); } -const ConfigKey *ConfigKey::get_by_identifier(string identifier) +const ConfigKey *ConfigKey::get_by_identifier(std::string identifier) { const struct sr_key_info *info = sr_key_info_name_get(SR_KEY_CONFIG, identifier.c_str()); if (!info) @@ -70,7 +70,51 @@ static inline double stod( const std::string& str ) } #endif -Glib::VariantBase ConfigKey::parse_string(string value, enum sr_datatype dt) +#ifndef HAVE_STOUL + +/* Fallback implementation of stoul. */ + +#include +#include +#include +#include + +static inline unsigned long stoul(const std::string &str) +{ + char *endptr; + unsigned long ret; + errno = 0; + ret = std::strtoul(str.c_str(), &endptr, 10); + if (endptr == str.c_str()) + throw std::invalid_argument("stoul"); + /* + * TODO Convert to a larger/wider intermediate data type? + * Because after conversion into the very target type, the + * range check is assumed to be ineffective. + */ + if (errno == ERANGE || + ret < std::numeric_limits::min() || + ret > std::numeric_limits::max()) + throw std::out_of_range("stoul"); + return ret; +} +#endif + +// Conversion from text to uint32_t, including a range check. +// This is sigrok specific, _not_ part of any C++ standard library. +static uint32_t stou32(const std::string &str) +{ + unsigned long ret; + errno = 0; + ret = stoul(str); + if (errno == ERANGE) + throw std::out_of_range("stou32"); + if (ret > std::numeric_limits::max()) + throw std::out_of_range("stou32"); + return ret; +} + +Glib::VariantBase ConfigKey::parse_string(std::string value, enum sr_datatype dt) { GVariant *variant; uint64_t p, q; @@ -109,6 +153,13 @@ Glib::VariantBase ConfigKey::parse_string(string value, enum sr_datatype dt) throw Error(SR_ERR_ARG); } break; + case SR_T_UINT32: + try { + variant = g_variant_new_uint32(stou32(value)); + } catch (invalid_argument&) { + throw Error(SR_ERR_ARG); + } + break; default: throw Error(SR_ERR_BUG); } @@ -116,7 +167,7 @@ Glib::VariantBase ConfigKey::parse_string(string value, enum sr_datatype dt) return Glib::VariantBase(variant, false); } -Glib::VariantBase ConfigKey::parse_string(string value) const +Glib::VariantBase ConfigKey::parse_string(std::string value) const { enum sr_datatype dt = (enum sr_datatype)(data_type()->id()); return parse_string(value, dt);