gcc/libstdc++-v3/include/std/charconv
Jason Merrill 63a598deb0 libstdc++: #ifdef out #pragma GCC system_header
In r15-3714-gd3a7302ec5985a I added -Wsystem-headers to the libstdc++ build
flags to help catch problems in the library.  This patch takes a different
approach, of disabling the #pragma system_header unless _GLIBCXX_SYSHDR is
defined.  As a result, the testsuites will treat them as non-system-headers
to get better warning coverage during regression testing of both gcc and
libstdc++, not just when building the library.

My rationale for the #ifdef instead of just removing the #pragma is the
three G++ tests that want to test libstdc++ system header behavior, so we
need a way to select it.

This doesn't affect installed libraries, as they get their
system-header status from the lookup path.  But testsuite_flags
--build-includes gives -I directives rather than -isystem.

This patch doesn't change the headers in config/ because I'm not compiling
with most of them, so won't see any warnings that need fixing.  Adjusting
them could happen later, or we can not bother.

libstdc++-v3/ChangeLog:

	* acinclude.m4 (WARN_FLAGS): Remove -Wsystem-headers.
	* configure: Regenerate.
	* include/bits/algorithmfwd.h: #ifdef out #pragma GCC system_header.
	* include/bits/atomic_base.h
	* include/bits/atomic_futex.h
	* include/bits/atomic_timed_wait.h
	* include/bits/atomic_wait.h
	* include/bits/basic_ios.h
	* include/bits/basic_string.h
	* include/bits/boost_concept_check.h
	* include/bits/char_traits.h
	* include/bits/charconv.h
	* include/bits/chrono.h
	* include/bits/chrono_io.h
	* include/bits/codecvt.h
	* include/bits/concept_check.h
	* include/bits/cpp_type_traits.h
	* include/bits/elements_of.h
	* include/bits/enable_special_members.h
	* include/bits/erase_if.h
	* include/bits/forward_list.h
	* include/bits/functional_hash.h
	* include/bits/gslice.h
	* include/bits/gslice_array.h
	* include/bits/hashtable.h
	* include/bits/indirect_array.h
	* include/bits/invoke.h
	* include/bits/ios_base.h
	* include/bits/iterator_concepts.h
	* include/bits/locale_classes.h
	* include/bits/locale_facets.h
	* include/bits/locale_facets_nonio.h
	* include/bits/localefwd.h
	* include/bits/mask_array.h
	* include/bits/max_size_type.h
	* include/bits/memory_resource.h
	* include/bits/memoryfwd.h
	* include/bits/move_only_function.h
	* include/bits/node_handle.h
	* include/bits/ostream_insert.h
	* include/bits/out_ptr.h
	* include/bits/parse_numbers.h
	* include/bits/postypes.h
	* include/bits/quoted_string.h
	* include/bits/range_access.h
	* include/bits/ranges_base.h
	* include/bits/refwrap.h
	* include/bits/sat_arith.h
	* include/bits/semaphore_base.h
	* include/bits/slice_array.h
	* include/bits/std_abs.h
	* include/bits/std_function.h
	* include/bits/std_mutex.h
	* include/bits/std_thread.h
	* include/bits/stl_iterator_base_funcs.h
	* include/bits/stl_iterator_base_types.h
	* include/bits/stl_tree.h
	* include/bits/stream_iterator.h
	* include/bits/streambuf_iterator.h
	* include/bits/stringfwd.h
	* include/bits/this_thread_sleep.h
	* include/bits/unique_lock.h
	* include/bits/uses_allocator_args.h
	* include/bits/utility.h
	* include/bits/valarray_after.h
	* include/bits/valarray_array.h
	* include/bits/valarray_before.h
	* include/bits/version.h
	* include/c_compatibility/fenv.h
	* include/c_compatibility/inttypes.h
	* include/c_compatibility/stdint.h
	* include/decimal/decimal.h
	* include/experimental/bits/net.h
	* include/experimental/bits/shared_ptr.h
	* include/ext/aligned_buffer.h
	* include/ext/alloc_traits.h
	* include/ext/atomicity.h
	* include/ext/concurrence.h
	* include/ext/numeric_traits.h
	* include/ext/pod_char_traits.h
	* include/ext/pointer.h
	* include/ext/stdio_filebuf.h
	* include/ext/stdio_sync_filebuf.h
	* include/ext/string_conversions.h
	* include/ext/type_traits.h
	* include/ext/vstring.h
	* include/ext/vstring_fwd.h
	* include/ext/vstring_util.h
	* include/parallel/algorithmfwd.h
	* include/parallel/numericfwd.h
	* include/tr1/functional_hash.h
	* include/tr1/hashtable.h
	* include/tr1/random.h
	* libsupc++/exception.h
	* libsupc++/hash_bytes.h
	* include/bits/basic_ios.tcc
	* include/bits/basic_string.tcc
	* include/bits/fstream.tcc
	* include/bits/istream.tcc
	* include/bits/locale_classes.tcc
	* include/bits/locale_facets.tcc
	* include/bits/locale_facets_nonio.tcc
	* include/bits/ostream.tcc
	* include/bits/sstream.tcc
	* include/bits/streambuf.tcc
	* include/bits/string_view.tcc
	* include/bits/version.tpl
	* include/experimental/bits/string_view.tcc
	* include/ext/pb_ds/detail/resize_policy/hash_prime_size_policy_imp.hpp
	* include/ext/random.tcc
	* include/ext/vstring.tcc
	* include/tr2/bool_set.tcc
	* include/tr2/dynamic_bitset.tcc
	* include/bits/c++config
	* include/c/cassert
	* include/c/cctype
	* include/c/cerrno
	* include/c/cfloat
	* include/c/ciso646
	* include/c/climits
	* include/c/clocale
	* include/c/cmath
	* include/c/csetjmp
	* include/c/csignal
	* include/c/cstdarg
	* include/c/cstddef
	* include/c/cstdio
	* include/c/cstdlib
	* include/c/cstring
	* include/c/ctime
	* include/c/cuchar
	* include/c/cwchar
	* include/c/cwctype
	* include/c_global/cassert
	* include/c_global/ccomplex
	* include/c_global/cctype
	* include/c_global/cerrno
	* include/c_global/cfenv
	* include/c_global/cfloat
	* include/c_global/cinttypes
	* include/c_global/ciso646
	* include/c_global/climits
	* include/c_global/clocale
	* include/c_global/cmath
	* include/c_global/csetjmp
	* include/c_global/csignal
	* include/c_global/cstdalign
	* include/c_global/cstdarg
	* include/c_global/cstdbool
	* include/c_global/cstddef
	* include/c_global/cstdint
	* include/c_global/cstdio
	* include/c_global/cstdlib
	* include/c_global/cstring
	* include/c_global/ctgmath
	* include/c_global/ctime
	* include/c_global/cuchar
	* include/c_global/cwchar
	* include/c_global/cwctype
	* include/c_std/cassert
	* include/c_std/cctype
	* include/c_std/cerrno
	* include/c_std/cfloat
	* include/c_std/ciso646
	* include/c_std/climits
	* include/c_std/clocale
	* include/c_std/cmath
	* include/c_std/csetjmp
	* include/c_std/csignal
	* include/c_std/cstdarg
	* include/c_std/cstddef
	* include/c_std/cstdio
	* include/c_std/cstdlib
	* include/c_std/cstring
	* include/c_std/ctime
	* include/c_std/cuchar
	* include/c_std/cwchar
	* include/c_std/cwctype
	* include/debug/array
	* include/debug/bitset
	* include/debug/deque
	* include/debug/forward_list
	* include/debug/list
	* include/debug/map
	* include/debug/set
	* include/debug/string
	* include/debug/unordered_map
	* include/debug/unordered_set
	* include/debug/vector
	* include/decimal/decimal
	* include/experimental/algorithm
	* include/experimental/any
	* include/experimental/array
	* include/experimental/buffer
	* include/experimental/chrono
	* include/experimental/contract
	* include/experimental/deque
	* include/experimental/executor
	* include/experimental/filesystem
	* include/experimental/forward_list
	* include/experimental/functional
	* include/experimental/internet
	* include/experimental/io_context
	* include/experimental/iterator
	* include/experimental/list
	* include/experimental/map
	* include/experimental/memory
	* include/experimental/memory_resource
	* include/experimental/net
	* include/experimental/netfwd
	* include/experimental/numeric
	* include/experimental/propagate_const
	* include/experimental/ratio
	* include/experimental/regex
	* include/experimental/scope
	* include/experimental/set
	* include/experimental/socket
	* include/experimental/string
	* include/experimental/string_view
	* include/experimental/synchronized_value
	* include/experimental/system_error
	* include/experimental/timer
	* include/experimental/tuple
	* include/experimental/type_traits
	* include/experimental/unordered_map
	* include/experimental/unordered_set
	* include/experimental/vector
	* include/ext/algorithm
	* include/ext/cmath
	* include/ext/functional
	* include/ext/iterator
	* include/ext/memory
	* include/ext/numeric
	* include/ext/random
	* include/ext/rb_tree
	* include/ext/rope
	* include/parallel/algorithm
	* include/std/algorithm
	* include/std/any
	* include/std/array
	* include/std/atomic
	* include/std/barrier
	* include/std/bit
	* include/std/bitset
	* include/std/charconv
	* include/std/chrono
	* include/std/codecvt
	* include/std/complex
	* include/std/concepts
	* include/std/condition_variable
	* include/std/coroutine
	* include/std/deque
	* include/std/execution
	* include/std/expected
	* include/std/filesystem
	* include/std/format
	* include/std/forward_list
	* include/std/fstream
	* include/std/functional
	* include/std/future
	* include/std/generator
	* include/std/iomanip
	* include/std/ios
	* include/std/iosfwd
	* include/std/iostream
	* include/std/istream
	* include/std/iterator
	* include/std/latch
	* include/std/limits
	* include/std/list
	* include/std/locale
	* include/std/map
	* include/std/memory
	* include/std/memory_resource
	* include/std/mutex
	* include/std/numbers
	* include/std/numeric
	* include/std/optional
	* include/std/ostream
	* include/std/print
	* include/std/queue
	* include/std/random
	* include/std/ranges
	* include/std/ratio
	* include/std/regex
	* include/std/scoped_allocator
	* include/std/semaphore
	* include/std/set
	* include/std/shared_mutex
	* include/std/span
	* include/std/spanstream
	* include/std/sstream
	* include/std/stack
	* include/std/stacktrace
	* include/std/stdexcept
	* include/std/streambuf
	* include/std/string
	* include/std/string_view
	* include/std/syncstream
	* include/std/system_error
	* include/std/text_encoding
	* include/std/thread
	* include/std/tuple
	* include/std/type_traits
	* include/std/typeindex
	* include/std/unordered_map
	* include/std/unordered_set
	* include/std/utility
	* include/std/valarray
	* include/std/variant
	* include/std/vector
	* include/std/version
	* include/tr1/array
	* include/tr1/cfenv
	* include/tr1/cinttypes
	* include/tr1/cmath
	* include/tr1/complex
	* include/tr1/cstdbool
	* include/tr1/cstdint
	* include/tr1/cstdio
	* include/tr1/cstdlib
	* include/tr1/cwchar
	* include/tr1/cwctype
	* include/tr1/functional
	* include/tr1/memory
	* include/tr1/random
	* include/tr1/regex
	* include/tr1/tuple
	* include/tr1/type_traits
	* include/tr1/unordered_map
	* include/tr1/unordered_set
	* include/tr1/utility
	* include/tr2/bool_set
	* include/tr2/dynamic_bitset
	* include/tr2/type_traits
	* libsupc++/atomic_lockfree_defines.h
	* libsupc++/compare
	* libsupc++/cxxabi.h
	* libsupc++/cxxabi_forced.h
	* libsupc++/cxxabi_init_exception.h
	* libsupc++/exception
	* libsupc++/initializer_list
	* libsupc++/new
	* libsupc++/typeinfo: Likewise.
	* testsuite/20_util/ratio/operations/ops_overflow_neg.cc
	* testsuite/23_containers/array/tuple_interface/get_neg.cc
	* testsuite/23_containers/vector/cons/destructible_debug_neg.cc
	* testsuite/24_iterators/operations/prev_neg.cc
	* testsuite/ext/type_traits/add_unsigned_floating_neg.cc
	* testsuite/ext/type_traits/add_unsigned_integer_neg.cc
	* testsuite/ext/type_traits/remove_unsigned_floating_neg.cc
	* testsuite/ext/type_traits/remove_unsigned_integer_neg.cc: Adjust
	line numbers.

gcc/testsuite/ChangeLog

	* g++.dg/analyzer/fanalyzer-show-events-in-system-headers-default.C
	* g++.dg/analyzer/fanalyzer-show-events-in-system-headers-no.C
	* g++.dg/diagnostic/disable.C: #define _GLIBCXX_SYSHDR.
2024-09-25 08:20:45 -04:00

942 lines
29 KiB
C++

// Primitive numeric conversions (to_chars and from_chars) -*- C++ -*-
// Copyright (C) 2017-2024 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.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
/** @file include/charconv
* This is a Standard C++ Library header.
*/
#ifndef _GLIBCXX_CHARCONV
#define _GLIBCXX_CHARCONV 1
#ifdef _GLIBCXX_SYSHDR
#pragma GCC system_header
#endif
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic" // __int128
#include <bits/requires_hosted.h> // for error codes
// As an extension we support <charconv> in C++14, but this header should not
// be included by any other library headers in C++14 mode. This ensures that
// the names defined in this header are not added to namespace std unless a
// user explicitly includes <charconv> in C++14 code.
#if __cplusplus >= 201402L
#include <type_traits>
#include <bit> // for __bit_width
#include <bits/charconv.h> // for __to_chars_len, __to_chars_10_impl
#include <bits/error_constants.h> // for std::errc
#include <ext/numeric_traits.h>
#define __glibcxx_want_to_chars
#define __glibcxx_want_constexpr_charconv
#include <bits/version.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Result type of std::to_chars
struct to_chars_result
{
char* ptr;
errc ec;
#if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L
friend bool
operator==(const to_chars_result&, const to_chars_result&) = default;
#endif
#if __cplusplus > 202302L
constexpr explicit operator bool() const noexcept { return ec == errc{}; }
#endif
};
/// Result type of std::from_chars
struct from_chars_result
{
const char* ptr;
errc ec;
#if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L
friend bool
operator==(const from_chars_result&, const from_chars_result&) = default;
#endif
#if __cplusplus > 202302L
constexpr explicit operator bool() const noexcept { return ec == errc{}; }
#endif
};
namespace __detail
{
// Pick an unsigned type of suitable size. This is used to reduce the
// number of specializations of __to_chars_len, __to_chars etc. that
// get instantiated. For example, to_chars<char> and to_chars<short>
// and to_chars<unsigned> will all use the same code, and so will
// to_chars<long> when sizeof(int) == sizeof(long).
template<typename _Tp>
struct __to_chars_unsigned_type : __make_unsigned_selector_base
{
using _UInts = _List<unsigned int, unsigned long, unsigned long long
#if __SIZEOF_INT128__ > __SIZEOF_LONG_LONG__
, unsigned __int128
#endif
>;
using type = typename __select<sizeof(_Tp), _UInts>::__type;
};
template<typename _Tp>
using __unsigned_least_t = typename __to_chars_unsigned_type<_Tp>::type;
// Generic implementation for arbitrary bases.
// Defined in <bits/charconv.h>.
template<typename _Tp>
constexpr unsigned
__to_chars_len(_Tp __value, int __base /* = 10 */) noexcept;
template<typename _Tp>
constexpr unsigned
__to_chars_len_2(_Tp __value) noexcept
{ return std::__bit_width(__value); }
// Generic implementation for arbitrary bases.
template<typename _Tp>
constexpr to_chars_result
__to_chars(char* __first, char* __last, _Tp __val, int __base) noexcept
{
static_assert(__integer_to_chars_is_unsigned<_Tp>, "implementation bug");
to_chars_result __res;
const unsigned __len = __to_chars_len(__val, __base);
if (__builtin_expect(size_t(__last - __first) < __len, 0))
{
__res.ptr = __last;
__res.ec = errc::value_too_large;
return __res;
}
unsigned __pos = __len - 1;
constexpr char __digits[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z'
};
while (__val >= (unsigned)__base)
{
auto const __quo = __val / __base;
auto const __rem = __val % __base;
__first[__pos--] = __digits[__rem];
__val = __quo;
}
*__first = __digits[__val];
__res.ptr = __first + __len;
__res.ec = {};
return __res;
}
template<typename _Tp>
constexpr to_chars_result
__to_chars_16(char* __first, char* __last, _Tp __val) noexcept
{
static_assert(__integer_to_chars_is_unsigned<_Tp>, "implementation bug");
to_chars_result __res;
const unsigned __len = (__to_chars_len_2(__val) + 3) / 4;
if (__builtin_expect(size_t(__last - __first) < __len, 0))
{
__res.ptr = __last;
__res.ec = errc::value_too_large;
return __res;
}
constexpr char __digits[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f'
};
unsigned __pos = __len - 1;
while (__val >= 0x100)
{
auto __num = __val & 0xF;
__val >>= 4;
__first[__pos] = __digits[__num];
__num = __val & 0xF;
__val >>= 4;
__first[__pos - 1] = __digits[__num];
__pos -= 2;
}
if (__val >= 0x10)
{
const auto __num = __val & 0xF;
__val >>= 4;
__first[1] = __digits[__num];
__first[0] = __digits[__val];
}
else
__first[0] = __digits[__val];
__res.ptr = __first + __len;
__res.ec = {};
return __res;
}
template<typename _Tp>
constexpr to_chars_result
__to_chars_10(char* __first, char* __last, _Tp __val) noexcept
{
static_assert(__integer_to_chars_is_unsigned<_Tp>, "implementation bug");
to_chars_result __res;
const unsigned __len = __to_chars_len(__val, 10);
if (__builtin_expect(size_t(__last - __first) < __len, 0))
{
__res.ptr = __last;
__res.ec = errc::value_too_large;
return __res;
}
__detail::__to_chars_10_impl(__first, __len, __val);
__res.ptr = __first + __len;
__res.ec = {};
return __res;
}
template<typename _Tp>
constexpr to_chars_result
__to_chars_8(char* __first, char* __last, _Tp __val) noexcept
{
static_assert(__integer_to_chars_is_unsigned<_Tp>, "implementation bug");
to_chars_result __res;
unsigned __len = 0;
if _GLIBCXX17_CONSTEXPR (__gnu_cxx::__int_traits<_Tp>::__digits <= 16)
{
__len = __val > 077777u ? 6u
: __val > 07777u ? 5u
: __val > 0777u ? 4u
: __val > 077u ? 3u
: __val > 07u ? 2u
: 1u;
}
else
__len = (__to_chars_len_2(__val) + 2) / 3;
if (__builtin_expect(size_t(__last - __first) < __len, 0))
{
__res.ptr = __last;
__res.ec = errc::value_too_large;
return __res;
}
unsigned __pos = __len - 1;
while (__val >= 0100)
{
auto __num = __val & 7;
__val >>= 3;
__first[__pos] = '0' + __num;
__num = __val & 7;
__val >>= 3;
__first[__pos - 1] = '0' + __num;
__pos -= 2;
}
if (__val >= 010)
{
auto const __num = __val & 7;
__val >>= 3;
__first[1] = '0' + __num;
__first[0] = '0' + __val;
}
else
__first[0] = '0' + __val;
__res.ptr = __first + __len;
__res.ec = {};
return __res;
}
template<typename _Tp>
constexpr to_chars_result
__to_chars_2(char* __first, char* __last, _Tp __val) noexcept
{
static_assert(__integer_to_chars_is_unsigned<_Tp>, "implementation bug");
to_chars_result __res;
const unsigned __len = __to_chars_len_2(__val);
if (__builtin_expect(size_t(__last - __first) < __len, 0))
{
__res.ptr = __last;
__res.ec = errc::value_too_large;
return __res;
}
unsigned __pos = __len - 1;
while (__pos)
{
__first[__pos--] = '0' + (__val & 1);
__val >>= 1;
}
// First digit is always '1' because __to_chars_len_2 skips
// leading zero bits and std::to_chars handles zero values
// directly.
__first[0] = '1';
__res.ptr = __first + __len;
__res.ec = {};
return __res;
}
} // namespace __detail
template<typename _Tp>
constexpr to_chars_result
__to_chars_i(char* __first, char* __last, _Tp __value, int __base = 10)
{
__glibcxx_assert(2 <= __base && __base <= 36);
using _Up = __detail::__unsigned_least_t<_Tp>;
_Up __unsigned_val = __value;
if (__first >= __last) [[__unlikely__]]
return { __last, errc::value_too_large };
if (__value == 0)
{
*__first = '0';
return { __first + 1, errc{} };
}
else if _GLIBCXX17_CONSTEXPR (std::is_signed<_Tp>::value)
if (__value < 0)
{
*__first++ = '-';
__unsigned_val = _Up(~__value) + _Up(1);
}
switch (__base)
{
case 16:
return __detail::__to_chars_16(__first, __last, __unsigned_val);
case 10:
return __detail::__to_chars_10(__first, __last, __unsigned_val);
case 8:
return __detail::__to_chars_8(__first, __last, __unsigned_val);
case 2:
return __detail::__to_chars_2(__first, __last, __unsigned_val);
default:
return __detail::__to_chars(__first, __last, __unsigned_val, __base);
}
}
#define _GLIBCXX_TO_CHARS(T) \
_GLIBCXX23_CONSTEXPR inline to_chars_result \
to_chars(char* __first, char* __last, T __value, int __base = 10) \
{ return std::__to_chars_i<T>(__first, __last, __value, __base); }
_GLIBCXX_TO_CHARS(char)
_GLIBCXX_TO_CHARS(signed char)
_GLIBCXX_TO_CHARS(unsigned char)
_GLIBCXX_TO_CHARS(signed short)
_GLIBCXX_TO_CHARS(unsigned short)
_GLIBCXX_TO_CHARS(signed int)
_GLIBCXX_TO_CHARS(unsigned int)
_GLIBCXX_TO_CHARS(signed long)
_GLIBCXX_TO_CHARS(unsigned long)
_GLIBCXX_TO_CHARS(signed long long)
_GLIBCXX_TO_CHARS(unsigned long long)
#if defined(__GLIBCXX_TYPE_INT_N_0)
_GLIBCXX_TO_CHARS(signed __GLIBCXX_TYPE_INT_N_0)
_GLIBCXX_TO_CHARS(unsigned __GLIBCXX_TYPE_INT_N_0)
#endif
#if defined(__GLIBCXX_TYPE_INT_N_1)
_GLIBCXX_TO_CHARS(signed __GLIBCXX_TYPE_INT_N_1)
_GLIBCXX_TO_CHARS(unsigned __GLIBCXX_TYPE_INT_N_1)
#endif
#if defined(__GLIBCXX_TYPE_INT_N_2)
_GLIBCXX_TO_CHARS(signed __GLIBCXX_TYPE_INT_N_2)
_GLIBCXX_TO_CHARS(unsigned __GLIBCXX_TYPE_INT_N_2)
#endif
#if defined(__GLIBCXX_TYPE_INT_N_3)
_GLIBCXX_TO_CHARS(signed __GLIBCXX_TYPE_INT_N_3)
_GLIBCXX_TO_CHARS(unsigned __GLIBCXX_TYPE_INT_N_3)
#endif
#undef _GLIBCXX_TO_CHARS
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 3266. to_chars(bool) should be deleted
to_chars_result to_chars(char*, char*, bool, int = 10) = delete;
namespace __detail
{
template<typename _Tp>
constexpr bool
__raise_and_add(_Tp& __val, int __base, unsigned char __c)
{
if (__builtin_mul_overflow(__val, __base, &__val)
|| __builtin_add_overflow(__val, __c, &__val))
return false;
return true;
}
template<bool _DecOnly>
struct __from_chars_alnum_to_val_table
{
struct type { unsigned char __data[1u << __CHAR_BIT__] = {}; };
// Construct and return a lookup table that maps 0-9, A-Z and a-z to their
// corresponding base-36 value and maps all other characters to 127.
static constexpr type
_S_make_table()
{
constexpr unsigned char __lower_letters[27] = "abcdefghijklmnopqrstuvwxyz";
constexpr unsigned char __upper_letters[27] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
type __table;
for (auto& __entry : __table.__data)
__entry = 127;
for (int __i = 0; __i < 10; ++__i)
__table.__data['0' + __i] = __i;
for (int __i = 0; __i < 26; ++__i)
{
__table.__data[__lower_letters[__i]] = 10 + __i;
__table.__data[__upper_letters[__i]] = 10 + __i;
}
return __table;
}
// This initializer is made superficially dependent in order
// to prevent the compiler from wastefully constructing the
// table ahead of time when it's not needed.
static constexpr type value = (_DecOnly, _S_make_table());
};
#if ! __cpp_inline_variables
template<bool _DecOnly>
const typename __from_chars_alnum_to_val_table<_DecOnly>::type
__from_chars_alnum_to_val_table<_DecOnly>::value;
#endif
// If _DecOnly is true: if the character is a decimal digit, then
// return its corresponding base-10 value, otherwise return a value >= 127.
// If _DecOnly is false: if the character is an alphanumeric digit, then
// return its corresponding base-36 value, otherwise return a value >= 127.
template<bool _DecOnly = false>
_GLIBCXX20_CONSTEXPR unsigned char
__from_chars_alnum_to_val(unsigned char __c)
{
if _GLIBCXX17_CONSTEXPR (_DecOnly)
return static_cast<unsigned char>(__c - '0');
else
return __from_chars_alnum_to_val_table<_DecOnly>::value.__data[__c];
}
/// std::from_chars implementation for integers in a power-of-two base.
/// If _DecOnly is true, then we may assume __base is at most 8.
template<bool _DecOnly, typename _Tp>
_GLIBCXX23_CONSTEXPR bool
__from_chars_pow2_base(const char*& __first, const char* __last, _Tp& __val,
int __base)
{
static_assert(is_integral<_Tp>::value, "implementation bug");
static_assert(is_unsigned<_Tp>::value, "implementation bug");
// __glibcxx_assert((__base & (__base - 1)) == 0);
// __glibcxx_assert(_DecOnly ? __base <= 8 : __base <= 32);
const int __log2_base = __countr_zero(unsigned(__base & 0x3f));
const ptrdiff_t __len = __last - __first;
ptrdiff_t __i = 0;
while (__i < __len && __first[__i] == '0')
++__i;
const ptrdiff_t __leading_zeroes = __i;
if (__i >= __len) [[__unlikely__]]
{
__first += __i;
return true;
}
// Remember the leading significant digit value if necessary.
unsigned char __leading_c = 0;
if (__base != 2)
{
__leading_c = __from_chars_alnum_to_val<_DecOnly>(__first[__i]);
// __glibcxx_assert(__leading_c != 0);
if (__leading_c >= __base) [[__unlikely__]]
{
__first += __i;
return true;
}
__val = __leading_c;
++__i;
}
for (; __i < __len; ++__i)
{
const unsigned char __c = __from_chars_alnum_to_val<_DecOnly>(__first[__i]);
if (__c >= __base)
break;
__val = (__val << __log2_base) | __c;
}
__first += __i;
auto __significant_bits = (__i - __leading_zeroes) * __log2_base;
if (__base != 2)
// Compensate for a leading significant digit that didn't use all
// of its available bits.
__significant_bits -= __log2_base - __bit_width(__leading_c);
// __glibcxx_assert(__significant_bits >= 0);
return __significant_bits <= __gnu_cxx::__int_traits<_Tp>::__digits;
}
/// std::from_chars implementation for integers in any base.
/// If _DecOnly is true, then we may assume __base is at most 10.
template<bool _DecOnly, typename _Tp>
constexpr bool
__from_chars_alnum(const char*& __first, const char* __last, _Tp& __val,
int __base)
{
// __glibcxx_assert(_DecOnly ? __base <= 10 : __base <= 36);
const int __bits_per_digit = __bit_width(unsigned(__base & 0x3f));
int __unused_bits_lower_bound = __gnu_cxx::__int_traits<_Tp>::__digits;
for (; __first != __last; ++__first)
{
const unsigned char __c = __from_chars_alnum_to_val<_DecOnly>(*__first);
if (__c >= __base)
return true;
__unused_bits_lower_bound -= __bits_per_digit;
if (__unused_bits_lower_bound >= 0) [[__likely__]]
// We're definitely not going to overflow.
__val = __val * __base + __c;
else if (!__raise_and_add(__val, __base, __c)) [[__unlikely__]]
{
while (++__first != __last
&& __from_chars_alnum_to_val<_DecOnly>(*__first) < __base)
;
return false;
}
}
return true;
}
} // namespace __detail
/// std::from_chars for integral types.
template<typename _Tp,
enable_if_t<__or_<__is_standard_integer<_Tp>,
is_same<char, remove_cv_t<_Tp>>>::value, int> = 0>
_GLIBCXX23_CONSTEXPR from_chars_result
from_chars(const char* __first, const char* __last, _Tp& __value,
int __base = 10)
{
__glibcxx_assert(2 <= __base && __base <= 36);
from_chars_result __res{__first, {}};
int __sign = 1;
if _GLIBCXX17_CONSTEXPR (std::is_signed<_Tp>::value)
if (__first != __last && *__first == '-')
{
__sign = -1;
++__first;
}
using _Up = __detail::__unsigned_least_t<_Tp>;
_Up __val = 0;
const auto __start = __first;
bool __valid;
if ((__base & (__base - 1)) == 0)
{
if (__base <= 8)
__valid = __detail::__from_chars_pow2_base<true>(__first, __last, __val, __base);
else
__valid = __detail::__from_chars_pow2_base<false>(__first, __last, __val, __base);
}
else if (__base <= 10)
__valid = __detail::__from_chars_alnum<true>(__first, __last, __val, __base);
else
__valid = __detail::__from_chars_alnum<false>(__first, __last, __val, __base);
if (__builtin_expect(__first == __start, 0))
__res.ec = errc::invalid_argument;
else
{
__res.ptr = __first;
if (!__valid)
__res.ec = errc::result_out_of_range;
else
{
if _GLIBCXX17_CONSTEXPR (std::is_signed<_Tp>::value)
{
_Tp __tmp;
if (__builtin_mul_overflow(__val, __sign, &__tmp))
__res.ec = errc::result_out_of_range;
else
__value = __tmp;
}
else
{
if _GLIBCXX17_CONSTEXPR (__gnu_cxx::__int_traits<_Up>::__max
> __gnu_cxx::__int_traits<_Tp>::__max)
{
if (__val > __gnu_cxx::__int_traits<_Tp>::__max)
__res.ec = errc::result_out_of_range;
else
__value = __val;
}
else
__value = __val;
}
}
}
return __res;
}
/// floating-point format for primitive numerical conversion
enum class chars_format
{
scientific = 1, fixed = 2, hex = 4, general = fixed | scientific
};
[[nodiscard]]
constexpr chars_format
operator|(chars_format __lhs, chars_format __rhs) noexcept
{ return (chars_format)((unsigned)__lhs | (unsigned)__rhs); }
[[nodiscard]]
constexpr chars_format
operator&(chars_format __lhs, chars_format __rhs) noexcept
{ return (chars_format)((unsigned)__lhs & (unsigned)__rhs); }
[[nodiscard]]
constexpr chars_format
operator^(chars_format __lhs, chars_format __rhs) noexcept
{ return (chars_format)((unsigned)__lhs ^ (unsigned)__rhs); }
[[nodiscard]]
constexpr chars_format
operator~(chars_format __fmt) noexcept
{ return (chars_format)~(unsigned)__fmt; }
constexpr chars_format&
operator|=(chars_format& __lhs, chars_format __rhs) noexcept
{ return __lhs = __lhs | __rhs; }
constexpr chars_format&
operator&=(chars_format& __lhs, chars_format __rhs) noexcept
{ return __lhs = __lhs & __rhs; }
constexpr chars_format&
operator^=(chars_format& __lhs, chars_format __rhs) noexcept
{ return __lhs = __lhs ^ __rhs; }
#if defined __cpp_lib_to_chars || _GLIBCXX_HAVE_USELOCALE
from_chars_result
from_chars(const char* __first, const char* __last, float& __value,
chars_format __fmt = chars_format::general) noexcept;
from_chars_result
from_chars(const char* __first, const char* __last, double& __value,
chars_format __fmt = chars_format::general) noexcept;
from_chars_result
from_chars(const char* __first, const char* __last, long double& __value,
chars_format __fmt = chars_format::general) noexcept;
// Library routines for 16-bit extended floating point formats
// using float as interchange format.
from_chars_result
__from_chars_float16_t(const char* __first, const char* __last,
float& __value,
chars_format __fmt = chars_format::general) noexcept;
from_chars_result
__from_chars_bfloat16_t(const char* __first, const char* __last,
float& __value,
chars_format __fmt = chars_format::general) noexcept;
#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) \
&& defined(__cpp_lib_to_chars)
inline from_chars_result
from_chars(const char* __first, const char* __last, _Float16& __value,
chars_format __fmt = chars_format::general) noexcept
{
float __val;
from_chars_result __res
= __from_chars_float16_t(__first, __last, __val, __fmt);
if (__res.ec == errc{})
__value = _Float16(__val);
return __res;
}
#endif
#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
inline from_chars_result
from_chars(const char* __first, const char* __last, _Float32& __value,
chars_format __fmt = chars_format::general) noexcept
{
float __val;
from_chars_result __res = from_chars(__first, __last, __val, __fmt);
if (__res.ec == errc{})
__value = _Float32(__val);
return __res;
}
#endif
#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
inline from_chars_result
from_chars(const char* __first, const char* __last, _Float64& __value,
chars_format __fmt = chars_format::general) noexcept
{
double __val;
from_chars_result __res = from_chars(__first, __last, __val, __fmt);
if (__res.ec == errc{})
__value = _Float64(__val);
return __res;
}
#endif
#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128)
inline from_chars_result
from_chars(const char* __first, const char* __last, _Float128& __value,
chars_format __fmt = chars_format::general) noexcept
{
long double __val;
from_chars_result __res = from_chars(__first, __last, __val, __fmt);
if (__res.ec == errc{})
__value = _Float128(__val);
return __res;
}
#elif defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_HAVE_FLOAT128_MATH)
#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
__extension__ from_chars_result
from_chars(const char* __first, const char* __last, __ieee128& __value,
chars_format __fmt = chars_format::general) noexcept;
inline from_chars_result
from_chars(const char* __first, const char* __last, _Float128& __value,
chars_format __fmt = chars_format::general) noexcept
{
__extension__ __ieee128 __val;
from_chars_result __res = from_chars(__first, __last, __val, __fmt);
if (__res.ec == errc{})
__value = _Float128(__val);
return __res;
}
#else
from_chars_result
from_chars(const char* __first, const char* __last, _Float128& __value,
chars_format __fmt = chars_format::general) noexcept;
#endif
#endif
#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) \
&& defined(__cpp_lib_to_chars)
inline from_chars_result
from_chars(const char* __first, const char* __last,
__gnu_cxx::__bfloat16_t & __value,
chars_format __fmt = chars_format::general) noexcept
{
float __val;
from_chars_result __res
= __from_chars_bfloat16_t(__first, __last, __val, __fmt);
if (__res.ec == errc{})
__value = __gnu_cxx::__bfloat16_t(__val);
return __res;
}
#endif
#endif
#if defined __cpp_lib_to_chars
// Floating-point std::to_chars
// Overloads for float.
to_chars_result to_chars(char* __first, char* __last, float __value) noexcept;
to_chars_result to_chars(char* __first, char* __last, float __value,
chars_format __fmt) noexcept;
to_chars_result to_chars(char* __first, char* __last, float __value,
chars_format __fmt, int __precision) noexcept;
// Overloads for double.
to_chars_result to_chars(char* __first, char* __last, double __value) noexcept;
to_chars_result to_chars(char* __first, char* __last, double __value,
chars_format __fmt) noexcept;
to_chars_result to_chars(char* __first, char* __last, double __value,
chars_format __fmt, int __precision) noexcept;
// Overloads for long double.
to_chars_result to_chars(char* __first, char* __last, long double __value)
noexcept;
to_chars_result to_chars(char* __first, char* __last, long double __value,
chars_format __fmt) noexcept;
to_chars_result to_chars(char* __first, char* __last, long double __value,
chars_format __fmt, int __precision) noexcept;
// Library routines for 16-bit extended floating point formats
// using float as interchange format.
to_chars_result __to_chars_float16_t(char* __first, char* __last,
float __value,
chars_format __fmt) noexcept;
to_chars_result __to_chars_bfloat16_t(char* __first, char* __last,
float __value,
chars_format __fmt) noexcept;
#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
inline to_chars_result
to_chars(char* __first, char* __last, _Float16 __value) noexcept
{
return __to_chars_float16_t(__first, __last, float(__value),
chars_format{});
}
inline to_chars_result
to_chars(char* __first, char* __last, _Float16 __value,
chars_format __fmt) noexcept
{ return __to_chars_float16_t(__first, __last, float(__value), __fmt); }
inline to_chars_result
to_chars(char* __first, char* __last, _Float16 __value,
chars_format __fmt, int __precision) noexcept
{ return to_chars(__first, __last, float(__value), __fmt, __precision); }
#endif
#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
inline to_chars_result
to_chars(char* __first, char* __last, _Float32 __value) noexcept
{ return to_chars(__first, __last, float(__value)); }
inline to_chars_result
to_chars(char* __first, char* __last, _Float32 __value,
chars_format __fmt) noexcept
{ return to_chars(__first, __last, float(__value), __fmt); }
inline to_chars_result
to_chars(char* __first, char* __last, _Float32 __value,
chars_format __fmt, int __precision) noexcept
{ return to_chars(__first, __last, float(__value), __fmt, __precision); }
#endif
#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
inline to_chars_result
to_chars(char* __first, char* __last, _Float64 __value) noexcept
{ return to_chars(__first, __last, double(__value)); }
inline to_chars_result
to_chars(char* __first, char* __last, _Float64 __value,
chars_format __fmt) noexcept
{ return to_chars(__first, __last, double(__value), __fmt); }
inline to_chars_result
to_chars(char* __first, char* __last, _Float64 __value,
chars_format __fmt, int __precision) noexcept
{ return to_chars(__first, __last, double(__value), __fmt, __precision); }
#endif
#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128)
inline to_chars_result
to_chars(char* __first, char* __last, _Float128 __value) noexcept
{ return to_chars(__first, __last, static_cast<long double>(__value)); }
inline to_chars_result
to_chars(char* __first, char* __last, _Float128 __value,
chars_format __fmt) noexcept
{
return to_chars(__first, __last, static_cast<long double>(__value), __fmt);
}
inline to_chars_result
to_chars(char* __first, char* __last, _Float128 __value,
chars_format __fmt, int __precision) noexcept
{
return to_chars(__first, __last, static_cast<long double>(__value), __fmt,
__precision);
}
#elif defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_HAVE_FLOAT128_MATH)
#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
__extension__ to_chars_result
to_chars(char* __first, char* __last, __float128 __value) noexcept;
__extension__ to_chars_result
to_chars(char* __first, char* __last, __float128 __value,
chars_format __fmt) noexcept;
__extension__ to_chars_result
to_chars(char* __first, char* __last, __float128 __value,
chars_format __fmt, int __precision) noexcept;
inline to_chars_result
to_chars(char* __first, char* __last, _Float128 __value) noexcept
{
return __extension__ to_chars(__first, __last,
static_cast<__float128>(__value));
}
inline to_chars_result
to_chars(char* __first, char* __last, _Float128 __value,
chars_format __fmt) noexcept
{
return __extension__ to_chars(__first, __last,
static_cast<__float128>(__value), __fmt);
}
inline to_chars_result
to_chars(char* __first, char* __last, _Float128 __value,
chars_format __fmt, int __precision) noexcept
{
return __extension__ to_chars(__first, __last,
static_cast<__float128>(__value), __fmt,
__precision);
}
#else
to_chars_result to_chars(char* __first, char* __last, _Float128 __value)
noexcept;
to_chars_result to_chars(char* __first, char* __last, _Float128 __value,
chars_format __fmt) noexcept;
to_chars_result to_chars(char* __first, char* __last, _Float128 __value,
chars_format __fmt, int __precision) noexcept;
#endif
#endif
#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
inline to_chars_result
to_chars(char* __first, char* __last,
__gnu_cxx::__bfloat16_t __value) noexcept
{
return __to_chars_bfloat16_t(__first, __last, float(__value),
chars_format{});
}
inline to_chars_result
to_chars(char* __first, char* __last, __gnu_cxx::__bfloat16_t __value,
chars_format __fmt) noexcept
{ return __to_chars_bfloat16_t(__first, __last, float(__value), __fmt); }
inline to_chars_result
to_chars(char* __first, char* __last, __gnu_cxx::__bfloat16_t __value,
chars_format __fmt, int __precision) noexcept
{ return to_chars(__first, __last, float(__value), __fmt, __precision); }
#endif
#endif
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++14
#pragma GCC diagnostic pop
#endif // _GLIBCXX_CHARCONV