diff --git a/ChangeLog b/ChangeLog index 89a3386d..d8cf3b63 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2019-11-17 Markus Gans + * Revision of FString number input stream + 2019-11-16 Markus Gans * New Widget class FSpinBox to provide spin boxes diff --git a/examples/term-attributes.cpp b/examples/term-attributes.cpp index 3aca493d..62c6c550 100644 --- a/examples/term-attributes.cpp +++ b/examples/term-attributes.cpp @@ -253,7 +253,7 @@ void AttribDemo::printColorLine() { auto parent = static_cast(getParent()); - for (FColor color{0}; color < uInt(colors); color++) + for (FColor color{0}; color < FColor(colors); color++) { print() << FColorPair(color, parent->bgcolor) << " # "; } diff --git a/src/fstring.cpp b/src/fstring.cpp index 49cddf9c..ab4c24db 100644 --- a/src/fstring.cpp +++ b/src/fstring.cpp @@ -244,88 +244,6 @@ FString& FString::operator << (const char c) return *this; } -//---------------------------------------------------------------------- -FString& FString::operator << (const sInt16 num) -{ - FString numstr(FString().setNumber(num)); - _insert (length, numstr.length, numstr.string); - return *this; -} - -//---------------------------------------------------------------------- -FString& FString::operator << (const uInt16 num) -{ - FString numstr(FString().setNumber(num)); - _insert (length, numstr.length, numstr.string); - return *this; -} - -//---------------------------------------------------------------------- -FString& FString::operator << (const sInt32 num) -{ - FString numstr(FString().setNumber(num)); - _insert (length, numstr.length, numstr.string); - return *this; -} - -//---------------------------------------------------------------------- -FString& FString::operator << (const sInt64 num) -{ - FString numstr(FString().setNumber(num)); - _insert (length, numstr.length, numstr.string); - return *this; -} - -//---------------------------------------------------------------------- -FString& FString::operator << (const uInt32 num) -{ - FString numstr(FString().setNumber(num)); - _insert (length, numstr.length, numstr.string); - return *this; -} - -//---------------------------------------------------------------------- -FString& FString::operator << (const uInt64 num) -{ - FString numstr(FString().setNumber(num)); - _insert (length, numstr.length, numstr.string); - return *this; -} - -//---------------------------------------------------------------------- -#if defined(__APPLE__) && defined(__MACH__) -FString& FString::operator << (const std::size_t num) -{ - FString numstr(FString().setNumber(num)); - _insert (length, numstr.length, numstr.string); - return *this; -} -#endif - -//---------------------------------------------------------------------- -FString& FString::operator << (const float num) -{ - FString numstr(FString().setNumber(num)); - _insert (length, numstr.length, numstr.string); - return *this; -} - -//---------------------------------------------------------------------- -FString& FString::operator << (const double num) -{ - FString numstr(FString().setNumber(num)); - _insert (length, numstr.length, numstr.string); - return *this; -} - -//---------------------------------------------------------------------- -FString& FString::operator << (const lDouble num) -{ - FString numstr(FString().setNumber(num)); - _insert (length, numstr.length, numstr.string); - return *this; -} - //---------------------------------------------------------------------- const FString& FString::operator >> (FString& s) { @@ -856,30 +774,23 @@ FString& FString::setString (const FString& s) //---------------------------------------------------------------------- FString& FString::setNumber (sInt64 num) { - bool neg{false}; wchar_t buf[30]{}; wchar_t* s = &buf[29]; + uInt64 abs_num = static_cast(num); if ( num < 0 ) - { - neg = true; - num = -num; - } - else - { - neg = false; - } + abs_num = -num; *s = '\0'; do { - *--s = L"0123456789"[num % 10]; - num /= 10; + *--s = L"0123456789"[abs_num % 10]; + abs_num /= 10; } - while ( num ); + while ( abs_num ); - if ( neg ) + if ( num < 0 ) *--s = '-'; _assign (s); @@ -938,37 +849,30 @@ FString& FString::setNumber (lDouble f_num, int precision) //---------------------------------------------------------------------- FString& FString::setFormatedNumber (sInt64 num, char separator) { - bool neg{false}; int n{0}; wchar_t buf[30]{}; wchar_t* s = &buf[29]; + uInt64 abs_num = static_cast(num); if ( separator == 0 ) separator = ' '; if ( num < 0 ) - { - neg = true; - num = -num; - } - else - { - neg = false; - } + abs_num = -num; *s = L'\0'; do { - *--s = L"0123456789"[num % 10]; - num /= 10; + *--s = L"0123456789"[abs_num % 10]; + abs_num /= 10; - if ( num && ++n % 3 == 0 ) + if ( abs_num && ++n % 3 == 0 ) *--s = separator; } - while ( num ); + while ( abs_num ); - if ( neg ) + if ( num < 0 ) *--s = '-'; _assign (s); diff --git a/src/include/final/fstring.h b/src/include/final/fstring.h index 4f1c16b6..cf506c34 100644 --- a/src/include/final/fstring.h +++ b/src/include/final/fstring.h @@ -114,18 +114,11 @@ class FString FString& operator << (fc::SpecialCharacter); FString& operator << (const wchar_t); FString& operator << (const char); - FString& operator << (const sInt16); - FString& operator << (const uInt16); - FString& operator << (const sInt32); - FString& operator << (const uInt32); - FString& operator << (const sInt64); - FString& operator << (const uInt64); -#if defined(__APPLE__) && defined(__MACH__) - FString& operator << (const std::size_t); -#endif - FString& operator << (const float); - FString& operator << (const double); - FString& operator << (const lDouble); + template ::value + || std::is_floating_point::value + , NumT>::type* = nullptr > + FString& operator << (const NumT); const FString& operator >> (FString&); const FString& operator >> (std::wstring&); @@ -291,8 +284,16 @@ class FString // FString inline functions //---------------------------------------------------------------------- -inline const FString FString::getClassName() -{ return "FString"; } +template ::value + || std::is_floating_point::value + , NumT>::type* = nullptr > +inline FString& FString::operator << (const NumT val) +{ + FString numstr(FString().setNumber(val)); + _insert (length, numstr.length, numstr.string); + return *this; +} //---------------------------------------------------------------------- template @@ -368,6 +369,10 @@ inline bool FString::operator > (const CharT& s) const return *this > tmp; } +//---------------------------------------------------------------------- +inline const FString FString::getClassName() +{ return "FString"; } + //---------------------------------------------------------------------- inline bool FString::isNull() const { return ! string; } diff --git a/test/fobject-test.cpp b/test/fobject-test.cpp index cbd7ab8c..0ea337e0 100644 --- a/test/fobject-test.cpp +++ b/test/fobject-test.cpp @@ -149,6 +149,7 @@ class FObjectTest : public CPPUNIT_NS::TestFixture void childObjectTest(); void widgetObjectTest(); void removeParentTest(); + void setParentTest(); void addTest(); void delTest(); void iteratorTest(); @@ -167,6 +168,7 @@ class FObjectTest : public CPPUNIT_NS::TestFixture CPPUNIT_TEST (childObjectTest); CPPUNIT_TEST (widgetObjectTest); CPPUNIT_TEST (removeParentTest); + CPPUNIT_TEST (setParentTest); CPPUNIT_TEST (addTest); CPPUNIT_TEST (delTest); CPPUNIT_TEST (iteratorTest); @@ -319,6 +321,51 @@ void FObjectTest::removeParentTest() delete obj; // also deletes the child object } +//---------------------------------------------------------------------- +void FObjectTest::setParentTest() +{ + // obj -> child + // => newobj -> child + + auto obj = new finalcut::FObject(); + auto child = new finalcut::FObject(obj); + + CPPUNIT_ASSERT ( obj->hasChildren() ); + CPPUNIT_ASSERT ( obj->numOfChildren() == 1 ); + CPPUNIT_ASSERT ( obj->isChild(child) ); + CPPUNIT_ASSERT ( obj->isDirectChild(child) ); + + CPPUNIT_ASSERT ( child->hasParent() ); + CPPUNIT_ASSERT ( child->getParent() == obj ); + + auto newobj = new finalcut::FObject(); + + CPPUNIT_ASSERT ( ! newobj->hasChildren() ); + CPPUNIT_ASSERT ( newobj->numOfChildren() == 0 ); + CPPUNIT_ASSERT ( ! newobj->isChild(child) ); + CPPUNIT_ASSERT ( ! newobj->isDirectChild(child) ); + + child->setParent(newobj); + + CPPUNIT_ASSERT ( ! obj->hasChildren() ); + CPPUNIT_ASSERT ( obj->numOfChildren() == 0 ); + CPPUNIT_ASSERT ( ! obj->isChild(child) ); + CPPUNIT_ASSERT ( ! obj->isDirectChild(child) ); + + CPPUNIT_ASSERT ( newobj->hasChildren() ); + CPPUNIT_ASSERT ( newobj->numOfChildren() == 1 ); + CPPUNIT_ASSERT ( newobj->isChild(child) ); + CPPUNIT_ASSERT ( newobj->isDirectChild(child) ); + + CPPUNIT_ASSERT ( child->hasParent() ); + CPPUNIT_ASSERT ( child->getParent() != obj ); + CPPUNIT_ASSERT ( child->getParent() == newobj ); + + delete obj; + delete child; + delete newobj; // also deletes the child object +} + //---------------------------------------------------------------------- void FObjectTest::addTest() { diff --git a/test/fstring-test.cpp b/test/fstring-test.cpp index 7b136ad2..96b5952d 100644 --- a/test/fstring-test.cpp +++ b/test/fstring-test.cpp @@ -832,6 +832,18 @@ void FStringTest::streamInsertionTest() out << char('A'); CPPUNIT_ASSERT ( out == L"A" ); + out.clear(); + out << sInt8(INT_LEAST8_MAX); + CPPUNIT_ASSERT ( out == L"127" ); + + out.clear(); + out << sInt8(INT_LEAST8_MIN); + CPPUNIT_ASSERT ( out == L"-128" ); + + out.clear(); + out << uInt8(UINT_LEAST8_MAX); + CPPUNIT_ASSERT ( out == L"255" ); + out.clear(); out << sInt16(INT_LEAST16_MAX); CPPUNIT_ASSERT ( out == L"32767" ); @@ -844,6 +856,38 @@ void FStringTest::streamInsertionTest() out << uInt16(UINT_LEAST16_MAX); CPPUNIT_ASSERT ( out == L"65535" ); + out.clear(); + out << sInt32(INT_LEAST32_MAX); + CPPUNIT_ASSERT ( out == L"2147483647" ); + + out.clear(); + out << sInt32(INT_LEAST32_MIN); + CPPUNIT_ASSERT ( out == L"-2147483648" ); + + out.clear(); + out << uInt32(UINT_LEAST32_MAX); + CPPUNIT_ASSERT ( out == L"4294967295" ); + + out.clear(); + out << sInt64(INT_LEAST64_MAX); + CPPUNIT_ASSERT ( out == L"9223372036854775807" ); + + out.clear(); + out << sInt64(INT_LEAST64_MIN); + CPPUNIT_ASSERT ( out == L"-9223372036854775808" ); + + out.clear(); + out << uInt64(UINT_LEAST64_MAX); + CPPUNIT_ASSERT ( out == L"18446744073709551615" ); + + out.clear(); + out << std::wint_t(WINT_MAX); + CPPUNIT_ASSERT ( out == L"4294967295" ); + + out.clear(); + out << std::size_t(999999999); + CPPUNIT_ASSERT ( out == L"999999999" ); + out.clear(); out << int(1234567); CPPUNIT_ASSERT ( out == L"1234567" ); @@ -1166,21 +1210,23 @@ void FStringTest::convertToNumberTest() //---------------------------------------------------------------------- void FStringTest::convertFromNumberTest() { - constexpr sInt8 n1 = -12; - constexpr uInt8 n2 = 12u; - constexpr sInt16 n3 = -1234; - constexpr uInt16 n4 = 1234u; - constexpr int n5 = -12345; - constexpr uInt n6 = 12345u; - constexpr sInt32 n7 = -12345; - constexpr uInt32 n8 = 12345u; - constexpr long n9 = -12345678; - constexpr uLong n10 = 12345678u; - constexpr sInt64 n11 = -12345678; - constexpr uInt64 n12 = 12345678u; - constexpr float n13 = 1234.56f; - constexpr double n14 = 1234.5678; - constexpr lDouble n15 = 12345.67890L; + constexpr sInt8 n1 = -12; + constexpr uInt8 n2 = 12u; + constexpr sInt16 n3 = -1234; + constexpr uInt16 n4 = 1234u; + constexpr int n5 = -12345; + constexpr uInt n6 = 12345u; + constexpr sInt32 n7 = -12345; + constexpr uInt32 n8 = 12345u; + constexpr long n9 = -12345678; + constexpr uLong n10 = 12345678u; + constexpr sInt64 n11 = -12345678; + constexpr uInt64 n12 = 12345678u; + constexpr std::wint_t n13 = 12345678; + constexpr std::size_t n14 = 12345678; + constexpr float n15 = 1234.56f; + constexpr double n16 = 1234.5678; + constexpr lDouble n17 = 12345.67890L; CPPUNIT_ASSERT ( finalcut::getPrecision() == FLT_DIG ); CPPUNIT_ASSERT ( finalcut::getPrecision() == DBL_DIG ); @@ -1198,17 +1244,19 @@ void FStringTest::convertFromNumberTest() CPPUNIT_ASSERT ( finalcut::FString().setNumber(n10) == "12345678" ); CPPUNIT_ASSERT ( finalcut::FString().setNumber(n11) == "-12345678" ); CPPUNIT_ASSERT ( finalcut::FString().setNumber(n12) == "12345678" ); - CPPUNIT_ASSERT ( finalcut::FString().setNumber(n13) == "1234.56" ); - CPPUNIT_ASSERT ( finalcut::FString().setNumber(n14) == "1234.5678" ); - CPPUNIT_ASSERT ( finalcut::FString().setNumber(n15) == "12345.6789" ); - CPPUNIT_ASSERT ( finalcut::FString().setNumber(n13, 0) == "1e+03" ); - CPPUNIT_ASSERT ( finalcut::FString().setNumber(n14, 0) == "1e+03" ); - CPPUNIT_ASSERT ( finalcut::FString().setNumber(n15, 0) == "1e+04" ); - CPPUNIT_ASSERT ( finalcut::FString().setNumber(n13, 100) - == "1234.56005859375" ); - CPPUNIT_ASSERT ( finalcut::FString().setNumber(n14, 100) - == "1234.567800000000033833202905952930450439453125" ); + CPPUNIT_ASSERT ( finalcut::FString().setNumber(n13) == "12345678" ); + CPPUNIT_ASSERT ( finalcut::FString().setNumber(n14) == "12345678" ); + CPPUNIT_ASSERT ( finalcut::FString().setNumber(n15) == "1234.56" ); + CPPUNIT_ASSERT ( finalcut::FString().setNumber(n16) == "1234.5678" ); + CPPUNIT_ASSERT ( finalcut::FString().setNumber(n17) == "12345.6789" ); + CPPUNIT_ASSERT ( finalcut::FString().setNumber(n15, 0) == "1e+03" ); + CPPUNIT_ASSERT ( finalcut::FString().setNumber(n16, 0) == "1e+03" ); + CPPUNIT_ASSERT ( finalcut::FString().setNumber(n17, 0) == "1e+04" ); CPPUNIT_ASSERT ( finalcut::FString().setNumber(n15, 100) + == "1234.56005859375" ); + CPPUNIT_ASSERT ( finalcut::FString().setNumber(n16, 100) + == "1234.567800000000033833202905952930450439453125" ); + CPPUNIT_ASSERT ( finalcut::FString().setNumber(n17, 100) == "12345.67889999999999961488583721802569925785064697265625" ); }