Boost logo

Boost :

From: g.peterhoff_at_[hidden]
Date: 2024-01-31 16:37:25


Hello Matt,
Sorry for submitting a bug report this way. (Having problems with my GitHub account at the moment).

Code: Attachment (gcc 13.2 -std=gnu++23 -O3 -Wall -fanalyzer)

Errors (normal)
- Missing sign
- Hex exponent is wrong
- Hex is completely wrong
- Accuracy is not correct
- Error code deviates from the standard
...
The backup functions via (quadmath)snprintf do not work.

Errors (critical)
- If the buffer is too small (e.g. set the array size to 3) there are a lot of buffer overflows. Especially with value ±nan/±inf.

The functions should therefore always be structured in the same way:
Auxiliary function
inline constexpr bool is_valid_range(const char*const first, const char*const last) noexcept
{
        return (first!=nullptr && last!=nullptr) ? first < last : false;
}

Pseudocode
to_chars(...) // FP
{
        to_chars_result
                result{last, std::errc::value_too_large};

        if (is_valid_range(first, last)) [[likely]]
        {
                const size_t
                        size = size_t(last - first);

                if (inf or nan) [[unlikely]]
                {
                        if (size is large enough)
                        {
                                copy the string values into the range
                                result = ...;

                                Here you could also use #define to specify whether the string values are compatible with the standard or not.
                                "±inf", "±nan"
                                or https://develop.charconv.cpp.al/#to_chars_usage_notes_for_to_chars_for_floating_point_types
                        }
                }
                else
                {
                        convert, detail::implemantation(first, size, ...)
                        result = ...;
                }
        }
        return result;
}

to_chars(...) // INT
{
        to_chars_result
                result{last, std::errc::value_too_large};

        if (is_valid_range(first, last)) [[likely]]
        {
                const size_t
                        size = size_t(last - first);

                convert, detail::implemantation(first, size, ...)
                result = ...;
        }
        return result;
}

This can be achieved with templates and typetraits:
FP
boost::is_floating_point still does not contain any C++23 types.

template <typename Type>
BOOST_NOINLINE typename std::enable_if<std::is_floating_point<Type>::value, to_chars_result>::type
to_chars(char*const first, char*const last, const Type value, const chars_format format, const int precision) noexcept;

template <type name Type>
BOOST_NOINLINE typename std::enable_if<std::is_floating_point<Type>::value, to_chars_result>::type
to_chars(char*const first, char*const last, const Type value, const chars_format format) noexcept;

INT
(boost)is_integer is unfortunately still missing.

template <type name Type>
BOOST_NOINLINE typename std::enable_if<boost::is_integer<Type>::value, to_chars_result>::type
to_chars(char*const first, char*const last, const Type value, const int base = 10) noexcept;

regards
Gero



Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk