string to int: Allow specifying string size
This commit is contained in:
parent
045c713cf5
commit
28f37bbbcd
|
@ -121,8 +121,8 @@ set(META_APP_AUTHOR "Martchus")
|
||||||
set(META_APP_URL "https://github.com/${META_APP_AUTHOR}/${META_PROJECT_NAME}")
|
set(META_APP_URL "https://github.com/${META_APP_AUTHOR}/${META_PROJECT_NAME}")
|
||||||
set(META_APP_DESCRIPTION "Common C++ classes and routines used by my applications such as argument parser, IO and conversion utilities")
|
set(META_APP_DESCRIPTION "Common C++ classes and routines used by my applications such as argument parser, IO and conversion utilities")
|
||||||
set(META_VERSION_MAJOR 4)
|
set(META_VERSION_MAJOR 4)
|
||||||
set(META_VERSION_MINOR 8)
|
set(META_VERSION_MINOR 9)
|
||||||
set(META_VERSION_PATCH 1)
|
set(META_VERSION_PATCH 0)
|
||||||
|
|
||||||
# find required 3rd party libraries
|
# find required 3rd party libraries
|
||||||
include(3rdParty)
|
include(3rdParty)
|
||||||
|
|
|
@ -301,7 +301,7 @@ StringType numberToString(IntegralType number, typename StringType::value_type b
|
||||||
* \tparam StringType The string type (should be an instantiation of the basic_string class template).
|
* \tparam StringType The string type (should be an instantiation of the basic_string class template).
|
||||||
* \remarks This function is using std::basic_stringstream interanlly and hence also has its limitations (eg. regarding
|
* \remarks This function is using std::basic_stringstream interanlly and hence also has its limitations (eg. regarding
|
||||||
* \a base and types).
|
* \a base and types).
|
||||||
* \sa stringToNumber()
|
* \sa stringToNumber(), bufferToNumber()
|
||||||
*/
|
*/
|
||||||
template <typename FloatingType, class StringType = std::string, Traits::EnableIf<std::is_floating_point<FloatingType>>...>
|
template <typename FloatingType, class StringType = std::string, Traits::EnableIf<std::is_floating_point<FloatingType>>...>
|
||||||
StringType numberToString(FloatingType number, typename StringType::value_type base = 10)
|
StringType numberToString(FloatingType number, typename StringType::value_type base = 10)
|
||||||
|
@ -334,11 +334,11 @@ template <typename CharType> CharType charToDigit(CharType character, CharType b
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Converts the given \a string to a number assuming \a string uses the specified \a base.
|
* \brief Converts the given \a string to an unsigned number assuming \a string uses the specified \a base.
|
||||||
* \tparam NumberType The data type used to store the converted value.
|
* \tparam NumberType The data type used to store the converted value.
|
||||||
* \tparam StringType The string type (should be an instantiation of the basic_string class template).
|
* \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.
|
* \throws A ConversionException will be thrown if the provided \a string is not a valid number.
|
||||||
* \sa numberToString()
|
* \sa numberToString(), bufferToNumber()
|
||||||
*/
|
*/
|
||||||
template <typename IntegralType, class StringType, Traits::EnableIf<std::is_integral<IntegralType>, Traits::Not<std::is_signed<IntegralType>>>...>
|
template <typename IntegralType, class StringType, Traits::EnableIf<std::is_integral<IntegralType>, Traits::Not<std::is_signed<IntegralType>>>...>
|
||||||
IntegralType stringToNumber(const StringType &string, typename StringType::value_type base = 10)
|
IntegralType stringToNumber(const StringType &string, typename StringType::value_type base = 10)
|
||||||
|
@ -355,11 +355,11 @@ IntegralType stringToNumber(const StringType &string, typename StringType::value
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Converts the given \a string to a number assuming \a string uses the specified \a base.
|
* \brief Converts the given \a string to a signed number assuming \a string uses the specified \a base.
|
||||||
* \tparam NumberType The data type used to store the converted value.
|
* \tparam NumberType The data type used to store the converted value.
|
||||||
* \tparam StringType The string type (should be an instantiation of the basic_string class template).
|
* \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.
|
* \throws A ConversionException will be thrown if the provided \a string is not a valid number.
|
||||||
* \sa numberToString()
|
* \sa numberToString(), bufferToNumber()
|
||||||
*/
|
*/
|
||||||
template <typename IntegralType, class StringType, Traits::EnableIf<std::is_integral<IntegralType>, std::is_signed<IntegralType>>...>
|
template <typename IntegralType, class StringType, Traits::EnableIf<std::is_integral<IntegralType>, std::is_signed<IntegralType>>...>
|
||||||
IntegralType stringToNumber(const StringType &string, typename StringType::value_type base = 10)
|
IntegralType stringToNumber(const StringType &string, typename StringType::value_type base = 10)
|
||||||
|
@ -393,7 +393,7 @@ IntegralType stringToNumber(const StringType &string, typename StringType::value
|
||||||
* \throws A ConversionException will be thrown if the provided \a string is not a valid number.
|
* \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
|
* \remarks This function is using std::basic_stringstream interanlly and hence also has its limitations (eg. regarding
|
||||||
* \a base and types).
|
* \a base and types).
|
||||||
* \sa numberToString()
|
* \sa numberToString(), bufferToNumber()
|
||||||
*/
|
*/
|
||||||
template <typename FloatingType, class StringType, Traits::EnableIf<std::is_floating_point<FloatingType>>...>
|
template <typename FloatingType, class StringType, Traits::EnableIf<std::is_floating_point<FloatingType>>...>
|
||||||
FloatingType stringToNumber(const StringType &string, typename StringType::value_type base = 10)
|
FloatingType stringToNumber(const StringType &string, typename StringType::value_type base = 10)
|
||||||
|
@ -409,11 +409,11 @@ FloatingType stringToNumber(const StringType &string, typename StringType::value
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Converts the given null-terminated \a string to a numeric value using the specified \a base.
|
* \brief Converts the given null-terminated \a string to an unsigned numeric value using the specified \a base.
|
||||||
* \tparam NumberType The data type used to store the converted value.
|
* \tparam NumberType The data type used to store the converted value.
|
||||||
* \tparam StringType The string type (should be an instantiation of the basic_string class template).
|
* \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.
|
* \throws A ConversionException will be thrown if the provided \a string is not a valid number.
|
||||||
* \sa numberToString()
|
* \sa numberToString(), bufferToNumber()
|
||||||
*/
|
*/
|
||||||
template <typename IntegralType, class CharType, Traits::EnableIf<std::is_integral<IntegralType>, Traits::Not<std::is_signed<IntegralType>>>...>
|
template <typename IntegralType, class CharType, Traits::EnableIf<std::is_integral<IntegralType>, Traits::Not<std::is_signed<IntegralType>>>...>
|
||||||
IntegralType stringToNumber(const CharType *string, unsigned char base = 10)
|
IntegralType stringToNumber(const CharType *string, unsigned char base = 10)
|
||||||
|
@ -430,11 +430,32 @@ IntegralType stringToNumber(const CharType *string, unsigned char base = 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Converts the given null-terminated \a string to a 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 NumberType The data type used to store the converted value.
|
* \tparam NumberType The data type used to store the converted value.
|
||||||
* \tparam StringType The string type (should be an instantiation of the basic_string class template).
|
* \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.
|
* \throws A ConversionException will be thrown if the provided \a string is not a valid number.
|
||||||
* \sa numberToString()
|
* \sa numberToString(), stringToNumber()
|
||||||
|
*/
|
||||||
|
template <typename IntegralType, class CharType, Traits::EnableIf<std::is_integral<IntegralType>, Traits::Not<std::is_signed<IntegralType>>>...>
|
||||||
|
IntegralType bufferToNumber(const CharType *string, std::size_t size, unsigned char base = 10)
|
||||||
|
{
|
||||||
|
IntegralType result = 0;
|
||||||
|
for (const CharType *end = string + size; string != end; ++string) {
|
||||||
|
if (*string == ' ') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result *= base;
|
||||||
|
result += charToDigit<CharType>(*string, base);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Converts the given null-terminated \a string to a signed numeric value using the specified \a base.
|
||||||
|
* \tparam NumberType 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 CharType, Traits::EnableIf<std::is_integral<IntegralType>, std::is_signed<IntegralType>>...>
|
template <typename IntegralType, class CharType, Traits::EnableIf<std::is_integral<IntegralType>, std::is_signed<IntegralType>>...>
|
||||||
IntegralType stringToNumber(const CharType *string, unsigned char base = 10)
|
IntegralType stringToNumber(const CharType *string, unsigned char base = 10)
|
||||||
|
@ -462,6 +483,40 @@ IntegralType stringToNumber(const CharType *string, unsigned char base = 10)
|
||||||
return negative ? -result : result;
|
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 NumberType 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(), stringToNumber()
|
||||||
|
*/
|
||||||
|
template <typename IntegralType, class CharType, Traits::EnableIf<std::is_integral<IntegralType>, std::is_signed<IntegralType>>...>
|
||||||
|
IntegralType bufferToNumber(const CharType *string, std::size_t size, unsigned char base = 10)
|
||||||
|
{
|
||||||
|
if (!size) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const CharType *end = string + size;
|
||||||
|
for (; string != end && *string == ' '; ++string)
|
||||||
|
;
|
||||||
|
if (string == end) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const bool negative = (*string == '-');
|
||||||
|
if (negative) {
|
||||||
|
++string;
|
||||||
|
}
|
||||||
|
IntegralType result = 0;
|
||||||
|
for (; string != end; ++string) {
|
||||||
|
if (*string == ' ') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result *= base;
|
||||||
|
result += charToDigit<CharType>(*string, base);
|
||||||
|
}
|
||||||
|
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.
|
||||||
*
|
*
|
||||||
|
|
|
@ -228,24 +228,27 @@ void ConversionTests::testStringEncodingConversions()
|
||||||
void ConversionTests::testStringConversions()
|
void ConversionTests::testStringConversions()
|
||||||
{
|
{
|
||||||
// stringToNumber() / numberToString() with zero and random numbers
|
// stringToNumber() / numberToString() with zero and random numbers
|
||||||
CPPUNIT_ASSERT_EQUAL(string("0"), numberToString<unsigned int>(0));
|
CPPUNIT_ASSERT_EQUAL("0"s, numberToString<unsigned int>(0));
|
||||||
CPPUNIT_ASSERT_EQUAL(string("0"), numberToString<signed int>(0));
|
CPPUNIT_ASSERT_EQUAL("0"s, numberToString<signed int>(0));
|
||||||
uniform_int_distribution<int64> randomDistSigned(numeric_limits<int64>::min());
|
uniform_int_distribution<int64> randomDistSigned(numeric_limits<int64>::min());
|
||||||
uniform_int_distribution<uint64> randomDistUnsigned(0);
|
uniform_int_distribution<uint64> randomDistUnsigned(0);
|
||||||
|
const string stringMsg("string"), wideStringMsg("wide string"), bufferMsg("buffer");
|
||||||
for (byte b = 1; b < 100; ++b) {
|
for (byte b = 1; b < 100; ++b) {
|
||||||
auto signedRandom = randomDistSigned(m_randomEngine);
|
auto signedRandom = randomDistSigned(m_randomEngine);
|
||||||
auto unsignedRandom = randomDistUnsigned(m_randomEngine);
|
auto unsignedRandom = randomDistUnsigned(m_randomEngine);
|
||||||
for (const auto base : initializer_list<byte>{ 2, 8, 10, 16 }) {
|
for (const auto base : initializer_list<byte>{ 2, 8, 10, 16 }) {
|
||||||
auto resultString = stringToNumber<uint64, string>(numberToString<uint64, string>(unsignedRandom, base), base);
|
const auto asString = numberToString<uint64, string>(unsignedRandom, static_cast<string::value_type>(base));
|
||||||
auto resultWideString = stringToNumber<uint64, wstring>(numberToString<uint64, wstring>(unsignedRandom, base), base);
|
const auto asWideString = numberToString<uint64, wstring>(unsignedRandom, base);
|
||||||
CPPUNIT_ASSERT_EQUAL(unsignedRandom, resultString);
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(stringMsg, unsignedRandom, stringToNumber<uint64>(asString, static_cast<string::value_type>(base)));
|
||||||
CPPUNIT_ASSERT_EQUAL(unsignedRandom, resultWideString);
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(wideStringMsg, unsignedRandom, stringToNumber<uint64>(asWideString, base));
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(bufferMsg, unsignedRandom, bufferToNumber<uint64>(asString.data(), asString.size(), base));
|
||||||
}
|
}
|
||||||
for (const auto base : initializer_list<byte>{ 10 }) {
|
for (const auto base : initializer_list<byte>{ 10 }) {
|
||||||
auto resultString = stringToNumber<int64, string>(numberToString<int64, string>(signedRandom, base), base);
|
const auto asString = numberToString<int64, string>(signedRandom, static_cast<string::value_type>(base));
|
||||||
auto resultWideString = stringToNumber<int64, wstring>(numberToString<int64, wstring>(signedRandom, base), base);
|
const auto asWideString = numberToString<int64, wstring>(signedRandom, base);
|
||||||
CPPUNIT_ASSERT_EQUAL(signedRandom, resultString);
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(stringMsg, signedRandom, stringToNumber<int64>(asString, static_cast<string::value_type>(base)));
|
||||||
CPPUNIT_ASSERT_EQUAL(signedRandom, resultWideString);
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(wideStringMsg, signedRandom, stringToNumber<int64>(asWideString, base));
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(bufferMsg, signedRandom, bufferToNumber<int64>(asString.data(), asString.size(), base));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,10 +257,12 @@ void ConversionTests::testStringConversions()
|
||||||
CPPUNIT_ASSERT_EQUAL(1, stringToNumber<int32>(L"01"s));
|
CPPUNIT_ASSERT_EQUAL(1, stringToNumber<int32>(L"01"s));
|
||||||
CPPUNIT_ASSERT_EQUAL(1, stringToNumber<int32>(u"01"s));
|
CPPUNIT_ASSERT_EQUAL(1, stringToNumber<int32>(u"01"s));
|
||||||
CPPUNIT_ASSERT_EQUAL(-23, stringToNumber<int32>(" - 023"s));
|
CPPUNIT_ASSERT_EQUAL(-23, stringToNumber<int32>(" - 023"s));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(-23, bufferToNumber<int32>(" - 023", 6));
|
||||||
CPPUNIT_ASSERT_EQUAL(1u, stringToNumber<uint32>("01"));
|
CPPUNIT_ASSERT_EQUAL(1u, stringToNumber<uint32>("01"));
|
||||||
CPPUNIT_ASSERT_EQUAL(1u, stringToNumber<uint32>(L"01"s));
|
CPPUNIT_ASSERT_EQUAL(1u, stringToNumber<uint32>(L"01"s));
|
||||||
CPPUNIT_ASSERT_EQUAL(1u, stringToNumber<uint32>(u"01"s));
|
CPPUNIT_ASSERT_EQUAL(1u, stringToNumber<uint32>(u"01"s));
|
||||||
CPPUNIT_ASSERT_EQUAL(23u, stringToNumber<uint32>(" 023"s));
|
CPPUNIT_ASSERT_EQUAL(23u, stringToNumber<uint32>(" 023"s));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(23u, bufferToNumber<uint32>(" 023", 5));
|
||||||
|
|
||||||
// interpretIntegerAsString()
|
// interpretIntegerAsString()
|
||||||
CPPUNIT_ASSERT_EQUAL("TEST"s, interpretIntegerAsString<uint32>(0x54455354));
|
CPPUNIT_ASSERT_EQUAL("TEST"s, interpretIntegerAsString<uint32>(0x54455354));
|
||||||
|
|
Loading…
Reference in New Issue