diff options
Diffstat (limited to 'zen/string_traits.h')
-rwxr-xr-x | zen/string_traits.h | 432 |
1 files changed, 216 insertions, 216 deletions
diff --git a/zen/string_traits.h b/zen/string_traits.h index 5ae5733c..f17e5e0d 100755 --- 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 <cstring> //strlen
-#include "type_tools.h"
-
-
-//uniform access to string-like types, both classes and character arrays
-namespace zen
-{
-/*
-IsStringLike<>::value:
- IsStringLike<const wchar_t*>::value; //equals "true"
- IsStringLike<const int*> ::value; //equals "false"
-
-GetCharType<>::Type:
- GetCharType<std::wstring>::Type //equals wchar_t
- GetCharType<wchar_t[5]> ::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 Char>
-class StringRef
-{
-public:
- template <class Iterator>
- 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<class S, class Char> //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<S>().c_str())) == sizeof(Yes) };
-};
-
-
-template <class S, bool isStringClass> struct GetCharTypeImpl : ResultType<NullType> {};
-
-template <class S>
-struct GetCharTypeImpl<S, true> :
- ResultType<
- typename SelectIf<HasConversion<S, wchar_t>::value, wchar_t,
- typename SelectIf<HasConversion<S, char >::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<char, false> : ResultType<char > {};
-template <> struct GetCharTypeImpl<wchar_t, false> : ResultType<wchar_t> {};
-
-template <> struct GetCharTypeImpl<StringRef<char >, false> : ResultType<char > {};
-template <> struct GetCharTypeImpl<StringRef<wchar_t >, false> : ResultType<wchar_t> {};
-template <> struct GetCharTypeImpl<StringRef<const char >, false> : ResultType<char > {};
-template <> struct GetCharTypeImpl<StringRef<const wchar_t>, false> : ResultType<wchar_t> {};
-
-
-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 S>
-class StringTraits
-{
- using NonRefType = typename RemoveRef <S >::Type;
- using NonConstType = typename RemoveConst <NonRefType >::Type;
- using NonArrayType = typename RemoveArray <NonConstType>::Type;
- using NonPtrType = typename RemovePointer<NonArrayType>::Type;
- using UndecoratedType = typename RemoveConst <NonPtrType >::Type ; //handle "const char* const"
-
-public:
- enum
- {
- isStringClass = HasMemberType_value_type<NonConstType>::value &&
- HasMember_c_str <NonConstType>::value &&
- HasMember_length <NonConstType>::value
- };
-
- using CharType = typename GetCharTypeImpl<UndecoratedType, isStringClass>::Type;
-
- enum
- {
- isStringLike = IsSameType<CharType, char>::value ||
- IsSameType<CharType, wchar_t>::value
- };
-};
-}
-
-template <class T>
-struct IsStringLike : StaticBool<implementation::StringTraits<T>::isStringLike> {};
-
-template <class T>
-struct GetCharType : ResultType<typename implementation::StringTraits<T>::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 <class C> inline
-size_t cStringLength(const C* str)
-{
- static_assert(IsSameType<C, char>::value || IsSameType<C, wchar_t>::value, "");
- size_t len = 0;
- while (*str++ != 0)
- ++len;
- return len;
-}
-#endif
-
-template <class S, typename = typename EnableIf<implementation::StringTraits<S>::isStringClass>::Type> inline
-const typename GetCharType<S>::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<char >& ref) { return ref.data(); }
-inline const wchar_t* strBegin(const StringRef<wchar_t >& ref) { return ref.data(); }
-inline const char* strBegin(const StringRef<const char >& ref) { return ref.data(); }
-inline const wchar_t* strBegin(const StringRef<const wchar_t>& ref) { return ref.data(); }
-
-
-template <class S, typename = typename EnableIf<implementation::StringTraits<S>::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<char >& ref) { return ref.length(); }
-inline size_t strLength(const StringRef<wchar_t >& ref) { return ref.length(); }
-inline size_t strLength(const StringRef<const char >& ref) { return ref.length(); }
-inline size_t strLength(const StringRef<const wchar_t>& ref) { return ref.length(); }
-}
-
-
-template <class S> inline
-auto strBegin(S&& str) -> const typename GetCharType<S>::Type*
-{
- static_assert(IsStringLike<S>::value, "");
- return implementation::strBegin(std::forward<S>(str));
-}
-
-
-template <class S> inline
-size_t strLength(S&& str)
-{
- static_assert(IsStringLike<S>::value, "");
- return implementation::strLength(std::forward<S>(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 <cstring> //strlen +#include "type_tools.h" + + +//uniform access to string-like types, both classes and character arrays +namespace zen +{ +/* +IsStringLike<>::value: + IsStringLike<const wchar_t*>::value; //equals "true" + IsStringLike<const int*> ::value; //equals "false" + +GetCharType<>::Type: + GetCharType<std::wstring>::Type //equals wchar_t + GetCharType<wchar_t[5]> ::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 Char> +class StringRef +{ +public: + template <class Iterator> + 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<class S, class Char> //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<S>().c_str())) == sizeof(Yes) }; +}; + + +template <class S, bool isStringClass> struct GetCharTypeImpl : ResultType<NullType> {}; + +template <class S> +struct GetCharTypeImpl<S, true> : + ResultType< + typename SelectIf<HasConversion<S, wchar_t>::value, wchar_t, + typename SelectIf<HasConversion<S, char >::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<char, false> : ResultType<char > {}; +template <> struct GetCharTypeImpl<wchar_t, false> : ResultType<wchar_t> {}; + +template <> struct GetCharTypeImpl<StringRef<char >, false> : ResultType<char > {}; +template <> struct GetCharTypeImpl<StringRef<wchar_t >, false> : ResultType<wchar_t> {}; +template <> struct GetCharTypeImpl<StringRef<const char >, false> : ResultType<char > {}; +template <> struct GetCharTypeImpl<StringRef<const wchar_t>, false> : ResultType<wchar_t> {}; + + +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 S> +class StringTraits +{ + using NonRefType = typename RemoveRef <S >::Type; + using NonConstType = typename RemoveConst <NonRefType >::Type; + using NonArrayType = typename RemoveArray <NonConstType>::Type; + using NonPtrType = typename RemovePointer<NonArrayType>::Type; + using UndecoratedType = typename RemoveConst <NonPtrType >::Type ; //handle "const char* const" + +public: + enum + { + isStringClass = HasMemberType_value_type<NonConstType>::value && + HasMember_c_str <NonConstType>::value && + HasMember_length <NonConstType>::value + }; + + using CharType = typename GetCharTypeImpl<UndecoratedType, isStringClass>::Type; + + enum + { + isStringLike = IsSameType<CharType, char>::value || + IsSameType<CharType, wchar_t>::value + }; +}; +} + +template <class T> +struct IsStringLike : StaticBool<implementation::StringTraits<T>::isStringLike> {}; + +template <class T> +struct GetCharType : ResultType<typename implementation::StringTraits<T>::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 <class C> inline +size_t cStringLength(const C* str) +{ + static_assert(IsSameType<C, char>::value || IsSameType<C, wchar_t>::value, ""); + size_t len = 0; + while (*str++ != 0) + ++len; + return len; +} +#endif + +template <class S, typename = typename EnableIf<implementation::StringTraits<S>::isStringClass>::Type> inline +const typename GetCharType<S>::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<char >& ref) { return ref.data(); } +inline const wchar_t* strBegin(const StringRef<wchar_t >& ref) { return ref.data(); } +inline const char* strBegin(const StringRef<const char >& ref) { return ref.data(); } +inline const wchar_t* strBegin(const StringRef<const wchar_t>& ref) { return ref.data(); } + + +template <class S, typename = typename EnableIf<implementation::StringTraits<S>::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<char >& ref) { return ref.length(); } +inline size_t strLength(const StringRef<wchar_t >& ref) { return ref.length(); } +inline size_t strLength(const StringRef<const char >& ref) { return ref.length(); } +inline size_t strLength(const StringRef<const wchar_t>& ref) { return ref.length(); } +} + + +template <class S> inline +auto strBegin(S&& str) -> const typename GetCharType<S>::Type* +{ + static_assert(IsStringLike<S>::value, ""); + return implementation::strBegin(std::forward<S>(str)); +} + + +template <class S> inline +size_t strLength(S&& str) +{ + static_assert(IsStringLike<S>::value, ""); + return implementation::strLength(std::forward<S>(str)); +} +} + +#endif //STRING_TRAITS_H_813274321443234 |