← Back to team overview

zorba-coders team mailing list archive

[Merge] lp:~paul-lucas/zorba/pjl-misc into lp:zorba

 

Paul J. Lucas has proposed merging lp:~paul-lucas/zorba/pjl-misc into lp:zorba.

Commit message:
1. Added atoll( char const *buf, char const *end, char const **last );
2. Added more aton() functions.
3. Fixed handling of integer overflow.

Requested reviews:
  Paul J. Lucas (paul-lucas)

For more details, see:
https://code.launchpad.net/~paul-lucas/zorba/pjl-misc/+merge/159064

1. Added atoll( char const *buf, char const *end, char const **last );
2. Added more aton() functions.
3. Fixed handling of integer overflow.
-- 
https://code.launchpad.net/~paul-lucas/zorba/pjl-misc/+merge/159064
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'src/util/string_util.cpp'
--- src/util/string_util.cpp	2013-03-31 15:53:11 +0000
+++ src/util/string_util.cpp	2013-04-16 02:34:29 +0000
@@ -56,14 +56,15 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-static void too_big_or_small( char const *buf, char const *last ) {
+static void throw_range_error( char const *buf, char const *last ) {
+  errno = ERANGE;
   zstring const s( buf, last );
   throw std::range_error( BUILD_STRING( '"', s, "\": number too big/small" ) );
 }
 
 inline void check_errno( char const *buf, char const *last ) {
   if ( errno == ERANGE )
-    too_big_or_small( buf, last );
+    throw_range_error( buf, last );
 }
 
 static void check_trailing_chars_impl( char const *last ) {
@@ -149,20 +150,65 @@
   return result;
 }
 
+long long atoll( char const *buf, char const *end, char const **last ) {
+  aton_context const ctx( last );
+  long long n = 0;
+  char const *s0 = ascii::trim_start_whitespace( buf, end - buf );
+  char const *s = s0;
+
+  if ( s < end ) {
+    bool minus = false;
+    switch ( *s ) {
+      case '-':
+        minus = true;
+        // no break;
+      case '+':
+        s0 = ++s;
+        break;
+    }
+    for ( ; s < end && ascii::is_digit( *s ); ++s ) {
+      long long const n_prev = n;
+      n *= 10;
+      if ( n / 10 != n_prev ) // see <http://stackoverflow.com/q/199333/99089>
+        throw_range_error( buf, end );
+      n += *s - '0';
+      if ( n < n_prev )
+        throw_range_error( buf, end );
+    }
+    if ( s == s0 )
+      s = buf;
+    else if ( minus )
+      n = -n;
+  }
+
+  *last = s;
+  check_parse_number( buf, *last, ctx.check_trailing_chars() );
+  return n;
+}
+
 unsigned long long atoull( char const *buf, char const *end,
                            char const **last ) {
   aton_context const ctx( last );
   unsigned long long n = 0;
-  char const *s = ascii::trim_start_whitespace( buf, end - buf );
+  char const *s0 = ascii::trim_start_whitespace( buf, end - buf );
+  char const *s = s0;
 
-  for ( ; s < end && ascii::is_digit( *s ); ++s ) {
-    unsigned long long const n_prev = n;
-    n = n * 10 + *s - '0';
-    if ( n < n_prev ) {
-      errno = ERANGE;
-      too_big_or_small( buf, end );
+  if ( s < end ) {
+    if ( *s == '+' )
+      s0 = ++s;
+    for ( ; s < end && ascii::is_digit( *s ); ++s ) {
+      unsigned long long const n_prev = n;
+      n *= 10;
+      if ( n / 10 != n_prev ) // see <http://stackoverflow.com/q/199333/99089>
+        throw_range_error( buf, end );
+      n += *s - '0';
+      if ( n < n_prev )
+        throw_range_error( buf, end );
     }
+    if ( s == s0 );
+      s = buf;
   }
+
   *last = s;
   check_parse_number( buf, *last, ctx.check_trailing_chars() );
   return n;

=== modified file 'src/util/string_util.h'
--- src/util/string_util.h	2013-03-26 00:25:41 +0000
+++ src/util/string_util.h	2013-04-16 02:34:29 +0000
@@ -414,13 +414,17 @@
  * Parses the given string for a \c double.
  *
  * @param buf The null-terminated C string to parse.  Leading and trailing
- * whitespace is ignored.
+ * whitespace is ignored.  After any leading whitespace, there may be a \c + or
+ * \c - sign, followed by a sequence of decimal digits optionally containing a
+ * single single \c . (decimal-point), optionally followed by an exponent
+ * consisting of an \c e or \c E followed by an optional \c + or \c - sign
+ * followed by a sequence of decimal digits.
  * @param last If not \c null, this is set to point to the character after the
  * last numeric character parsed; if \c null, characters past the last numeric
  * character may only be whitespace.
  * @return Returns the \c double value.
- * @throws invalid_argument if \a buf contains characters other than digits or
- * leading/trailing whitespace, or contains no digits at all.
+ * @throws invalid_argument if \a buf contains characters other than as
+ * described or contains no digits at all.
  * @throws range_error if the number overflows/underflows.
  */
 double atod( char const *buf, char const **last = nullptr );
@@ -429,13 +433,17 @@
  * Parses the given string for a \c float.
  *
  * @param buf The null-terminated C string to parse.  Leading and trailing
- * whitespace is ignored.
+ * whitespace is ignored.  After any leading whitespace, there may be a \c + or
+ * \c - sign, followed by a sequence of decimal digits optionally containing a
+ * single single \c . (decimal-point), optionally followed by an exponent
+ * consisting of an \c e or \c E followed by an optional \c + or \c - sign
+ * followed by a sequence of decimal digits.
  * @param last If not \c null, this is set to point to the character after the
  * last numeric character parsed; if \c null, characters past the last numeric
  * character may only be whitespace.
  * @return Returns the \c float value.
- * @throws invalid_argument if \a buf contains characters other than digits or
- * leading/trailing whitespace, or contains no digits at all.
+ * @throws invalid_argument if \a buf contains characters other than as
+ * described or contains no digits at all.
  * @throws range_error if the number overflows/underflows.
  */
 float atof( char const *buf, char const **last = nullptr );
@@ -444,28 +452,47 @@
  * Parses the given string for a <code>long long</code>.
  *
  * @param buf The null-terminated C string to parse.  Leading and trailing
- * whitespace is ignored.
+ * whitespace is ignored.  After any leading whitespace, there may be a \c + or
+ * \c - sign, followed by a sequence of decimal digits.
  * @param last If not \c null, this is set to point to the character after the
  * last numeric character parsed; if \c null, characters past the last numeric
  * character may only be whitespace.
  * @return Returns the <code>long long</code> value.
- * @throws invalid_argument if \a buf contains characters other than digits or
- * leading/trailing whitespace, or contains no digits at all.
+ * @throws invalid_argument if \a buf contains characters other than as
+ * described or contains no digits at all.
  * @throws range_error if the number overflows/underflows.
  */
 long long atoll( char const *buf, char const **last = nullptr );
 
 /**
+ * Parses the given string for a <code>long long</code>.
+ *
+ * @param buf The C string to parse; it need not be null-terminated.  Leading
+ * and trailing whitespace is ignored.  After any leading whitespace, there may
+ * be a \c + or \c - sign, followed by a sequence of decimal digits.
+ * @param end A pointer to one past the last character to parse.
+ * @param last If not \c null, this is set to point to the character after the
+ * last numeric character parsed; if \c null, characters past the last numeric
+ * character may only be whitespace.
+ * @return Returns the <code>long long</code> value.
+ * @throws invalid_argument if \a buf contains characters other than as
+ * described or contains no digits at all.
+ * @throws range_error if the number overflows.
+ */
+long long atoll( char const *buf, char const *end, char const **last );
+
+/**
  * Parses the given string for an <code>unsigned long long</code>.
  *
  * @param buf The null-terminated C string to parse.  Leading and trailing
- * whitespace is ignored.
+ * whitespace is ignored.  After any leading whitespace, there may be a \c +
+ * sign, followed by a sequence of decimal digits.
  * @param last If not \c null, this is set to point to the character after the
  * last numeric character parsed; if \c null, characters past the last numeric
  * character may only be whitespace.
  * @return Returns the <code>unsigned long long</code> value.
- * @throws invalid_argument if \a buf contains characters other than digits or
- * leading/trailing whitespace, or contains no digits at all.
+ * @throws invalid_argument if \a buf contains characters other than as
+ * described or contains no digits at all.
  * @throws range_error if the number overflows.
  */
 unsigned long long atoull( char const *buf, char const **last = nullptr );
@@ -474,14 +501,15 @@
  * Parses the given string for an <code>unsigned long long</code>.
  *
  * @param buf The C string to parse; it need not be null-terminated.  Leading
- * and trailing whitespace is ignored.
+ * and trailing whitespace is ignored.  After any leading whitespace, there may
+ * be a \c + sign, followed by a sequence of decimal digits.
  * @param end A pointer to one past the last character to parse.
  * @param last If not \c null, this is set to point to the character after the
  * last numeric character parsed; if \c null, characters past the last numeric
  * character may only be whitespace.
  * @return Returns the <code>unsigned long long</code> value.
- * @throws invalid_argument if \a buf contains characters other than digits or
- * leading/trailing whitespace, or contains no digits at all.
+ * @throws invalid_argument if \a buf contains characters other than as
+ * described or contains no digits at all.
  * @throws range_error if the number overflows.
  */
 unsigned long long atoull( char const *buf, char const *end,
@@ -492,117 +520,254 @@
  *
  * @tparam IntegralType The C++ signed integral type to parse for.
  * @param buf The null-terminated C string to parse.  Leading and trailing
- * whitespace is ignored.
- * @param last If not \c null, this is set to point to the character after the
- * last numeric character parsed; if \c null, characters past the last numeric
- * character may only be whitespace.
- * @return Returns the \c IntegralType value.
- * @throws invalid_argument if \a buf contains characters other than digits, a
- * sign, or leading/trailing whitespace, or contains no digits at all.
- * @throws range_error if the number is either too small or too big.
- */
-template<typename IntegralType> inline
-//
-// Note that the is_integral shouldn't be needed since is_signed means "is a
-// signed integral type", but Microsoft's implementation is broken and returns
-// true for floating point types as well.
-//
-typename std::enable_if<ZORBA_TR1_NS::is_integral<IntegralType>::value
-                     && ZORBA_TR1_NS::is_signed<IntegralType>::value,
-                        IntegralType>::type
-aton( char const *buf, char const **last = nullptr ) {
-  long long const result = atoll( buf, last );
-  if ( result < std::numeric_limits<IntegralType>::min() ||
-       result > std::numeric_limits<IntegralType>::max() )
-    throw std::range_error(
-      BUILD_STRING( '"', result, "\": number too big/small" )
-    );
-  return static_cast<IntegralType>( result );
-}
-
-/**
- * Parses the given string for a C++ signed integral type.
- *
- * @tparam IntegralType The C++ signed integral type to parse for.
- * @param buf The null-terminated C string to parse.  Leading and trailing
- * whitespace is ignored.
- * @param low The lower acceptable bound.
- * @param high the higher acceptable bound.
- * @param last If not \c null, this is set to point to the character after the
- * last numeric character parsed; if \c null, characters past the last numeric
- * character may only be whitespace.
- * @return Returns the \c IntegralType value.
- * @throws invalid_argument if \a buf contains characters other than digits, a
- * sign, or leading/trailing whitespace, or contains no digits at all.
- * @throws range_error if the number is either too small or too big.
- */
-template<typename IntegralType> inline
-//
-// Note that the is_integral shouldn't be needed since is_signed means "is a
-// signed integral type", but Microsoft's implementation is broken and returns
-// true for floating point types as well.
-//
-typename std::enable_if<ZORBA_TR1_NS::is_integral<IntegralType>::value
-                     && ZORBA_TR1_NS::is_signed<IntegralType>::value,
-                        IntegralType>::type
-aton( char const *buf, IntegralType low, IntegralType high,
-      char const **last = nullptr ) {
-  long long const result = atoll( buf, last );
-  if ( result < low || result > high )
-    throw std::range_error(
-      BUILD_STRING(
-        '"', result, "\": number not in range ", low, '-', high
-      )
-    );
-  return static_cast<IntegralType>( result );
-}
-
-/**
- * Parses the given string for a C++ unsigned integral types.
- *
- * @tparam IntegralType The C++ unsigned integral type to parse for.
- * @param buf The null-terminated C string to parse.  Leading and trailing
- * whitespace is ignored.
- * @param last If not \c null, this is set to point to the character after the
- * last numeric character parsed; if \c null, characters past the last numeric
- * character may only be whitespace.
- * @return Returns the \c IntegralType value.
- * @throws invalid_argument if \a buf contains characters other than digits, a
- * sign, or leading/trailing whitespace, or contains no digits at all.
- * @throws range_error if the number is either too small or too big.
- */
-template<typename IntegralType> inline
-typename std::enable_if<ZORBA_TR1_NS::is_unsigned<IntegralType>::value,
-                        IntegralType>::type
-aton( char const *buf, char const **last = nullptr ) {
-  unsigned long long const result = atoull( buf, last );
-  if ( result > std::numeric_limits<IntegralType>::max() )
-    throw std::range_error( BUILD_STRING( '"', result, "\": number too big" ) );
-  return static_cast<IntegralType>( result );
-}
-
-/**
- * Parses the given string for a C++ unsigned integral types.
- *
- * @tparam IntegralType The C++ unsigned integral type to parse for.
- * @param buf The null-terminated C string to parse.  Leading and trailing
- * whitespace is ignored.
- * @param low The lower acceptable bound.
- * @param high the higher acceptable bound.
- * @param last If not \c null, this is set to point to the character after the
- * last numeric character parsed; if \c null, characters past the last numeric
- * character may only be whitespace.
- * @return Returns the \c IntegralType value.
- * @throws invalid_argument if \a buf contains characters other than digits or
- * leading/trailing whitespace, or contains no digits at all.
- * @throws range_error if the number is either too small or too big.
- */
-template<typename IntegralType> inline
-typename std::enable_if<ZORBA_TR1_NS::is_unsigned<IntegralType>::value,
-                        IntegralType>::type
-aton( char const *buf, IntegralType low, IntegralType high,
-      char const **last = nullptr ) {
-  unsigned long long const result = atoull( buf, last );
+ * whitespace is ignored.  After any leading whitespace, there may be a \c + or
+ * \c - sign, followed by a sequence of decimal digits.
+ * @param last If not \c null, this is set to point to the character after the
+ * last numeric character parsed; if \c null, characters past the last numeric
+ * character may only be whitespace.
+ * @return Returns the \c IntegralType value.
+ * @throws invalid_argument if \a buf contains characters other than as
+ * described or contains no digits at all.
+ * @throws range_error if the number is either too small or too big.
+ */
+template<typename IntegralType> inline
+//
+// Note that the is_integral shouldn't be needed since is_signed means "is a
+// signed integral type", but Microsoft's implementation is broken and returns
+// true for floating point types as well.
+//
+typename std::enable_if<ZORBA_TR1_NS::is_integral<IntegralType>::value
+                     && ZORBA_TR1_NS::is_signed<IntegralType>::value,
+                        IntegralType>::type
+aton( char const *buf, char const **last = nullptr ) {
+  long long const result = atoll( buf, last );
+  if ( result < std::numeric_limits<IntegralType>::min() ||
+       result > std::numeric_limits<IntegralType>::max() )
+    throw std::range_error(
+      BUILD_STRING( '"', result, "\": number too big/small" )
+    );
+  return static_cast<IntegralType>( result );
+}
+
+/**
+ * Parses the given string for a C++ signed integral type.
+ *
+ * @tparam IntegralType The C++ signed integral type to parse for.
+ * @param buf The null-terminated C string to parse.  Leading and trailing
+ * whitespace is ignored.  After any leading whitespace, there may be a \c + or
+ * \c - sign, followed by a sequence of decimal digits.
+ * @param low The lower acceptable bound.
+ * @param high the higher acceptable bound.
+ * @param last If not \c null, this is set to point to the character after the
+ * last numeric character parsed; if \c null, characters past the last numeric
+ * character may only be whitespace.
+ * @return Returns the \c IntegralType value.
+ * @throws invalid_argument if \a buf contains characters other than as
+ * described or contains no digits at all.
+ * @throws range_error if the number is either too small or too big.
+ */
+template<typename IntegralType> inline
+//
+// Note that the is_integral shouldn't be needed since is_signed means "is a
+// signed integral type", but Microsoft's implementation is broken and returns
+// true for floating point types as well.
+//
+typename std::enable_if<ZORBA_TR1_NS::is_integral<IntegralType>::value
+                     && ZORBA_TR1_NS::is_signed<IntegralType>::value,
+                        IntegralType>::type
+aton( char const *buf, IntegralType low, IntegralType high,
+      char const **last = nullptr ) {
+  long long const result = atoll( buf, last );
+  if ( result < low || result > high )
+    throw std::range_error(
+      BUILD_STRING(
+        '"', result, "\": number not in range ", low, '-', high
+      )
+    );
+  return static_cast<IntegralType>( result );
+}
+
+/**
+ * Parses the given string for a C++ signed integral type.
+ *
+ * @tparam IntegralType The C++ signed integral type to parse for.
+ * @param buf The C string to parse; it need not be null-terminated.  Leading
+ * and trailing whitespace is ignored.  After any leading whitespace, there may
+ * be a \c + or \c - sign, followed by a sequence of decimal digits.
+ * @param end A pointer to one past the last character to parse.
+ * @param last If not \c null, this is set to point to the character after the
+ * last numeric character parsed; if \c null, characters past the last numeric
+ * character may only be whitespace.
+ * @return Returns the \c IntegralType value.
+ * @throws invalid_argument if \a buf contains characters other than as
+ * described or contains no digits at all.
+ * @throws range_error if the number is either too small or too big.
+ */
+template<typename IntegralType> inline
+//
+// Note that the is_integral shouldn't be needed since is_signed means "is a
+// signed integral type", but Microsoft's implementation is broken and returns
+// true for floating point types as well.
+//
+typename std::enable_if<ZORBA_TR1_NS::is_integral<IntegralType>::value
+                     && ZORBA_TR1_NS::is_signed<IntegralType>::value,
+                        IntegralType>::type
+aton( char const *buf, char const *end, char const **last = nullptr ) {
+  long long const result = atoll( buf, end, last );
+  if ( result < std::numeric_limits<IntegralType>::min() ||
+       result > std::numeric_limits<IntegralType>::max() )
+    throw std::range_error(
+      BUILD_STRING( '"', result, "\": number too big/small" )
+    );
+  return static_cast<IntegralType>( result );
+}
+
+/**
+ * Parses the given string for a C++ signed integral type.
+ *
+ * @tparam IntegralType The C++ signed integral type to parse for.
+ * @param buf The null-terminated C string to parse.  Leading and trailing
+ * whitespace is ignored.  After any leading whitespace, there may be a \c + or
+ * \c - sign, followed by a sequence of decimal digits.
+ * @param end A pointer to one past the last character to parse.
+ * @param low The lower acceptable bound.
+ * @param high the higher acceptable bound.
+ * @param last If not \c null, this is set to point to the character after the
+ * last numeric character parsed; if \c null, characters past the last numeric
+ * character may only be whitespace.
+ * @return Returns the \c IntegralType value.
+ * @throws invalid_argument if \a buf contains characters other than as
+ * described or contains no digits at all.
+ * @throws range_error if the number is either too small or too big.
+ */
+template<typename IntegralType> inline
+//
+// Note that the is_integral shouldn't be needed since is_signed means "is a
+// signed integral type", but Microsoft's implementation is broken and returns
+// true for floating point types as well.
+//
+typename std::enable_if<ZORBA_TR1_NS::is_integral<IntegralType>::value
+                     && ZORBA_TR1_NS::is_signed<IntegralType>::value,
+                        IntegralType>::type
+aton( char const *buf, char const *end, IntegralType low, IntegralType high,
+      char const **last = nullptr ) {
+  long long const result = atoll( buf, end, last );
+  if ( result < low || result > high )
+    throw std::range_error(
+      BUILD_STRING(
+        '"', result, "\": number not in range ", low, '-', high
+      )
+    );
+  return static_cast<IntegralType>( result );
+}
+
+/**
+ * Parses the given string for a C++ unsigned integral types.
+ *
+ * @tparam IntegralType The C++ unsigned integral type to parse for.
+ * @param buf The null-terminated C string to parse.  Leading and trailing
+ * whitespace is ignored.  After any leading whitespace, there may be a \c +
+ * sign, followed by a sequence of decimal digits.
+ * @param last If not \c null, this is set to point to the character after the
+ * last numeric character parsed; if \c null, characters past the last numeric
+ * character may only be whitespace.
+ * @return Returns the \c IntegralType value.
+ * @throws invalid_argument if \a buf contains characters other than as
+ * described or contains no digits at all.
+ * @throws range_error if the number is either too small or too big.
+ */
+template<typename IntegralType> inline
+typename std::enable_if<ZORBA_TR1_NS::is_unsigned<IntegralType>::value,
+                        IntegralType>::type
+aton( char const *buf, char const **last = nullptr ) {
+  unsigned long long const result = atoull( buf, last );
+  if ( result > std::numeric_limits<IntegralType>::max() )
+    throw std::range_error( BUILD_STRING( '"', result, "\": number too big" ) );
+  return static_cast<IntegralType>( result );
+}
+
+/**
+ * Parses the given string for a C++ unsigned integral types.
+ *
+ * @tparam IntegralType The C++ unsigned integral type to parse for.
+ * @param buf The null-terminated C string to parse.  Leading and trailing
+ * whitespace is ignored.  After any leading whitespace, there may be a \c +
+ * sign, followed by a sequence of decimal digits.
+ * @param low The lower acceptable bound.
+ * @param high the higher acceptable bound.
+ * @param last If not \c null, this is set to point to the character after the
+ * last numeric character parsed; if \c null, characters past the last numeric
+ * character may only be whitespace.
+ * @return Returns the \c IntegralType value.
+ * @throws invalid_argument if \a buf contains characters other than as
+ * described or contains no digits at all.
+ * @throws range_error if the number is either too small or too big.
+ */
+template<typename IntegralType> inline
+typename std::enable_if<ZORBA_TR1_NS::is_unsigned<IntegralType>::value,
+                        IntegralType>::type
+aton( char const *buf, IntegralType low, IntegralType high,
+      char const **last = nullptr ) {
+  unsigned long long const result = atoull( buf, last );
+  if ( result < low || result > high )
+    throw std::range_error(
+      BUILD_STRING(
+        '"', result, "\": number not in range ", low, '-', high
+      )
+    );
+  return static_cast<IntegralType>( result );
+}
+
+/**
+ * Parses the given string for a C++ unsigned integral types.
+ *
+ * @tparam IntegralType The C++ unsigned integral type to parse for.
+ * @param buf The C string to parse; it need not be null-terminated.  Leading
+ * and trailing whitespace is ignored.  After any leading whitespace, there may
+ * be a \c + sign, followed by a sequence of decimal digits.
+ * @param end A pointer to one past the last character to parse.
+ * @param last If not \c null, this is set to point to the character after the
+ * last numeric character parsed; if \c null, characters past the last numeric
+ * character may only be whitespace.
+ * @return Returns the \c IntegralType value.
+ * @throws invalid_argument if \a buf contains characters other than as
+ * described or contains no digits at all.
+ * @throws range_error if the number is either too small or too big.
+ */
+template<typename IntegralType> inline
+typename std::enable_if<ZORBA_TR1_NS::is_unsigned<IntegralType>::value,
+                        IntegralType>::type
+aton( char const *buf, char const *end, char const **last = nullptr ) {
+  unsigned long long const result = atoull( buf, end, last );
+  if ( result > std::numeric_limits<IntegralType>::max() )
+    throw std::range_error( BUILD_STRING( '"', result, "\": number too big" ) );
+  return static_cast<IntegralType>( result );
+}
+
+/**
+ * Parses the given string for a C++ unsigned integral types.
+ *
+ * @tparam IntegralType The C++ unsigned integral type to parse for.
+ * @param buf The C string to parse; it need not be null-terminated.  Leading
+ * and trailing whitespace is ignored.  After any leading whitespace, there may
+ * be a \c + sign, followed by a sequence of decimal digits.
+ * @param end A pointer to one past the last character to parse.
+ * @param low The lower acceptable bound.
+ * @param high the higher acceptable bound.
+ * @param last If not \c null, this is set to point to the character after the
+ * last numeric character parsed; if \c null, characters past the last numeric
+ * character may only be whitespace.
+ * @return Returns the \c IntegralType value.
+ * @throws invalid_argument if \a buf contains characters other than as
+ * described or contains no digits at all.
+ * @throws range_error if the number is either too small or too big.
+ */
+template<typename IntegralType> inline
+typename std::enable_if<ZORBA_TR1_NS::is_unsigned<IntegralType>::value,
+                        IntegralType>::type
+aton( char const *buf, char const *end, IntegralType low, IntegralType high,
+      char const **last = nullptr ) {
+  unsigned long long const result = atoull( buf, end, last );
   if ( result < low || result > high )
     throw std::range_error(
       BUILD_STRING(
@@ -616,14 +781,17 @@
  * Parses the given string for a C++ \c double type.
  *
  * @param buf The null-terminated C string to parse.  Leading and trailing
- * whitespace is ignored.
+ * whitespace is ignored.  After any leading whitespace, there may be a \c + or
+ * \c - sign, followed by a sequence of decimal digits optionally containing a
+ * single single \c . (decimal-point), optionally followed by an exponent
+ * consisting of an \c e or \c E followed by an optional \c + or \c - sign
+ * followed by a sequence of decimal digits.
  * @param last If not \c null, this is set to point to the character after the
  * last numeric character parsed; if \c null, characters past the last numeric
  * character may only be whitespace.
  * @return Returns the \c double value.
- * @throws invalid_argument if \a buf contains characters other than those for
- * a valid \c double value or leading/trailing whitespace, or contains no
- * digits at all.
+ * @throws invalid_argument if \a buf contains characters other than as
+ * described or contains no digits at all.
  * @throws range_error if the number overflows/underflows.
  */
 template<typename NumericType> inline
@@ -637,14 +805,17 @@
  * Parses the given string for a C++ \c float type.
  *
  * @param buf The null-terminated C string to parse.  Leading and trailing
- * whitespace is ignored.
+ * whitespace is ignored.  After any leading whitespace, there may be a \c + or
+ * \c - sign, followed by a sequence of decimal digits optionally containing a
+ * single single \c . (decimal-point), optionally followed by an exponent
+ * consisting of an \c e or \c E followed by an optional \c + or \c - sign
+ * followed by a sequence of decimal digits.
  * @param last If not \c null, this is set to point to the character after the
  * last numeric character parsed; if \c null, characters past the last numeric
  * character may only be whitespace.
  * @return Returns the \c float value.
- * @throws invalid_argument if \a buf contains characters other than those for
- * a valid \c float value or leading/trailing whitespace, or contains no digits
- * at all.
+ * @throws invalid_argument if \a buf contains characters other than as
+ * described or contains no digits at all.
  * @throws range_error if the number overflows/underflows.
  */
 template<typename NumericType> inline


Follow ups