From: Gerhard Sittig Date: Sat, 17 Dec 2022 13:26:09 +0000 (+0100) Subject: bindings/cxx: implement std::stoul() fallback when C++11 is missing X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=f806de1864167feed30952f1ab65497b8ee4152a;p=libsigrok.git bindings/cxx: implement std::stoul() fallback when C++11 is missing Provide an implementation of stoul(3) when the targetted platform does not provide it. This is modelled after the stoi() and stod() routines. --- diff --git a/bindings/cxx/ConfigKey_methods.cpp b/bindings/cxx/ConfigKey_methods.cpp index 7f8c201e..7381c922 100644 --- a/bindings/cxx/ConfigKey_methods.cpp +++ b/bindings/cxx/ConfigKey_methods.cpp @@ -70,6 +70,36 @@ static inline double stod( const std::string& str ) } #endif +#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 + Glib::VariantBase ConfigKey::parse_string(std::string value, enum sr_datatype dt) { GVariant *variant; diff --git a/configure.ac b/configure.ac index c98c55a4..3ba6c8c5 100644 --- a/configure.ac +++ b/configure.ac @@ -465,6 +465,16 @@ AM_COND_IF([BINDINGS_CXX], [ AS_IF([test "x$sr_cv_have_stoi_stod" = xyes], [AC_DEFINE([HAVE_STOI_STOD], [1], [Specifies whether we have the stoi and stod functions.])]) + # In theory std::stoul() should have identical availability + # as std::stoi() and std::stod() have. All of them are C++11. + # But we play it safe here, and check support individually. + AC_CACHE_CHECK([for stoul], [sr_cv_have_stoul], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[(void) std::stoul("1");]])], + [sr_cv_have_stoul=yes], [sr_cv_have_stoul=no])]) + AS_IF([test "x$sr_cv_have_stoul" = xyes], + [AC_DEFINE([HAVE_STOUL], [1], + [Specifies whether we have the std::stoul function.])]) ]) #######################