static_assert(is_unsigned<_Tp>::value, "implementation bug");
const ptrdiff_t __len = __last - __first;
- int __i = 0;
+ ptrdiff_t __i = 0;
+ while (__i < __len && __first[__i] == '0')
+ ++__i;
+ const ptrdiff_t __leading_zeroes = __i;
+
while (__i < __len)
{
const unsigned char __c = (unsigned)__first[__i] - '0';
__i++;
}
__first += __i;
- return __i <= __detail::__int_limits<_Tp>::digits;
+ return (__i - __leading_zeroes) <= __detail::__int_limits<_Tp>::digits;
}
/// std::from_chars implementation for integers in bases 3 to 10.
std::from_chars_result r = base == 0
? std::from_chars(begin, end, val)
: std::from_chars(begin, end, val, base);
- return r.ec == std::errc{} && (r.ptr == end || *r.ptr == term) && val == expected;
+ return r.ec == std::errc{} && (r.ptr == end || *r.ptr == term)
+ && val == expected;
}
#include <climits>
test02()
{
// "0x" parsed as "0" not as hex prefix:
- VERIFY( check_from_chars(0, "0x1", 10, 'x') );
- VERIFY( check_from_chars(0, "0X1", 10, 'X') );
- VERIFY( check_from_chars(0, "0x1", 16, 'x') );
- VERIFY( check_from_chars(0, "0X1", 16, 'X') );
+ for (int base = 2; base < 34; ++base)
+ {
+ VERIFY( check_from_chars(0, "0x1", base, 'x') );
+ VERIFY( check_from_chars(0, "0X1", base, 'X') );
+ }
+
+ VERIFY( check_from_chars(1123, "0x1", 34) );
+ VERIFY( check_from_chars(1123, "0X1", 34) );
+ VERIFY( check_from_chars(1156, "0x1", 35) );
+ VERIFY( check_from_chars(1156, "0X1", 35) );
+ VERIFY( check_from_chars(1189, "0x1", 36) );
+ VERIFY( check_from_chars(1189, "0X1", 36) );
VERIFY( check_from_chars(1155, "xx", 34) );
VERIFY( check_from_chars(1155, "XX", 34) );
--- /dev/null
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++14 } }
+
+#include <charconv>
+#include <string>
+#include <testsuite_hooks.h>
+
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+long long
+read(const char* first, const char* last, int base)
+{
+ long long val = 0;
+ long long place = 1;
+ while (last > first)
+ {
+ val += (*--last - '0') * place;
+ place *= base;
+ }
+ return val;
+}
+
+void
+test01()
+{
+ std::from_chars_result res;
+ long long val;
+ for (auto s : { "10001", "10010", "10011", "10101", "10110", "10111",
+ "11001", "11010", "11011", "11101", "11110", "11111" })
+ {
+ std::string ss[2] = { s, std::string(64, '0') + s };
+ for (const auto& str : ss)
+ {
+ const char* first = str.data();
+ for (int base = 2; base < 37; ++base)
+ {
+ const char* last = str.data() + str.length();
+ for (size_t n = 0; n < ss[0].length(); ++n)
+ {
+#ifdef DEBUG
+ printf("Parsing \"%.*s\" in base %d\n", int(last - first), first,
+ base);
+#endif
+ res = std::from_chars(first, last, val, base);
+ VERIFY( res.ptr == last );
+ VERIFY( res.ec == std::errc{} );
+ VERIFY( val == read(first, last, base) );
+ // Test again with shorter string to check from_chars doesn't read
+ // the digits past the last pointer.
+ --last;
+ }
+ }
+ }
+ }
+}
+
+int
+main()
+{
+ test01();
+}