Reduce redundant code in stringconversion.h
This commit is contained in:
parent
3afed30760
commit
2e93882882
|
@ -526,125 +526,6 @@ void raiseAndAdd(IntegralType &result, BaseType base, CharType character)
|
|||
} // namespace Detail
|
||||
/// \endcond
|
||||
|
||||
/*!
|
||||
* \brief Converts the given \a string to an unsigned number assuming \a string uses the specified \a base.
|
||||
* \tparam IntegralType The data type used to store the converted value.
|
||||
* \tparam StringType The string type (should be an instantiation of the basic_string class template).
|
||||
* \throws A ConversionException will be thrown if the provided \a string is not a valid number.
|
||||
* \sa numberToString(), bufferToNumber()
|
||||
*/
|
||||
template <typename IntegralType, class StringType, typename BaseType = IntegralType,
|
||||
Traits::EnableIf<std::is_integral<IntegralType>, std::is_unsigned<IntegralType>, Traits::Not<std::is_scalar<std::decay_t<StringType>>>>
|
||||
* = nullptr>
|
||||
IntegralType stringToNumber(const StringType &string, BaseType base = 10)
|
||||
{
|
||||
IntegralType result = 0;
|
||||
for (const auto &c : string) {
|
||||
Detail::raiseAndAdd(result, base, c);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Converts the given \a string to a signed number assuming \a string uses the specified \a base.
|
||||
* \tparam IntegralType The data type used to store the converted value.
|
||||
* \tparam StringType The string type (should be an instantiation of the basic_string class template).
|
||||
* \throws A ConversionException will be thrown if the provided \a string is not a valid number.
|
||||
* \sa numberToString(), bufferToNumber()
|
||||
*/
|
||||
template <typename IntegralType, class StringType, typename BaseType = IntegralType,
|
||||
Traits::EnableIf<std::is_integral<IntegralType>, std::is_signed<IntegralType>, Traits::Not<std::is_scalar<std::decay_t<StringType>>>> * = nullptr>
|
||||
IntegralType stringToNumber(const StringType &string, BaseType base = 10)
|
||||
{
|
||||
auto i = string.begin();
|
||||
auto end = string.end();
|
||||
for (; i != end && *i == ' '; ++i)
|
||||
;
|
||||
if (i == end) {
|
||||
return 0;
|
||||
}
|
||||
const bool negative = (*i == '-');
|
||||
if (negative) {
|
||||
++i;
|
||||
}
|
||||
IntegralType result = 0;
|
||||
for (; i != end; ++i) {
|
||||
Detail::raiseAndAdd(result, base, *i);
|
||||
}
|
||||
return negative ? -result : result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Converts the given \a string to a number assuming \a string uses the specified \a base.
|
||||
* \tparam FloatingType The data type used to store the converted value.
|
||||
* \tparam StringType The string type (should be an instantiation of the basic_string class template).
|
||||
* \throws A ConversionException will be thrown if the provided \a string is not a valid number.
|
||||
* \remarks This function is using std::basic_stringstream interanlly and hence also has its limitations (eg. regarding
|
||||
* \a base and types).
|
||||
* \sa numberToString(), bufferToNumber()
|
||||
*/
|
||||
template <typename FloatingType, class StringType,
|
||||
Traits::EnableIf<std::is_floating_point<FloatingType>, Traits::Not<std::is_scalar<std::decay_t<StringType>>>> * = nullptr>
|
||||
FloatingType stringToNumber(const StringType &string, int base = 10)
|
||||
{
|
||||
std::basic_stringstream<typename StringType::value_type> ss;
|
||||
ss << std::setbase(base) << string;
|
||||
FloatingType result;
|
||||
if ((ss >> result) && ss.eof()) {
|
||||
return result;
|
||||
}
|
||||
std::string errorMsg;
|
||||
errorMsg.reserve(48 + string.size());
|
||||
errorMsg += "The string \"";
|
||||
errorMsg += string;
|
||||
errorMsg += "\" is no valid floating point number.";
|
||||
throw ConversionException(errorMsg);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Converts the given null-terminated \a string to an unsigned numeric value using the specified \a base.
|
||||
* \tparam IntegralType The data type used to store the converted value.
|
||||
* \tparam CharType The character type.
|
||||
* \throws A ConversionException will be thrown if the provided \a string is not a valid number.
|
||||
* \sa numberToString(), bufferToNumber()
|
||||
*/
|
||||
template <typename IntegralType, typename CharType, typename BaseType = IntegralType,
|
||||
Traits::EnableIf<std::is_integral<IntegralType>, std::is_unsigned<IntegralType>> * = nullptr>
|
||||
IntegralType stringToNumber(const CharType *string, BaseType base = 10)
|
||||
{
|
||||
IntegralType result = 0;
|
||||
for (; *string; ++string) {
|
||||
Detail::raiseAndAdd(result, base, *string);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Converts the given null-terminated \a string to a number assuming \a string uses the specified \a base.
|
||||
* \tparam FloatingType The data type used to store the converted value.
|
||||
* \tparam CharType The character type.
|
||||
* \throws A ConversionException will be thrown if the provided \a string is not a valid number.
|
||||
* \remarks This function is using std::basic_stringstream interanlly and hence also has its limitations (eg. regarding
|
||||
* \a base and types).
|
||||
* \sa numberToString(), bufferToNumber()
|
||||
*/
|
||||
template <typename FloatingType, class CharType, Traits::EnableIf<std::is_floating_point<FloatingType>> * = nullptr>
|
||||
FloatingType stringToNumber(const CharType *string, int base = 10)
|
||||
{
|
||||
std::basic_stringstream<CharType> ss;
|
||||
ss << std::setbase(base) << string;
|
||||
FloatingType result;
|
||||
if ((ss >> result) && ss.eof()) {
|
||||
return result;
|
||||
}
|
||||
std::string errorMsg;
|
||||
errorMsg.reserve(42 + std::char_traits<CharType>::length(string));
|
||||
errorMsg += "The string \"";
|
||||
errorMsg += string;
|
||||
errorMsg += "\" is no valid floating number.";
|
||||
throw ConversionException(errorMsg);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Converts the given \a string of \a size characters to an unsigned numeric value using the specified \a base.
|
||||
* \tparam IntegralType The data type used to store the converted value.
|
||||
|
@ -663,36 +544,6 @@ IntegralType bufferToNumber(const CharType *string, std::size_t size, BaseType b
|
|||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Converts the given null-terminated \a string to a signed numeric value using the specified \a base.
|
||||
* \tparam IntegralType The data type used to store the converted value.
|
||||
* \tparam CharType The character type.
|
||||
* \throws A ConversionException will be thrown if the provided \a string is not a valid number.
|
||||
* \sa numberToString(), bufferToNumber()
|
||||
*/
|
||||
template <typename IntegralType, typename CharType, typename BaseType = IntegralType,
|
||||
Traits::EnableIf<std::is_integral<IntegralType>, std::is_signed<IntegralType>> * = nullptr>
|
||||
IntegralType stringToNumber(const CharType *string, IntegralType base = 10)
|
||||
{
|
||||
if (!*string) {
|
||||
return 0;
|
||||
}
|
||||
for (; *string && *string == ' '; ++string)
|
||||
;
|
||||
if (!*string) {
|
||||
return 0;
|
||||
}
|
||||
const bool negative = (*string == '-');
|
||||
if (negative) {
|
||||
++string;
|
||||
}
|
||||
IntegralType result = 0;
|
||||
for (; *string; ++string) {
|
||||
Detail::raiseAndAdd(result, base, *string);
|
||||
}
|
||||
return negative ? -result : result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Converts the given \a string of \a size characters to a signed numeric value using the specified \a base.
|
||||
* \tparam IntegralType The data type used to store the converted value.
|
||||
|
@ -724,6 +575,128 @@ IntegralType bufferToNumber(const CharType *string, std::size_t size, BaseType b
|
|||
return negative ? -result : result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Converts the given \a string to an unsigned/signed number assuming \a string uses the specified \a base.
|
||||
* \tparam IntegralType The data type used to store the converted value.
|
||||
* \tparam StringType The string type (should be an instantiation of the basic_string class template).
|
||||
* \throws A ConversionException will be thrown if the provided \a string is not a valid number.
|
||||
* \sa numberToString(), bufferToNumber()
|
||||
*/
|
||||
template <typename IntegralType, class StringType, typename BaseType = IntegralType,
|
||||
Traits::EnableIf<std::is_integral<IntegralType>, Traits::Not<std::is_scalar<std::decay_t<StringType>>>> * = nullptr>
|
||||
IntegralType stringToNumber(const StringType &string, BaseType base = 10)
|
||||
{
|
||||
return bufferToNumber<IntegralType, typename StringType::value_type, BaseType>(string.data(), string.size(), base);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Converts the given \a stringView to a number assuming \a stringView uses the specified \a base.
|
||||
* \tparam FloatingType The data type used to store the converted value.
|
||||
* \tparam StringViewType The string view type (must be an instantiation of the basic_string_view class template).
|
||||
* \throws A ConversionException will be thrown if the provided \a string is not a valid number.
|
||||
* \remarks This function is using std::basic_stringstream interanlly and hence also has its limitations (eg. regarding
|
||||
* \a base and types).
|
||||
* \sa numberToString(), bufferToNumber()
|
||||
*/
|
||||
template <typename FloatingType, class StringViewType,
|
||||
Traits::EnableIf<std::is_floating_point<FloatingType>, Traits::IsSpecializationOf<StringViewType, std::basic_string_view>> * = nullptr>
|
||||
FloatingType stringToNumber(StringViewType stringView, int base = 10)
|
||||
{
|
||||
std::basic_stringstream<typename StringViewType::value_type> ss;
|
||||
ss << std::setbase(base) << stringView;
|
||||
FloatingType result;
|
||||
if ((ss >> result) && ss.eof()) {
|
||||
return result;
|
||||
}
|
||||
std::string errorMsg;
|
||||
errorMsg.reserve(48 + stringView.size());
|
||||
errorMsg += "The string \"";
|
||||
errorMsg += stringView;
|
||||
errorMsg += "\" is no valid floating point number.";
|
||||
throw ConversionException(errorMsg);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Converts the given \a string to a number assuming \a string uses the specified \a base.
|
||||
* \tparam FloatingType The data type used to store the converted value.
|
||||
* \tparam StringType The string type (should be an instantiation of the basic_string class template).
|
||||
* \throws A ConversionException will be thrown if the provided \a string is not a valid number.
|
||||
* \remarks This function is using std::basic_stringstream interanlly and hence also has its limitations (eg. regarding
|
||||
* \a base and types).
|
||||
* \sa numberToString(), bufferToNumber()
|
||||
*/
|
||||
template <typename FloatingType, class StringType,
|
||||
Traits::EnableIf<std::is_floating_point<FloatingType>, Traits::Not<std::is_scalar<std::decay_t<StringType>>>,
|
||||
Traits::Not<Traits::IsSpecializationOf<StringType, std::basic_string_view>>> * = nullptr>
|
||||
FloatingType stringToNumber(const StringType &string, int base = 10)
|
||||
{
|
||||
using StringViewType = std::basic_string_view<typename StringType::value_type>;
|
||||
return stringToNumber<FloatingType, StringViewType>(StringViewType(string.data(), string.size()), base);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Converts the given null-terminated \a string to an unsigned numeric value using the specified \a base.
|
||||
* \tparam IntegralType The data type used to store the converted value.
|
||||
* \tparam CharType The character type.
|
||||
* \throws A ConversionException will be thrown if the provided \a string is not a valid number.
|
||||
* \sa numberToString(), bufferToNumber()
|
||||
*/
|
||||
template <typename IntegralType, typename CharType, typename BaseType = IntegralType,
|
||||
Traits::EnableIf<std::is_integral<IntegralType>, std::is_unsigned<IntegralType>> * = nullptr>
|
||||
IntegralType stringToNumber(const CharType *string, BaseType base = 10)
|
||||
{
|
||||
IntegralType result = 0;
|
||||
for (; *string; ++string) {
|
||||
Detail::raiseAndAdd(result, base, *string);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Converts the given null-terminated \a string to a number assuming \a string uses the specified \a base.
|
||||
* \tparam FloatingType The data type used to store the converted value.
|
||||
* \tparam CharType The character type.
|
||||
* \throws A ConversionException will be thrown if the provided \a string is not a valid number.
|
||||
* \remarks This function is using std::basic_stringstream interanlly and hence also has its limitations (eg. regarding
|
||||
* \a base and types).
|
||||
* \sa numberToString(), bufferToNumber()
|
||||
*/
|
||||
template <typename FloatingType, class CharType, Traits::EnableIf<std::is_floating_point<FloatingType>> * = nullptr>
|
||||
FloatingType stringToNumber(const CharType *string, int base = 10)
|
||||
{
|
||||
return stringToNumber<FloatingType, std::basic_string_view<CharType>>(string, base);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Converts the given null-terminated \a string to a signed numeric value using the specified \a base.
|
||||
* \tparam IntegralType The data type used to store the converted value.
|
||||
* \tparam CharType The character type.
|
||||
* \throws A ConversionException will be thrown if the provided \a string is not a valid number.
|
||||
* \sa numberToString(), bufferToNumber()
|
||||
*/
|
||||
template <typename IntegralType, typename CharType, typename BaseType = IntegralType,
|
||||
Traits::EnableIf<std::is_integral<IntegralType>, std::is_signed<IntegralType>> * = nullptr>
|
||||
IntegralType stringToNumber(const CharType *string, IntegralType base = 10)
|
||||
{
|
||||
if (!*string) {
|
||||
return 0;
|
||||
}
|
||||
for (; *string && *string == ' '; ++string)
|
||||
;
|
||||
if (!*string) {
|
||||
return 0;
|
||||
}
|
||||
const bool negative = (*string == '-');
|
||||
if (negative) {
|
||||
++string;
|
||||
}
|
||||
IntegralType result = 0;
|
||||
for (; *string; ++string) {
|
||||
Detail::raiseAndAdd(result, base, *string);
|
||||
}
|
||||
return negative ? -result : result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Interprets the given \a integer at the specified position as std::string using the specified byte order.
|
||||
*
|
||||
|
|
|
@ -292,6 +292,11 @@ void ConversionTests::testStringConversions()
|
|||
CPPUNIT_ASSERT_EQUAL_MESSAGE("negative limit", -2147483647, stringToNumber<std::int32_t>("-2147483647", 10));
|
||||
#endif
|
||||
|
||||
// stringToNumber() / numberToString() with floating point numbers
|
||||
CPPUNIT_ASSERT_EQUAL(1.5f, stringToNumber<float>(numberToString(1.5f)));
|
||||
CPPUNIT_ASSERT_EQUAL(1.5, stringToNumber<double>(numberToString(1.5)));
|
||||
CPPUNIT_ASSERT_EQUAL(-10.25, stringToNumber<double>("-10.25"));
|
||||
|
||||
// interpretIntegerAsString()
|
||||
CPPUNIT_ASSERT_EQUAL("TEST"s, interpretIntegerAsString<std::uint32_t>(0x54455354));
|
||||
|
||||
|
|
Loading…
Reference in New Issue