// ************************************************************************** // * This file is part of the zenXML project. It is distributed under the * // * Boost Software License, Version 1.0. See accompanying file * // * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt. * // * Copyright (C) 2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** #ifndef STRING_TRAITS_HEADER_813274321443234 #define STRING_TRAITS_HEADER_813274321443234 #include "type_tools.h" #include "assert_static.h" //uniform access to string-like types: classes and character arrays namespace zen { /* strBegin(): std::wstring str(L"dummy"); char array[] = "dummy"; const wchar_t* iter = strBegin(str); //returns str.c_str() const char* iter2 = strBegin(array); //returns array strLength(): strLength(str); //equals str.size() strLength(array); //equals cStringLength(array) StringTraits<>::CharType: StringTraits::CharType //equals wchar_t StringTraits ::CharType //equals wchar_t StringTraits<>::isStringLike: StringTraits::isStringLike; //equals "true" StringTraits ::isStringLike; //equals "false" StringTraits<>::isStringClass: StringTraits::isStringClass //equals "true" StringTraits ::isStringClass //equals "false" */ //---------------------- implementation ---------------------- namespace implementation { template class HasValueTypedef { typedef char Yes[1]; typedef char No [2]; template class HelperTp {}; //detect presence of a member type called value_type template static Yes& hasMemberValueType(HelperTp*); template static No& hasMemberValueType(...); public: enum { result = sizeof(hasMemberValueType(NULL)) == sizeof(Yes) }; }; template class HasStringMembers { public: enum { result = false }; }; template class HasStringMembers { typedef char Yes[1]; typedef char No [2]; //detect presence of member functions (without specific restriction on return type, within T or one of it's base classes) template class HelperFn {}; struct Fallback { int c_str; int length; }; template struct Helper2 : public U, public Fallback {}; //U must be a class-type! //we don't know the exact declaration of the member attribute (may be in base class), but we know what NOT to expect: template static No& hasMemberCstr(HelperFn::c_str>*); template static Yes& hasMemberCstr(...); template static No& hasMemberLength(HelperFn::length>*); template static Yes& hasMemberLength(...); public: enum { result = sizeof(hasMemberCstr (NULL)) == sizeof(Yes) && sizeof(hasMemberLength(NULL)) == sizeof(Yes) }; }; template struct StringTraits2 { typedef EmptyType Result; }; //"StringTraits2": fix some VS bug with namespace and partial template specialization template struct StringTraits2 { typedef typename S::value_type Result; }; template <> struct StringTraits2 { typedef char Result; }; template <> struct StringTraits2 { typedef wchar_t Result; }; } template struct StringTraits { private: typedef typename RemoveRef ::Result NonRefType; typedef typename RemoveConst ::Result NonConstType; typedef typename RemoveArray ::Result NonArrayType; typedef typename RemovePointer::Result NonPtrType; typedef typename RemoveConst ::Result UndecoratedType; //handle "const char* const" public: enum { isStringClass = implementation::HasStringMembers::result>::result }; typedef typename implementation::StringTraits2::Result CharType; enum { isStringLike = IsSameType::result || IsSameType::result }; }; namespace implementation { template inline size_t cStringLength(const C* str) //strlen() { assert_static((IsSameType::result || IsSameType::result)); size_t len = 0; while (*str++ != 0) ++len; return len; } } template inline const typename StringTraits::CharType* strBegin(const S& str, typename S::value_type dummy = 0) { return str.c_str(); } //SFINAE: T must be a "string" template inline const typename StringTraits::CharType* strBegin(const Char* str) { return str; } inline const char* strBegin(const char& ch) { return &ch; } inline const wchar_t* strBegin(const wchar_t& ch) { return &ch; } template inline size_t strLength(const S& str, typename S::value_type dummy = 0) { return str.length(); } //SFINAE: T must be a "string" template inline size_t strLength(const Char* str) { return implementation::cStringLength(str); } inline size_t strLength(char) { return 1; } inline size_t strLength(wchar_t) { return 1; } } #endif //STRING_TRAITS_HEADER_813274321443234