]> sigrok.org Git - libsigrok.git/commitdiff
bindings/cxx: implement std::stoul() fallback when C++11 is missing
authorGerhard Sittig <redacted>
Sat, 17 Dec 2022 13:26:09 +0000 (14:26 +0100)
committerGerhard Sittig <redacted>
Sat, 17 Dec 2022 19:10:30 +0000 (20:10 +0100)
Provide an implementation of stoul(3) when the targetted platform does
not provide it. This is modelled after the stoi() and stod() routines.

bindings/cxx/ConfigKey_methods.cpp
configure.ac

index 7f8c201ed5a8f1e649b4f4e9a452b5c8344e1dd3..7381c922f3203e58a97e83d6d5a48bab3e4beae1 100644 (file)
@@ -70,6 +70,36 @@ static inline double stod( const std::string& str )
 }
 #endif
 
+#ifndef HAVE_STOUL
+
+/* Fallback implementation of stoul. */
+
+#include <cerrno>
+#include <cstdlib>
+#include <limits>
+#include <stdexcept>
+
+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<unsigned long>::min() ||
+               ret > std::numeric_limits<unsigned long>::max())
+               throw std::out_of_range("stoul");
+       return ret;
+}
+#endif
+
 Glib::VariantBase ConfigKey::parse_string(std::string value, enum sr_datatype dt)
 {
        GVariant *variant;
index c98c55a4808b9921bce93e245134afdf481993ed..3ba6c8c5df6dd3e42bcce5c03f27c370da03e19a 100644 (file)
@@ -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 <string>]],
+                               [[(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.])])
 ])
 
 #######################