From cb233048857e738dea488190aa6b816f9ba17a9d Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Fri, 5 Jan 2018 20:03:11 +0000 Subject: [PATCH] added: to methods Toull(), Toll(), Toul(), Toui(), Tol(), Toi() a new parameter: bool allow_skip_whitechars default true added: new methods: Toull_b(), Toll_b(), Toul_b(), Toui_b(), Tol_b(), Toi_b() automatically detects the base (radix): 4323 - base 10 0122 - base 8 (string starts with 0) #fff - base 16 (string starts with #) &101 - base 2 (string starts with &) added: CharType * SkipWhiteFromBack(CharType * str, bool check_additional_chars = true, bool treat_new_line_as_white = true) skipping white characters from the end of a string changed: Toll_b(), Toull_b(), Tol_b() and Toul_b() are used in Space now for methods ToInt() etc so we are able to use a different base now changed: some work in Space (const correctness) git-svn-id: svn://ttmath.org/publicrep/pikotools/trunk@1070 e52654a7-88a9-db11-a3e9-0013d4bc506e --- convert/strtoint.h | 209 ++++++++++++++++++++++++++++++++++++++++----- convert/text.h | 32 +++++++ space/space.cpp | 145 +++++++++++++++---------------- space/space.h | 69 ++++++++------- 4 files changed, 325 insertions(+), 130 deletions(-) diff --git a/convert/strtoint.h b/convert/strtoint.h index b1f2271..3aae7dc 100644 --- a/convert/strtoint.h +++ b/convert/strtoint.h @@ -50,14 +50,16 @@ namespace PT template -unsigned long long Toull(const CharType * str, int base = 10, const CharType ** after_str = 0, bool * was_overflow = 0) +unsigned long long Toull(const CharType * str, int base = 10, const CharType ** after_str = 0, bool * was_overflow = 0, bool allow_skip_whitechars = true) { unsigned long long res = 0; bool carry = false; int digit; SetOverflow(was_overflow, false); - str = SkipWhite(str); + + if( allow_skip_whitechars ) + str = SkipWhite(str); while( !carry && IsDigit(*str, base, &digit) ) { @@ -78,9 +80,12 @@ unsigned long long Toull(const CharType * str, int base = 10, const CharType ** if( carry ) { - while( IsDigit(*str, base, &digit) ) + if( after_str ) { - str += 1; + while( IsDigit(*str, base, &digit) ) + { + str += 1; + } } SetOverflow(was_overflow, true); @@ -95,13 +100,15 @@ unsigned long long Toull(const CharType * str, int base = 10, const CharType ** template -long long Toll(const CharType * str, int base = 10, const CharType ** after_str = 0, bool * was_overflow = 0) +long long Toll(const CharType * str, int base = 10, const CharType ** after_str = 0, bool * was_overflow = 0, bool allow_skip_whitechars = true) { bool was_sign = false; bool was_overflow_u = false; SetOverflow(was_overflow, false); - str = SkipWhite(str); + + if( allow_skip_whitechars ) + str = SkipWhite(str); if( *str == '-' ) { @@ -109,9 +116,7 @@ long long Toll(const CharType * str, int base = 10, const CharType ** after_str str += 1; } - // we do not trim spaces between a sign and a digit - - unsigned long long uval = Toull(str, base, after_str, &was_overflow_u); + unsigned long long uval = Toull(str, base, after_str, &was_overflow_u, false); unsigned long long sign_add = ( was_sign ) ? 1 : 0; if( was_overflow_u ) @@ -136,13 +141,14 @@ long long Toll(const CharType * str, int base = 10, const CharType ** after_str + template -IntegerType ToUnsignedIntegerType(const CharType * str, int base = 10, const CharType ** after_str = 0, bool * was_overflow = 0) +IntegerType ToUnsignedIntegerType(const CharType * str, int base = 10, const CharType ** after_str = 0, bool * was_overflow = 0, bool allow_skip_whitechars = true) { bool was_overflow_ll = false; SetOverflow(was_overflow, false); - unsigned long long val = Toull(str, base, after_str, &was_overflow_ll); + unsigned long long val = Toull(str, base, after_str, &was_overflow_ll, allow_skip_whitechars); if( was_overflow_ll || val > static_cast(std::numeric_limits::max()) ) { @@ -155,15 +161,15 @@ IntegerType ToUnsignedIntegerType(const CharType * str, int base = 10, const Cha template -unsigned long Toul(const CharType * str, int base = 10, const CharType ** after_str = 0, bool * was_overflow = 0) +unsigned long Toul(const CharType * str, int base = 10, const CharType ** after_str = 0, bool * was_overflow = 0, bool allow_skip_whitechars = true) { - return ToUnsignedIntegerType(str, base, after_str, was_overflow); + return ToUnsignedIntegerType(str, base, after_str, was_overflow, allow_skip_whitechars); } template -unsigned int Toui(const CharType * str, int base = 10, const CharType ** after_str = 0, bool * was_overflow = 0) +unsigned int Toui(const CharType * str, int base = 10, const CharType ** after_str = 0, bool * was_overflow = 0, bool allow_skip_whitechars = true) { - return ToUnsignedIntegerType(str, base, after_str, was_overflow); + return ToUnsignedIntegerType(str, base, after_str, was_overflow, allow_skip_whitechars); } @@ -171,12 +177,12 @@ unsigned int Toui(const CharType * str, int base = 10, const CharType ** after_s template -IntegerType ToIntegerType(const CharType * str, int base = 10, const CharType ** after_str = 0, bool * was_overflow = 0) +IntegerType ToIntegerType(const CharType * str, int base = 10, const CharType ** after_str = 0, bool * was_overflow = 0, bool allow_skip_whitechars = true) { bool was_overflow_ll = false; SetOverflow(was_overflow, false); - long long val = Toll(str, base, after_str, &was_overflow_ll); + long long val = Toll(str, base, after_str, &was_overflow_ll, allow_skip_whitechars); if( was_overflow_ll || val < static_cast(std::numeric_limits::min()) || @@ -192,19 +198,180 @@ IntegerType ToIntegerType(const CharType * str, int base = 10, const CharType ** template -long Tol(const CharType * str, int base = 10, const CharType ** after_str = 0, bool * was_overflow = 0) +long Tol(const CharType * str, int base = 10, const CharType ** after_str = 0, bool * was_overflow = 0, bool allow_skip_whitechars = true) { - return ToIntegerType(str, base, after_str, was_overflow); + return ToIntegerType(str, base, after_str, was_overflow, allow_skip_whitechars); } template -int Toi(const CharType * str, int base = 10, const CharType ** after_str = 0, bool * was_overflow = 0) +int Toi(const CharType * str, int base = 10, const CharType ** after_str = 0, bool * was_overflow = 0, bool allow_skip_whitechars = true) { - return ToIntegerType(str, base, after_str, was_overflow); + return ToIntegerType(str, base, after_str, was_overflow, allow_skip_whitechars); } + + + + + +/* + * + * the base will be automatically detected + * + * (first digit is [1-9]) - base 10 + * 0 - 8 + * # - 16 + * & - 2 + * + */ +template +unsigned long long Toull_b(const CharType * str, const CharType ** after_str = 0, bool * was_overflow = 0, bool allow_skip_whitechars = true) +{ + if( allow_skip_whitechars ) + str = SkipWhite(str); + + int base = 10; + + if( *str == '0' ) + { + base = 8; + str += 1; + } + else + if( *str == '#' ) + { + base = 16; + str += 1; + } + else + if( *str == '&' ) + { + base = 2; + str += 1; + } + + return Toull(str, base, after_str, was_overflow, false); +} + + + +template +long long Toll_b(const CharType * str, const CharType ** after_str = 0, bool * was_overflow = 0, bool allow_skip_whitechars = true) +{ + bool was_sign = false; + bool was_overflow_u = false; + + SetOverflow(was_overflow, false); + + if( allow_skip_whitechars ) + str = SkipWhite(str); + + if( *str == '-' ) + { + was_sign = true; + str += 1; + } + + unsigned long long uval = Toull_b(str, after_str, &was_overflow_u, false); + unsigned long long sign_add = ( was_sign ) ? 1 : 0; + + if( was_overflow_u ) + { + SetOverflow(was_overflow, true); + return 0; + } + + if( uval > static_cast(std::numeric_limits::max()) + sign_add ) + { + SetOverflow(was_overflow, true); + return 0; + } + + if( was_sign ) + { + return static_cast(0) - static_cast(uval); + } + + return static_cast(uval); +} + + + + + + + + +template +IntegerType ToUnsignedIntegerType_b(const CharType * str, const CharType ** after_str = 0, bool * was_overflow = 0, bool allow_skip_whitechars = true) +{ + bool was_overflow_ll = false; + + SetOverflow(was_overflow, false); + unsigned long long val = Toull_b(str, after_str, &was_overflow_ll, allow_skip_whitechars); + + if( was_overflow_ll || val > static_cast(std::numeric_limits::max()) ) + { + SetOverflow(was_overflow, true); + return 0; + } + + return static_cast(val); +} + + +template +unsigned long Toul_b(const CharType * str, const CharType ** after_str = 0, bool * was_overflow = 0, bool allow_skip_whitechars = true) +{ + return ToUnsignedIntegerType_b(str, after_str, was_overflow, allow_skip_whitechars); +} + +template +unsigned int Toui_b(const CharType * str, const CharType ** after_str = 0, bool * was_overflow = 0, bool allow_skip_whitechars = true) +{ + return ToUnsignedIntegerType_b(str, after_str, was_overflow, allow_skip_whitechars); +} + + + + + +template +IntegerType ToIntegerType_b(const CharType * str, const CharType ** after_str = 0, bool * was_overflow = 0, bool allow_skip_whitechars = true) +{ + bool was_overflow_ll = false; + + SetOverflow(was_overflow, false); + long long val = Toll_b(str, after_str, &was_overflow_ll, allow_skip_whitechars); + + if( was_overflow_ll || + val < static_cast(std::numeric_limits::min()) || + val > static_cast(std::numeric_limits::max()) ) + { + SetOverflow(was_overflow, true); + return 0; + } + + return static_cast(val); +} + + + +template +long Tol_b(const CharType * str, const CharType ** after_str = 0, bool * was_overflow = 0, bool allow_skip_whitechars = true) +{ + return ToIntegerType_b(str, after_str, was_overflow, allow_skip_whitechars); +} + +template +int Toi_b(const CharType * str, const CharType ** after_str = 0, bool * was_overflow = 0, bool allow_skip_whitechars = true) +{ + return ToIntegerType_b(str, after_str, was_overflow, allow_skip_whitechars); +} + + } diff --git a/convert/text.h b/convert/text.h index 09dec29..49f64f8 100644 --- a/convert/text.h +++ b/convert/text.h @@ -61,6 +61,38 @@ CharType * SkipWhite(CharType * str, bool check_additional_chars = true, bool tr } +/* + * + * str_end is pointing at the end of the string (the last item + one) + * + * return value is a pointer to the first white character after a non-white character at the end + * or to the last+one if there is no any white characters + * + */ +template +CharType * SkipWhiteFromBack(CharType * str_begin, CharType * str_end, bool check_additional_chars = true, bool treat_new_line_as_white = true) +{ + while( str_end > str_begin && IsWhite(static_cast(*(str_end-1)), check_additional_chars, treat_new_line_as_white) ) + { + str_end -= 1; + } + + return str_end; +} + + +template +CharType * SkipWhiteFromBack(CharType * str, bool check_additional_chars = true, bool treat_new_line_as_white = true) +{ + CharType * str_begin = str; + + while( *str != 0 ) + { + str += 1; + } + + return SkipWhiteFromBack(str_begin, str, check_additional_chars, treat_new_line_as_white); +} } diff --git a/space/space.cpp b/space/space.cpp index c4cb6d9..d1a6099 100644 --- a/space/space.cpp +++ b/space/space.cpp @@ -50,7 +50,7 @@ namespace PT Space::Space() { - parent = 0; + parent = nullptr; } @@ -116,7 +116,7 @@ Space::Value * Space::GetValue(const std::wstring & name) if( t == table.end() ) { - return 0; + return nullptr; } else { @@ -138,7 +138,7 @@ const Space::Value * Space::GetValue(const std::wstring & name) const if( t == table.cend() ) { - return 0; + return nullptr; } else { @@ -164,7 +164,7 @@ std::wstring * Space::GetFirstValue(const std::wstring & name) if( t == table.end() || t->second.empty() ) { - return 0; + return nullptr; } else { @@ -187,7 +187,7 @@ const std::wstring * Space::GetFirstValue(const std::wstring & name) const if( t == table.end() || t->second.empty() ) { - return 0; + return nullptr; } else { @@ -403,72 +403,36 @@ std::string Space::TextA(const std::wstring & name, const std::wstring & def) co -int Space::CheckIntegerBase(const std::wstring & value, const wchar_t ** save_ptr) -{ - const wchar_t * ptr = SkipWhite(value.c_str()); - int base = 10; - - if( *ptr == '0' ) - { - base = 8; - ptr += 1; // we can skip the first zero - } - else - if( *ptr == '-' && *(ptr+1) == '0' ) - { - base = 8; - // ptr is pointing to '-', do not increment it here - } - - *save_ptr = ptr; - return base; -} - - - - unsigned int Space::ToUInt(const std::wstring & value) { - const wchar_t * ptr; - int base = CheckIntegerBase(value, &ptr); - return Toui(ptr, base); + return Toui_b(value.c_str()); } int Space::ToInt(const std::wstring & value) { - const wchar_t * ptr; - int base = CheckIntegerBase(value, &ptr); - return Toi(ptr, base); + return Toi_b(value.c_str()); } unsigned long Space::ToULong(const std::wstring & value) { - const wchar_t * ptr; - int base = CheckIntegerBase(value, &ptr); - return Toul(ptr, base); + return Toul_b(value.c_str()); } long Space::ToLong(const std::wstring & value) { - const wchar_t * ptr; - int base = CheckIntegerBase(value, &ptr); - return Tol(ptr, base); + return Tol_b(value.c_str()); } unsigned long long Space::ToULongLong(const std::wstring & value) { - const wchar_t * ptr; - int base = CheckIntegerBase(value, &ptr); - return Toull(ptr, base); + return Toull_b(value.c_str()); } long long Space::ToLongLong(const std::wstring & value) { - const wchar_t * ptr; - int base = CheckIntegerBase(value, &ptr); - return Toll(ptr, base); + return Toll_b(value.c_str()); } @@ -486,10 +450,12 @@ size_t Space::ToSize(const std::wstring & value) bool Space::ToBool(const std::wstring & value) { - // IMPROVE ME add support for trimming white chars? - return (EqualNoCase(value.c_str(), L"true") || - EqualNoCase(value.c_str(), L"yes") || - EqualNoCase(value.c_str(), L"1") + const wchar_t * str_begin = SkipWhite(value.c_str()); + const wchar_t * str_end = SkipWhiteFromBack(str_begin); + + return (EqualNoCase(str_begin, str_end, L"true") || + EqualNoCase(str_begin, str_end, L"yes") || + EqualNoCase(str_begin, str_end, L"1") ); } @@ -498,7 +464,7 @@ bool Space::ToBool(const std::wstring & value) -int Space::Int(const wchar_t * name, int def) +int Space::Int(const wchar_t * name, int def) const { tmp_name = name; return Int(tmp_name, def); @@ -507,9 +473,9 @@ int Space::Int(const wchar_t * name, int def) -int Space::Int(const std::wstring & name, int def) +int Space::Int(const std::wstring & name, int def) const { - std::wstring * value = GetFirstValue(name); + const std::wstring * value = GetFirstValue(name); if( value ) return ToInt(*value); @@ -519,16 +485,16 @@ return def; -unsigned int Space::UInt(const wchar_t * name, unsigned int def) +unsigned int Space::UInt(const wchar_t * name, unsigned int def) const { tmp_name = name; return UInt(tmp_name, def); } -unsigned int Space::UInt(const std::wstring & name, unsigned int def) +unsigned int Space::UInt(const std::wstring & name, unsigned int def) const { - std::wstring * value = GetFirstValue(name); + const std::wstring * value = GetFirstValue(name); if( value ) return ToUInt(*value); @@ -540,16 +506,16 @@ return def; -long Space::Long(const wchar_t * name, long def) +long Space::Long(const wchar_t * name, long def) const { tmp_name = name; return Long(tmp_name, def); } -long Space::Long(const std::wstring & name, long def) +long Space::Long(const std::wstring & name, long def) const { - std::wstring * value = GetFirstValue(name); + const std::wstring * value = GetFirstValue(name); if( value ) return ToLong(*value); @@ -558,16 +524,16 @@ return def; } -unsigned long Space::ULong(const wchar_t * name, unsigned long def) +unsigned long Space::ULong(const wchar_t * name, unsigned long def) const { tmp_name = name; return ULong(tmp_name, def); } -unsigned long Space::ULong(const std::wstring & name, unsigned long def) +unsigned long Space::ULong(const std::wstring & name, unsigned long def) const { - std::wstring * value = GetFirstValue(name); + const std::wstring * value = GetFirstValue(name); if( value ) return ToULong(*value); @@ -577,15 +543,15 @@ return def; -long long Space::LongLong(const wchar_t * name, long long def) +long long Space::LongLong(const wchar_t * name, long long def) const { tmp_name = name; return LongLong(tmp_name, def); } -long long Space::LongLong(const std::wstring & name, long long def) +long long Space::LongLong(const std::wstring & name, long long def) const { - std::wstring * value = GetFirstValue(name); + const std::wstring * value = GetFirstValue(name); if( value ) return ToLongLong(*value); @@ -593,15 +559,15 @@ long long Space::LongLong(const std::wstring & name, long long def) return def; } -unsigned long long Space::ULongLong(const wchar_t * name, unsigned long long def) +unsigned long long Space::ULongLong(const wchar_t * name, unsigned long long def) const { tmp_name = name; return ULongLong(tmp_name, def); } -unsigned long long Space::ULongLong(const std::wstring & name, unsigned long long def) +unsigned long long Space::ULongLong(const std::wstring & name, unsigned long long def) const { - std::wstring * value = GetFirstValue(name); + const std::wstring * value = GetFirstValue(name); if( value ) return ToULongLong(*value); @@ -613,16 +579,16 @@ return def; -size_t Space::Size(const wchar_t * name, size_t def) +size_t Space::Size(const wchar_t * name, size_t def) const { tmp_name = name; return Size(tmp_name, def); } -size_t Space::Size(const std::wstring & name, size_t def) +size_t Space::Size(const std::wstring & name, size_t def) const { - std::wstring * value = GetFirstValue(name); + const std::wstring * value = GetFirstValue(name); if( value ) return ToSize(*value); @@ -633,7 +599,7 @@ return def; -bool Space::Bool(const wchar_t * name, bool def) +bool Space::Bool(const wchar_t * name, bool def) const { tmp_name = name; return Bool(tmp_name, def); @@ -641,9 +607,9 @@ bool Space::Bool(const wchar_t * name, bool def) -bool Space::Bool(const std::wstring & name, bool def) +bool Space::Bool(const std::wstring & name, bool def) const { - std::wstring * value = GetFirstValue(name); + const std::wstring * value = GetFirstValue(name); if( value ) return ToBool(*value); @@ -928,7 +894,7 @@ Space * Space::FindSpace(const wchar_t * name) return spaces[i]; } -return 0; +return nullptr; } @@ -940,7 +906,7 @@ Space * Space::FindSpace(const std::wstring & name) return spaces[i]; } -return 0; +return nullptr; } @@ -1042,6 +1008,8 @@ return c; } +// IMPROVE ME +// move me to a better place bool Space::EqualNoCase(const wchar_t * str1, const wchar_t * str2) { while( *str1 && *str2 && ToSmall(*str1) == ToSmall(*str2) ) @@ -1057,6 +1025,29 @@ return false; } +/* + * + * the first string is trimmed + * str1_end is pointing one character after the last valid character + * + */ +// IMPROVE ME +// move me to a better place +bool Space::EqualNoCase(const wchar_t * str1_begin, const wchar_t * str1_end, const wchar_t * str2) +{ + while( str1_begin < str1_end && *str2 && ToSmall(*str1_begin) == ToSmall(*str2) ) + { + ++str1_begin; + ++str2; + } + + if( str1_begin == str1_end && *str2 == 0 ) + return true; + +return false; +} + + /* those white characters here should be the same as in spaceparser.cpp */ diff --git a/space/space.h b/space/space.h index 6f6dc0d..07e3dfc 100644 --- a/space/space.h +++ b/space/space.h @@ -206,7 +206,12 @@ public: * */ - // moze tu powinno być FindValue? + /* + * + * their working in O(log) + * can return a null pointer + * + */ Value * GetValue(const wchar_t * name); Value * GetValue(const std::wstring & name); @@ -214,7 +219,6 @@ public: const Value * GetValue(const std::wstring & name) const; - // moze tu powinno być FindFirstValue? // they can return a null pointer if there is not such a 'name' std::wstring * GetFirstValue(const wchar_t * name); std::wstring * GetFirstValue(const std::wstring & name); @@ -260,26 +264,26 @@ public: - int Int(const wchar_t * name, int def = 0); - int Int(const std::wstring & name, int def = 0); - unsigned int UInt(const wchar_t * name, unsigned int def = 0); - unsigned int UInt(const std::wstring & name, unsigned int def = 0); + int Int(const wchar_t * name, int def = 0) const; + int Int(const std::wstring & name, int def = 0) const; + unsigned int UInt(const wchar_t * name, unsigned int def = 0) const; + unsigned int UInt(const std::wstring & name, unsigned int def = 0) const; - long Long(const wchar_t * name, long def = 0); - long Long(const std::wstring & name, long def = 0); - unsigned long ULong(const wchar_t * name, unsigned long def = 0); - unsigned long ULong(const std::wstring & name, unsigned long def = 0); + long Long(const wchar_t * name, long def = 0) const; + long Long(const std::wstring & name, long def = 0) const; + unsigned long ULong(const wchar_t * name, unsigned long def = 0) const; + unsigned long ULong(const std::wstring & name, unsigned long def = 0) const; - long long LongLong(const wchar_t * name, long long def = 0); - long long LongLong(const std::wstring & name, long long def = 0); - unsigned long long ULongLong(const wchar_t * name, unsigned long long def = 0); - unsigned long long ULongLong(const std::wstring & name, unsigned long long def = 0); + long long LongLong(const wchar_t * name, long long def = 0) const; + long long LongLong(const std::wstring & name, long long def = 0) const; + unsigned long long ULongLong(const wchar_t * name, unsigned long long def = 0) const; + unsigned long long ULongLong(const std::wstring & name, unsigned long long def = 0) const; - size_t Size(const wchar_t * name, size_t def = 0); - size_t Size(const std::wstring & name, size_t def = 0); + size_t Size(const wchar_t * name, size_t def = 0) const; + size_t Size(const std::wstring & name, size_t def = 0) const; - bool Bool(const wchar_t * name, bool def = false); - bool Bool(const std::wstring & name, bool def = false); + bool Bool(const wchar_t * name, bool def = false) const; + bool Bool(const std::wstring & name, bool def = false) const; @@ -393,21 +397,20 @@ private: std::wstring tmp_value_text; std::string tmp_value_text_ascii; - int CheckIntegerBase(const std::wstring & value, const wchar_t ** save_ptr); + static unsigned int ToUInt(const std::wstring & value); + static int ToInt(const std::wstring & value); + static unsigned long ToULong(const std::wstring & value); + static long ToLong(const std::wstring & value); + static unsigned long long ToULongLong(const std::wstring & value); + static long long ToLongLong(const std::wstring & value); + static size_t ToSize(const std::wstring & value); + static bool ToBool(const std::wstring & value); - unsigned int ToUInt(const std::wstring & value); - int ToInt(const std::wstring & value); - unsigned long ToULong(const std::wstring & value); - long ToLong(const std::wstring & value); - unsigned long long ToULongLong(const std::wstring & value); - long long ToLongLong(const std::wstring & value); - size_t ToSize(const std::wstring & value); - bool ToBool(const std::wstring & value); - - wchar_t ToSmall(wchar_t c); - bool EqualNoCase(const wchar_t * str1, const wchar_t * str2); - static bool IsWhite(int c); - static bool HasWhite(const std::wstring & str); + static wchar_t ToSmall(wchar_t c); + static bool EqualNoCase(const wchar_t * str1, const wchar_t * str2); + static bool EqualNoCase(const wchar_t * str1_begin, const wchar_t * str1_end, const wchar_t * str2); + static bool IsWhite(int c); + static bool HasWhite(const std::wstring & str); }; @@ -459,6 +462,8 @@ void Space::PrintKey(Stream & out, const std::wstring & str) { bool use_quote = false; + // CHECK ME + // HasWhite doesn't take a new line into account, is it correct to use it here? if( str.empty() || HasWhite(str) ) use_quote = true;