Add function template simgear::strutils::readNonNegativeInt()
This function is similar to simgear::strutils::to_int(), except it is:
- generic: the return type, selected with the first template
parameter, can be an arbitrary integral type. This type also defines
the set of accepted input strings ("values").
- stricter regarding the input: it must be non-empty and contain only
valid digits for the specified base (second template parameter). If
the input doesn't conform to these constraints or is too large to
fit into the specified type, an exception with a suitable error
message is raised.
- faster (12 to 17 times as fast as simgear::strutils::to_int() on my
system, depending on compilation flags): this is probably a
consequence of not using std::stringstream to do the conversion.
The function template is only instantiated for <int, 10> and
<unsigned int, 10> in order to be sure not to waste memory (see comments
in strutils.cxx). If you need it for other combinations of type and
base, just enable them by adjusting the corresponding '#if 0 / #endif'
pairs in strutils.cxx and strutils_test.cxx.
This commit is contained in:
@@ -22,12 +22,13 @@
|
||||
|
||||
#include <simgear_config.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <string.h> // strerror_r() and strerror_s()
|
||||
#include <errno.h>
|
||||
#include <type_traits>
|
||||
#include <cstring> // strerror_r() and strerror_s()
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
|
||||
#if defined(HAVE_CPP11_CODECVT)
|
||||
#include <codecvt> // new in C++11
|
||||
@@ -374,6 +375,173 @@ namespace simgear {
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
int digitValue<10>(char c)
|
||||
{
|
||||
if ('0' <= c && c <= '9') {
|
||||
return static_cast<int>(c - '0');
|
||||
} else {
|
||||
throw sg_range_exception("invalid as a decimal digit: '" +
|
||||
std::string(1, c) + "'");
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
int digitValue<16>(char c)
|
||||
{
|
||||
if ('0' <= c && c <= '9') {
|
||||
return static_cast<int>(c - '0');
|
||||
} else if ('a' <= c && c <= 'f') {
|
||||
return 10 + static_cast<int>(c - 'a');
|
||||
} else if ('A' <= c && c <= 'F') {
|
||||
return 10 + static_cast<int>(c - 'A');
|
||||
} else {
|
||||
throw sg_range_exception("invalid as an hexadecimal digit: '" +
|
||||
std::string(1, c) + "'");
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string numerationBaseAdjective<10>()
|
||||
{ return std::string("decimal"); }
|
||||
|
||||
template<>
|
||||
std::string numerationBaseAdjective<16>()
|
||||
{ return std::string("hexadecimal"); }
|
||||
|
||||
template<
|
||||
class T,
|
||||
int BASE = 10,
|
||||
typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
|
||||
T readNonNegativeInt(const std::string& s)
|
||||
{
|
||||
static_assert(0 < BASE,
|
||||
"template value BASE must be a positive integer");
|
||||
static_assert(BASE <= std::numeric_limits<T>::max(),
|
||||
"template type T too small: it cannot represent BASE");
|
||||
T res(0);
|
||||
T multiplier(1);
|
||||
T increment;
|
||||
int digit;
|
||||
|
||||
if (s.empty()) {
|
||||
throw sg_format_exception("expected a non-empty string", s);
|
||||
}
|
||||
|
||||
for (auto it = s.crbegin(); it != s.crend(); it++) {
|
||||
if (it != s.crbegin()) {
|
||||
// Check if 'multiplier *= BASE' is going to overflow. This is
|
||||
// reliable because 'multiplier' and 'BASE' are positive.
|
||||
if (multiplier > std::numeric_limits<T>::max() / BASE) {
|
||||
// If all remaining digits are '0', it doesn't matter that
|
||||
// the multiplier overflows.
|
||||
if (std::all_of(it, s.crend(),
|
||||
[](char c){ return (c == '0'); })) {
|
||||
return res;
|
||||
} else {
|
||||
throw sg_range_exception(
|
||||
"doesn't fit in the specified type: '" + s + "'");
|
||||
}
|
||||
}
|
||||
multiplier *= BASE;
|
||||
}
|
||||
|
||||
try {
|
||||
digit = digitValue<BASE>(*it);
|
||||
} catch (const sg_range_exception&) {
|
||||
throw sg_format_exception(
|
||||
"expected a string containing " +
|
||||
numerationBaseAdjective<BASE>() +
|
||||
" digits only, but got '" + s + "'", s);
|
||||
}
|
||||
|
||||
// Reliable because 'multiplier' is positive
|
||||
if (digit > 0 &&
|
||||
multiplier > std::numeric_limits<T>::max() / digit) {
|
||||
throw sg_range_exception(
|
||||
"doesn't fit in the specified type: '" + s + "'");
|
||||
}
|
||||
increment = multiplier*digit;
|
||||
|
||||
if (res > std::numeric_limits<T>::max() - increment) {
|
||||
throw sg_range_exception(
|
||||
"doesn't fit in the specified type: '" + s + "'");
|
||||
}
|
||||
res += increment;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// Explicit template instantiations.
|
||||
//
|
||||
// In order to save some bytes for the SimGearCore library[*], we only
|
||||
// instantiate a small number of variants of readNonNegativeInt() below.
|
||||
// Just enable the ones you need if they are disabled.
|
||||
//
|
||||
// [*] The exact amount depends a lot on what you measure and in which
|
||||
// circumstances. On Linux amd64 with g++, I measured a cost ranging
|
||||
// from 2 KB per template in a Release build to 19 KB per template in
|
||||
// a RelWithDebInfo build for the in-memory code size of the resulting
|
||||
// fgfs binary (CODE column in 'top', after selecting a suitable
|
||||
// unit). If I look at the fgfs binary size (statically-linked with
|
||||
// SimGear), I measure from 2 KB per template (Release) to 30 KB per
|
||||
// template (RelWithDebInfo). Finally, a Debug build compiled with
|
||||
// '-fno-omit-frame-pointer -O0 -fno-inline' lies between the Release
|
||||
// and the RelWithDebInfo builds.
|
||||
|
||||
#if 0
|
||||
template
|
||||
signed char readNonNegativeInt<signed char, 10>(const std::string& s);
|
||||
template
|
||||
signed char readNonNegativeInt<signed char, 16>(const std::string& s);
|
||||
template
|
||||
unsigned char readNonNegativeInt<unsigned char, 10>(const std::string& s);
|
||||
template
|
||||
unsigned char readNonNegativeInt<unsigned char, 16>(const std::string& s);
|
||||
|
||||
template
|
||||
short readNonNegativeInt<short, 10>(const std::string& s);
|
||||
template
|
||||
short readNonNegativeInt<short, 16>(const std::string& s);
|
||||
template
|
||||
unsigned short readNonNegativeInt<unsigned short, 10>(const std::string& s);
|
||||
template
|
||||
unsigned short readNonNegativeInt<unsigned short, 16>(const std::string& s);
|
||||
#endif
|
||||
|
||||
template
|
||||
int readNonNegativeInt<int, 10>(const std::string& s);
|
||||
template
|
||||
unsigned int readNonNegativeInt<unsigned int, 10>(const std::string& s);
|
||||
|
||||
#if 0
|
||||
template
|
||||
int readNonNegativeInt<int, 16>(const std::string& s);
|
||||
template
|
||||
unsigned int readNonNegativeInt<unsigned int, 16>(const std::string& s);
|
||||
|
||||
template
|
||||
long readNonNegativeInt<long, 10>(const std::string& s);
|
||||
template
|
||||
long readNonNegativeInt<long, 16>(const std::string& s);
|
||||
template
|
||||
unsigned long readNonNegativeInt<unsigned long, 10>(const std::string& s);
|
||||
template
|
||||
unsigned long readNonNegativeInt<unsigned long, 16>(const std::string& s);
|
||||
|
||||
template
|
||||
long long readNonNegativeInt<long long, 10>(const std::string& s);
|
||||
template
|
||||
long long readNonNegativeInt<long long, 16>(const std::string& s);
|
||||
template
|
||||
unsigned long long readNonNegativeInt<unsigned long long, 10>(
|
||||
const std::string& s);
|
||||
template
|
||||
unsigned long long readNonNegativeInt<unsigned long long, 16>(
|
||||
const std::string& s);
|
||||
#endif
|
||||
|
||||
int compare_versions(const string& v1, const string& v2, int maxComponents)
|
||||
{
|
||||
vector<string> v1parts(split(v1, "."));
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
#include <cstdlib>
|
||||
|
||||
typedef std::vector < std::string > string_list;
|
||||
@@ -169,6 +170,44 @@ namespace simgear {
|
||||
*/
|
||||
int to_int(const std::string& s, int base = 10);
|
||||
|
||||
/** Convert a char to the integer it represents in the specified BASE.
|
||||
*
|
||||
* Contrary to std::isdigit() and std::isxdigit(), only the standard ASCII
|
||||
* digits for BASE are accepted (with both uppercase and lowercase 'a'-'f'
|
||||
* letters for base 16). Throw sg_range_exception if the char is not a
|
||||
* valid digit for this base.
|
||||
*
|
||||
* See template specializations in strutils.cxx.
|
||||
*/
|
||||
template<int BASE>
|
||||
int digitValue(char c);
|
||||
|
||||
/** Return:
|
||||
* - std::string("decimal") if BASE is 10;
|
||||
* - std::string("hexadecimal") if BASE is 16.
|
||||
*
|
||||
* Template specializations in strutils.cxx.
|
||||
*/
|
||||
template<int BASE>
|
||||
std::string numerationBaseAdjective();
|
||||
|
||||
/** Convert a string representing an integer to an integral type.
|
||||
*
|
||||
* The input string must be non-empty and contain only digits of the
|
||||
* specified BASE (template parameter). Throw:
|
||||
* - sg_format_exception if the input string doesn't respect these
|
||||
* constraints;
|
||||
* - sg_range_exception if the value can't be represented by type T
|
||||
* (i.e., if it is too large).
|
||||
*
|
||||
* Explicit template instantiations are added as needed in strutils.cxx.
|
||||
* Have a look there and enable the ones you need!
|
||||
*/
|
||||
template<
|
||||
class T,
|
||||
int BASE = 10,
|
||||
typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
|
||||
T readNonNegativeInt(const std::string& s);
|
||||
|
||||
/**
|
||||
* Convert a string representing a boolean, to a bool.
|
||||
|
||||
@@ -6,12 +6,19 @@
|
||||
#include <vector>
|
||||
#include <utility> // std::move()
|
||||
#include <fstream> // std::ifstream
|
||||
#include <cerrno>
|
||||
#include <sstream> // std::ostringstream
|
||||
#include <ios> // std::dec, std::hex
|
||||
#include <limits> // std::numeric_limits
|
||||
#include <typeinfo> // typeid()
|
||||
#include <cstdint> // uint16_t, uintmax_t, etc.
|
||||
#include <cstdlib> // _set_errno() on Windows
|
||||
#include <cerrno>
|
||||
#include <cassert>
|
||||
|
||||
#include <simgear/misc/test_macros.hxx>
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/misc/strutils.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
@@ -90,6 +97,290 @@ void test_to_int()
|
||||
SG_CHECK_EQUAL(strutils::to_int("-10000"), -10000);
|
||||
}
|
||||
|
||||
// Auxiliary function for test_readNonNegativeInt()
|
||||
void aux_readNonNegativeInt_setUpOStringStream(std::ostringstream& oss, int base)
|
||||
{
|
||||
switch (base) {
|
||||
case 10:
|
||||
oss << std::dec;
|
||||
break;
|
||||
case 16:
|
||||
oss << std::hex;
|
||||
break;
|
||||
default:
|
||||
SG_TEST_FAIL("unsupported value for 'base': " + std::to_string(base));
|
||||
}
|
||||
}
|
||||
|
||||
// Auxiliary function for test_readNonNegativeInt(): round-trip conversion for
|
||||
// the given number of values below and up to std::numeric_limits<T>::max().
|
||||
template<typename T, int BASE>
|
||||
void aux_readNonNegativeInt_testValuesCloseToMax(T nbValues)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
assert(0 <= nbValues && nbValues <= std::numeric_limits<T>::max());
|
||||
aux_readNonNegativeInt_setUpOStringStream(oss, BASE);
|
||||
|
||||
for (T i = std::numeric_limits<T>::max() - nbValues;
|
||||
i < std::numeric_limits<T>::max(); i++) {
|
||||
T valueToTest = i + 1;
|
||||
T roundTripResult;
|
||||
bool gotException = false;
|
||||
|
||||
oss.str("");
|
||||
// The cast is only useful when T is a char type
|
||||
oss << static_cast<uintmax_t>(valueToTest);
|
||||
|
||||
try {
|
||||
roundTripResult = strutils::readNonNegativeInt<T, BASE>(oss.str());
|
||||
} catch (const sg_range_exception&) {
|
||||
gotException = true;
|
||||
}
|
||||
|
||||
SG_VERIFY(!gotException);
|
||||
SG_CHECK_EQUAL(roundTripResult, valueToTest);
|
||||
}
|
||||
}
|
||||
|
||||
// Auxiliary class for test_readNonNegativeInt(): test that we do get an
|
||||
// exception when trying to convert the smallest, positive out-of-range value
|
||||
// for type T.
|
||||
template<typename T, int BASE>
|
||||
class ReadNonNegativeInt_JustOutOfRangeTester {
|
||||
public:
|
||||
ReadNonNegativeInt_JustOutOfRangeTester()
|
||||
{ }
|
||||
|
||||
// Run the test
|
||||
void run()
|
||||
{
|
||||
std::ostringstream oss;
|
||||
aux_readNonNegativeInt_setUpOStringStream(oss, BASE);
|
||||
oss << 1 + static_cast<uintmax_t>(std::numeric_limits<T>::max());
|
||||
bool gotException = false;
|
||||
|
||||
try {
|
||||
strutils::readNonNegativeInt<T, BASE>(oss.str());
|
||||
} catch (const sg_range_exception&) {
|
||||
gotException = true;
|
||||
}
|
||||
|
||||
SG_VERIFY(gotException);
|
||||
}
|
||||
};
|
||||
|
||||
class ReadNonNegativeInt_DummyTester {
|
||||
public:
|
||||
ReadNonNegativeInt_DummyTester()
|
||||
{ }
|
||||
|
||||
void run()
|
||||
{ }
|
||||
};
|
||||
|
||||
// We use this helper class to automatically determine for which types
|
||||
// ReadNonNegativeInt_JustOutOfRangeTester::run() can be run.
|
||||
template<typename T, int BASE>
|
||||
class AuxReadNonNegativeInt_JustOutOfRange_Helper
|
||||
{
|
||||
typedef typename std::make_unsigned<T>::type uT;
|
||||
|
||||
// Define TestRunner to be either
|
||||
//
|
||||
// ReadNonNegativeInt_JustOutOfRangeTester<T, BASE>
|
||||
//
|
||||
// or
|
||||
//
|
||||
// ReadNonNegativeInt_DummyTester
|
||||
//
|
||||
// depending on whether 1 + std::numeric_limits<T>::max() can be
|
||||
// represented by uintmax_t.
|
||||
typedef typename std::conditional<
|
||||
static_cast<uT>(std::numeric_limits<T>::max()) <
|
||||
std::numeric_limits<uintmax_t>::max(),
|
||||
ReadNonNegativeInt_JustOutOfRangeTester<T, BASE>,
|
||||
ReadNonNegativeInt_DummyTester >::type TestRunner;
|
||||
|
||||
public:
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper()
|
||||
{ };
|
||||
|
||||
void test()
|
||||
{
|
||||
TestRunner().run();
|
||||
}
|
||||
};
|
||||
|
||||
void test_readNonNegativeInt()
|
||||
{
|
||||
// In order to save some bytes for the SimGearCore library[*], we only
|
||||
// instantiated a small number of variants of readNonNegativeInt() in
|
||||
// strutils.cxx. This is why many tests are disabled with '#if 0' below. Of
|
||||
// course, more variants can be enabled when they are needed.
|
||||
//
|
||||
// [*] See measures in strutils.cxx before the template instantiations.
|
||||
|
||||
#if 0
|
||||
SG_CHECK_EQUAL((strutils::readNonNegativeInt<short>("0")), 0);
|
||||
SG_CHECK_EQUAL((strutils::readNonNegativeInt<short>("23")), 23);
|
||||
#endif
|
||||
|
||||
SG_CHECK_EQUAL((strutils::readNonNegativeInt<int>("0")), 0);
|
||||
SG_CHECK_EQUAL((strutils::readNonNegativeInt<int>("00000000")), 0);
|
||||
SG_CHECK_EQUAL((strutils::readNonNegativeInt<int>("12345")), 12345);
|
||||
SG_CHECK_EQUAL((strutils::readNonNegativeInt<int, 10>("12345")), 12345);
|
||||
|
||||
#if 0
|
||||
SG_CHECK_EQUAL((strutils::readNonNegativeInt<int, 16>("ff")), 0xff);
|
||||
SG_CHECK_EQUAL((strutils::readNonNegativeInt<int, 16>("a5E9")), 0xa5e9);
|
||||
SG_CHECK_EQUAL((strutils::readNonNegativeInt<unsigned long, 16>("0cda")),
|
||||
0x0cda);
|
||||
|
||||
SG_CHECK_EQUAL((strutils::readNonNegativeInt<uint16_t, 10>("65535")), 0xffff);
|
||||
SG_CHECK_EQUAL(
|
||||
(strutils::readNonNegativeInt<uint16_t, 10>("00000000000000000000065535")),
|
||||
0xffff);
|
||||
SG_CHECK_EQUAL((strutils::readNonNegativeInt<uint16_t, 16>("ffff")), 0xffff);
|
||||
SG_CHECK_EQUAL((strutils::readNonNegativeInt<int16_t, 10>("32767")), 0x7fff);
|
||||
SG_CHECK_EQUAL((strutils::readNonNegativeInt<int16_t, 16>("7fff")), 0x7fff);
|
||||
#endif
|
||||
|
||||
// Nothing special about the values :)
|
||||
SG_CHECK_EQUAL_NOSTREAM((typeid(strutils::readNonNegativeInt<int, 10>("72"))),
|
||||
typeid(int(12)));
|
||||
#if 0
|
||||
SG_CHECK_EQUAL_NOSTREAM((typeid(strutils::readNonNegativeInt<long, 10>("72"))),
|
||||
typeid(12L));
|
||||
SG_CHECK_EQUAL_NOSTREAM(
|
||||
(typeid(strutils::readNonNegativeInt<long long, 10>("72"))),
|
||||
typeid(12LL));
|
||||
#endif
|
||||
|
||||
{
|
||||
bool gotException = false;
|
||||
try {
|
||||
strutils::readNonNegativeInt<int>(""); // empty string: illegal
|
||||
} catch (const sg_format_exception&) {
|
||||
gotException = true;
|
||||
}
|
||||
SG_VERIFY(gotException);
|
||||
}
|
||||
|
||||
{
|
||||
bool gotException = false;
|
||||
try {
|
||||
strutils::readNonNegativeInt<int>("-1"); // non-digit character: illegal
|
||||
} catch (const sg_format_exception&) {
|
||||
gotException = true;
|
||||
}
|
||||
SG_VERIFY(gotException);
|
||||
}
|
||||
|
||||
{
|
||||
bool gotException = false;
|
||||
try {
|
||||
strutils::readNonNegativeInt<int>("+1"); // non-digit character: illegal
|
||||
} catch (const sg_format_exception&) {
|
||||
gotException = true;
|
||||
}
|
||||
SG_VERIFY(gotException);
|
||||
}
|
||||
|
||||
{
|
||||
bool gotException = false;
|
||||
try {
|
||||
strutils::readNonNegativeInt<int>("858efe"); // trailing garbage: illegal
|
||||
} catch (const sg_format_exception&) {
|
||||
gotException = true;
|
||||
}
|
||||
SG_VERIFY(gotException);
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
bool gotException = false;
|
||||
try {
|
||||
strutils::readNonNegativeInt<int, 16>("858g5k"); // ditto for base 16
|
||||
} catch (const sg_format_exception&) {
|
||||
gotException = true;
|
||||
}
|
||||
SG_VERIFY(gotException);
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
bool gotException = false;
|
||||
try {
|
||||
strutils::readNonNegativeInt<int>(" 858"); // leading whitespace/garbage:
|
||||
} catch (const sg_format_exception&) { // illegal too
|
||||
gotException = true;
|
||||
}
|
||||
SG_VERIFY(gotException);
|
||||
}
|
||||
|
||||
// Try to read a value that is 1 unit too large for the type. Check that it
|
||||
// raises an sg_range_exception in each case.
|
||||
#if 0
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper<signed char, 10>().test();
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper<signed char, 16>().test();
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper<unsigned char, 10>().test();
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper<unsigned char, 16>().test();
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper<short, 10>().test();
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper<short, 16>().test();
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper<unsigned short, 10>().test();
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper<unsigned short, 16>().test();
|
||||
#endif
|
||||
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper<int, 10>().test();
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper<unsigned int, 10>().test();
|
||||
|
||||
#if 0
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper<int, 16>().test();
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper<unsigned int, 16>().test();
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper<long, 10>().test();
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper<long, 16>().test();
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper<unsigned long, 10>().test();
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper<unsigned long, 16>().test();
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper<long long, 10>().test();
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper<long long, 16>().test();
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper<unsigned long long, 10>().test();
|
||||
AuxReadNonNegativeInt_JustOutOfRange_Helper<unsigned long long, 16>().test();
|
||||
#endif
|
||||
|
||||
// Round trip tests with large values, including the largest value that can
|
||||
// be represented by the type, in each case.
|
||||
//
|
||||
// Can be casted as any of the following types
|
||||
constexpr int nbValues = 5000;
|
||||
#if 0
|
||||
aux_readNonNegativeInt_testValuesCloseToMax<signed char, 10>(127);
|
||||
aux_readNonNegativeInt_testValuesCloseToMax<signed char, 16>(127);
|
||||
aux_readNonNegativeInt_testValuesCloseToMax<unsigned char, 10>(127);
|
||||
aux_readNonNegativeInt_testValuesCloseToMax<unsigned char, 16>(127);
|
||||
aux_readNonNegativeInt_testValuesCloseToMax<short, 10>(nbValues);
|
||||
aux_readNonNegativeInt_testValuesCloseToMax<short, 16>(nbValues);
|
||||
aux_readNonNegativeInt_testValuesCloseToMax<unsigned short, 10>(nbValues);
|
||||
aux_readNonNegativeInt_testValuesCloseToMax<unsigned short, 16>(nbValues);
|
||||
#endif
|
||||
|
||||
aux_readNonNegativeInt_testValuesCloseToMax<int, 10>(nbValues);
|
||||
aux_readNonNegativeInt_testValuesCloseToMax<unsigned int, 10>(nbValues);
|
||||
|
||||
#if 0
|
||||
aux_readNonNegativeInt_testValuesCloseToMax<int, 16>(nbValues);
|
||||
aux_readNonNegativeInt_testValuesCloseToMax<unsigned int, 16>(nbValues);
|
||||
aux_readNonNegativeInt_testValuesCloseToMax<long, 10>(nbValues);
|
||||
aux_readNonNegativeInt_testValuesCloseToMax<long, 16>(nbValues);
|
||||
aux_readNonNegativeInt_testValuesCloseToMax<unsigned long, 10>(nbValues);
|
||||
aux_readNonNegativeInt_testValuesCloseToMax<unsigned long, 16>(nbValues);
|
||||
aux_readNonNegativeInt_testValuesCloseToMax<long long, 10>(nbValues);
|
||||
aux_readNonNegativeInt_testValuesCloseToMax<long long, 16>(nbValues);
|
||||
aux_readNonNegativeInt_testValuesCloseToMax<unsigned long long, 10>(nbValues);
|
||||
aux_readNonNegativeInt_testValuesCloseToMax<unsigned long long, 16>(nbValues);
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_split()
|
||||
{
|
||||
string_list l = strutils::split("zero one two three four five");
|
||||
@@ -299,6 +590,7 @@ int main(int argc, char* argv[])
|
||||
test_ends_with();
|
||||
test_simplify();
|
||||
test_to_int();
|
||||
test_readNonNegativeInt();
|
||||
test_split();
|
||||
test_escape();
|
||||
test_unescape();
|
||||
|
||||
Reference in New Issue
Block a user