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
|
} // namespace Detail
|
||||||
/// \endcond
|
/// \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.
|
* \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.
|
* \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;
|
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.
|
* \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.
|
* \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;
|
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.
|
* \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));
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("negative limit", -2147483647, stringToNumber<std::int32_t>("-2147483647", 10));
|
||||||
#endif
|
#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()
|
// interpretIntegerAsString()
|
||||||
CPPUNIT_ASSERT_EQUAL("TEST"s, interpretIntegerAsString<std::uint32_t>(0x54455354));
|
CPPUNIT_ASSERT_EQUAL("TEST"s, interpretIntegerAsString<std::uint32_t>(0x54455354));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue