diff options
Diffstat (limited to 'zen/string_traits.h')
-rwxr-xr-x[-rw-r--r--] | 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 f17e5e0d..5ae5733c 100644..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
|