}
#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;
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.])])
])
#######################