From 9d071d2a2cec9a7662a02669488569a017f0ea35 Mon Sep 17 00:00:00 2001 From: Daniel Wilhelm Date: Mon, 13 Feb 2017 21:25:04 -0700 Subject: 8.9 --- zen/string_traits.h | 432 ++++++++++++++++++++++++++-------------------------- 1 file changed, 216 insertions(+), 216 deletions(-) mode change 100644 => 100755 zen/string_traits.h (limited to 'zen/string_traits.h') diff --git a/zen/string_traits.h b/zen/string_traits.h old mode 100644 new mode 100755 index f17e5e0d..5ae5733c --- a/zen/string_traits.h +++ b/zen/string_traits.h @@ -1,216 +1,216 @@ -// ***************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 * -// * Copyright (C) Zenju (zenju AT freefilesync DOT org) - All Rights Reserved * -// ***************************************************************************** - -#ifndef STRING_TRAITS_H_813274321443234 -#define STRING_TRAITS_H_813274321443234 - -#include //strlen -#include "type_tools.h" - - -//uniform access to string-like types, both classes and character arrays -namespace zen -{ -/* -IsStringLike<>::value: - IsStringLike::value; //equals "true" - IsStringLike ::value; //equals "false" - -GetCharType<>::Type: - GetCharType::Type //equals wchar_t - GetCharType ::Type //equals wchar_t - -strLength(): - strLength(str); //equals str.length() - strLength(array); //equals cStringLength(array) - -strBegin(): -> not null-terminated! -> may be nullptr if length is 0! - std::wstring str(L"dummy"); - char array[] = "dummy"; - strBegin(str); //returns str.c_str() - strBegin(array); //returns array -*/ - -//reference a sub-string for consumption by zen string_tools -template -class StringRef -{ -public: - template - StringRef(Iterator first, Iterator last) : len_(last - first), str_(first != last ? &*first : nullptr) {} - //StringRef(const Char* str, size_t len) : str_(str), len_(len) {} -> needless constraint! Char* not available for empty range! - - Char* data () const { return str_; } //1. no null-termination! 2. may be nullptr! - size_t length() const { return len_; } - -private: - const size_t len_; - Char* str_; -}; - - - - - - - - - - - - -//---------------------- implementation ---------------------- -namespace implementation -{ -template //test if result of S::c_str() can convert to const Char* -class HasConversion -{ - using Yes = char[1]; - using No = char[2]; - - static Yes& hasConversion(const Char*); - static No& hasConversion(...); - -public: - enum { value = sizeof(hasConversion(std::declval().c_str())) == sizeof(Yes) }; -}; - - -template struct GetCharTypeImpl : ResultType {}; - -template -struct GetCharTypeImpl : - ResultType< - typename SelectIf::value, wchar_t, - typename SelectIf::value, char, NullType>::Type - >::Type> -{ - //using Type = typename S::value_type; - /*DON'T use S::value_type: - 1. support Glib::ustring: value_type is "unsigned int" but c_str() returns "const char*" - 2. wxString, wxWidgets v2.9, has some questionable string design: wxString::c_str() returns a proxy (wxCStrData) which - is implicitly convertible to *both* "const char*" and "const wchar_t*" while wxString::value_type is a wrapper around an unsigned int - */ -}; - -template <> struct GetCharTypeImpl : ResultType {}; -template <> struct GetCharTypeImpl : ResultType {}; - -template <> struct GetCharTypeImpl, false> : ResultType {}; -template <> struct GetCharTypeImpl, false> : ResultType {}; -template <> struct GetCharTypeImpl, false> : ResultType {}; -template <> struct GetCharTypeImpl, false> : ResultType {}; - - -ZEN_INIT_DETECT_MEMBER_TYPE(value_type); -ZEN_INIT_DETECT_MEMBER(c_str); //we don't know the exact declaration of the member attribute and it may be in a base class! -ZEN_INIT_DETECT_MEMBER(length); // - -template -class StringTraits -{ - using NonRefType = typename RemoveRef ::Type; - using NonConstType = typename RemoveConst ::Type; - using NonArrayType = typename RemoveArray ::Type; - using NonPtrType = typename RemovePointer::Type; - using UndecoratedType = typename RemoveConst ::Type ; //handle "const char* const" - -public: - enum - { - isStringClass = HasMemberType_value_type::value && - HasMember_c_str ::value && - HasMember_length ::value - }; - - using CharType = typename GetCharTypeImpl::Type; - - enum - { - isStringLike = IsSameType::value || - IsSameType::value - }; -}; -} - -template -struct IsStringLike : StaticBool::isStringLike> {}; - -template -struct GetCharType : ResultType::CharType> {}; - - -namespace implementation -{ -//strlen/wcslen are vectorized since VS14 CTP3 -inline size_t cStringLength(const char* str) { return std::strlen(str); } -inline size_t cStringLength(const wchar_t* str) { return std::wcslen(str); } - -//no significant perf difference for "comparison" test case between cStringLength/wcslen: -#if 0 -template inline -size_t cStringLength(const C* str) -{ - static_assert(IsSameType::value || IsSameType::value, ""); - size_t len = 0; - while (*str++ != 0) - ++len; - return len; -} -#endif - -template ::isStringClass>::Type> inline -const typename GetCharType::Type* strBegin(const S& str) //SFINAE: T must be a "string" -{ - return str.c_str(); -} - -inline const char* strBegin(const char* str) { return str; } -inline const wchar_t* strBegin(const wchar_t* str) { return str; } -inline const char* strBegin(const char& ch) { return &ch; } -inline const wchar_t* strBegin(const wchar_t& ch) { return &ch; } - -inline const char* strBegin(const StringRef& ref) { return ref.data(); } -inline const wchar_t* strBegin(const StringRef& ref) { return ref.data(); } -inline const char* strBegin(const StringRef& ref) { return ref.data(); } -inline const wchar_t* strBegin(const StringRef& ref) { return ref.data(); } - - -template ::isStringClass>::Type> inline -size_t strLength(const S& str) //SFINAE: T must be a "string" -{ - return str.length(); -} - -inline size_t strLength(const char* str) { return cStringLength(str); } -inline size_t strLength(const wchar_t* str) { return cStringLength(str); } -inline size_t strLength(char) { return 1; } -inline size_t strLength(wchar_t) { return 1; } - -inline size_t strLength(const StringRef& ref) { return ref.length(); } -inline size_t strLength(const StringRef& ref) { return ref.length(); } -inline size_t strLength(const StringRef& ref) { return ref.length(); } -inline size_t strLength(const StringRef& ref) { return ref.length(); } -} - - -template inline -auto strBegin(S&& str) -> const typename GetCharType::Type* -{ - static_assert(IsStringLike::value, ""); - return implementation::strBegin(std::forward(str)); -} - - -template inline -size_t strLength(S&& str) -{ - static_assert(IsStringLike::value, ""); - return implementation::strLength(std::forward(str)); -} -} - -#endif //STRING_TRAITS_H_813274321443234 +// ***************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 * +// * Copyright (C) Zenju (zenju AT freefilesync DOT org) - All Rights Reserved * +// ***************************************************************************** + +#ifndef STRING_TRAITS_H_813274321443234 +#define STRING_TRAITS_H_813274321443234 + +#include //strlen +#include "type_tools.h" + + +//uniform access to string-like types, both classes and character arrays +namespace zen +{ +/* +IsStringLike<>::value: + IsStringLike::value; //equals "true" + IsStringLike ::value; //equals "false" + +GetCharType<>::Type: + GetCharType::Type //equals wchar_t + GetCharType ::Type //equals wchar_t + +strLength(): + strLength(str); //equals str.length() + strLength(array); //equals cStringLength(array) + +strBegin(): -> not null-terminated! -> may be nullptr if length is 0! + std::wstring str(L"dummy"); + char array[] = "dummy"; + strBegin(str); //returns str.c_str() + strBegin(array); //returns array +*/ + +//reference a sub-string for consumption by zen string_tools +template +class StringRef +{ +public: + template + StringRef(Iterator first, Iterator last) : len_(last - first), str_(first != last ? &*first : nullptr) {} + //StringRef(const Char* str, size_t len) : str_(str), len_(len) {} -> needless constraint! Char* not available for empty range! + + Char* data () const { return str_; } //1. no null-termination! 2. may be nullptr! + size_t length() const { return len_; } + +private: + const size_t len_; + Char* str_; +}; + + + + + + + + + + + + +//---------------------- implementation ---------------------- +namespace implementation +{ +template //test if result of S::c_str() can convert to const Char* +class HasConversion +{ + using Yes = char[1]; + using No = char[2]; + + static Yes& hasConversion(const Char*); + static No& hasConversion(...); + +public: + enum { value = sizeof(hasConversion(std::declval().c_str())) == sizeof(Yes) }; +}; + + +template struct GetCharTypeImpl : ResultType {}; + +template +struct GetCharTypeImpl : + ResultType< + typename SelectIf::value, wchar_t, + typename SelectIf::value, char, NullType>::Type + >::Type> +{ + //using Type = typename S::value_type; + /*DON'T use S::value_type: + 1. support Glib::ustring: value_type is "unsigned int" but c_str() returns "const char*" + 2. wxString, wxWidgets v2.9, has some questionable string design: wxString::c_str() returns a proxy (wxCStrData) which + is implicitly convertible to *both* "const char*" and "const wchar_t*" while wxString::value_type is a wrapper around an unsigned int + */ +}; + +template <> struct GetCharTypeImpl : ResultType {}; +template <> struct GetCharTypeImpl : ResultType {}; + +template <> struct GetCharTypeImpl, false> : ResultType {}; +template <> struct GetCharTypeImpl, false> : ResultType {}; +template <> struct GetCharTypeImpl, false> : ResultType {}; +template <> struct GetCharTypeImpl, false> : ResultType {}; + + +ZEN_INIT_DETECT_MEMBER_TYPE(value_type); +ZEN_INIT_DETECT_MEMBER(c_str); //we don't know the exact declaration of the member attribute and it may be in a base class! +ZEN_INIT_DETECT_MEMBER(length); // + +template +class StringTraits +{ + using NonRefType = typename RemoveRef ::Type; + using NonConstType = typename RemoveConst ::Type; + using NonArrayType = typename RemoveArray ::Type; + using NonPtrType = typename RemovePointer::Type; + using UndecoratedType = typename RemoveConst ::Type ; //handle "const char* const" + +public: + enum + { + isStringClass = HasMemberType_value_type::value && + HasMember_c_str ::value && + HasMember_length ::value + }; + + using CharType = typename GetCharTypeImpl::Type; + + enum + { + isStringLike = IsSameType::value || + IsSameType::value + }; +}; +} + +template +struct IsStringLike : StaticBool::isStringLike> {}; + +template +struct GetCharType : ResultType::CharType> {}; + + +namespace implementation +{ +//strlen/wcslen are vectorized since VS14 CTP3 +inline size_t cStringLength(const char* str) { return std::strlen(str); } +inline size_t cStringLength(const wchar_t* str) { return std::wcslen(str); } + +//no significant perf difference for "comparison" test case between cStringLength/wcslen: +#if 0 +template inline +size_t cStringLength(const C* str) +{ + static_assert(IsSameType::value || IsSameType::value, ""); + size_t len = 0; + while (*str++ != 0) + ++len; + return len; +} +#endif + +template ::isStringClass>::Type> inline +const typename GetCharType::Type* strBegin(const S& str) //SFINAE: T must be a "string" +{ + return str.c_str(); +} + +inline const char* strBegin(const char* str) { return str; } +inline const wchar_t* strBegin(const wchar_t* str) { return str; } +inline const char* strBegin(const char& ch) { return &ch; } +inline const wchar_t* strBegin(const wchar_t& ch) { return &ch; } + +inline const char* strBegin(const StringRef& ref) { return ref.data(); } +inline const wchar_t* strBegin(const StringRef& ref) { return ref.data(); } +inline const char* strBegin(const StringRef& ref) { return ref.data(); } +inline const wchar_t* strBegin(const StringRef& ref) { return ref.data(); } + + +template ::isStringClass>::Type> inline +size_t strLength(const S& str) //SFINAE: T must be a "string" +{ + return str.length(); +} + +inline size_t strLength(const char* str) { return cStringLength(str); } +inline size_t strLength(const wchar_t* str) { return cStringLength(str); } +inline size_t strLength(char) { return 1; } +inline size_t strLength(wchar_t) { return 1; } + +inline size_t strLength(const StringRef& ref) { return ref.length(); } +inline size_t strLength(const StringRef& ref) { return ref.length(); } +inline size_t strLength(const StringRef& ref) { return ref.length(); } +inline size_t strLength(const StringRef& ref) { return ref.length(); } +} + + +template inline +auto strBegin(S&& str) -> const typename GetCharType::Type* +{ + static_assert(IsStringLike::value, ""); + return implementation::strBegin(std::forward(str)); +} + + +template inline +size_t strLength(S&& str) +{ + static_assert(IsStringLike::value, ""); + return implementation::strLength(std::forward(str)); +} +} + +#endif //STRING_TRAITS_H_813274321443234 -- cgit