lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
|
00001 /*****************************************************/ 00002 /* lean Strings (c) Tobias Zirr 2011 */ 00003 /*****************************************************/ 00004 00005 #ifndef LEAN_STRINGS_NULLTERMINATED 00006 #define LEAN_STRINGS_NULLTERMINATED 00007 00008 #include "../lean.h" 00009 #include "../meta/strip.h" 00010 #include "../meta/type_traits.h" 00011 #include "../meta/enable_if.h" 00012 #include "char_traits.h" 00013 00014 namespace lean 00015 { 00016 namespace strings 00017 { 00018 00019 struct nullterminated_incompatible { }; 00020 00022 template <class Compatible, class Char, class Traits> 00023 struct nullterminated_compatible : public nullterminated_incompatible 00024 { 00025 #ifdef DOXYGEN_READ_THIS 00026 00027 00028 static const Char* from(const Compatible &from); 00031 static const Char* from(const Compatible &from, const Char *begin); 00032 00034 static Compatible to(const Char *begin); 00036 static Compatible to(const Char *begin, const Char *end); 00037 #endif 00038 }; 00039 00041 template <class Compatible, class Char, class Traits> 00042 struct is_nullterminated_compatible 00043 { 00045 static const bool value = !is_derived< 00046 nullterminated_compatible<Compatible, Char, Traits>, 00047 nullterminated_incompatible>::value; 00048 }; 00049 00051 template <class Compatible, class Char, class Traits> 00052 struct is_nullterminated_convertible 00053 { 00055 static const bool value = is_equal< 00056 typename strip_modifiers<typename strip_pointer<typename strip_reference<Compatible>::type>::type>::type, 00057 typename strip_modifiers<Char>::type >::value 00058 || is_equal< 00059 typename strip_modifiers<typename strip_array<typename strip_reference<Compatible>::type>::type>::type, 00060 typename strip_modifiers<Char>::type >::value 00061 || is_nullterminated_compatible<Compatible, Char, Traits>::value; 00062 }; 00063 00065 template <class Compatible, class Char, class Traits> 00066 struct assert_nullterminated_compatible 00067 { 00068 static const bool is_compatible = is_nullterminated_compatible<Compatible, Char, Traits>::value; 00069 00070 LEAN_STATIC_ASSERT_MSG_ALT(is_compatible, 00071 "Type incompatible with nullterminated character range class.", 00072 Type_incompatible_with_nullterminated_character_range_class); 00073 00075 typedef void type; 00076 }; 00077 00080 template < class Char, class Traits = char_traits<typename strip_const<Char>::type> > 00081 class nullterminated_implicit 00082 { 00083 public: 00085 typedef typename strip_const<Char>::type value_type; 00086 00088 typedef size_t size_type; 00090 typedef ptrdiff_t difference_type; 00091 00093 typedef value_type* pointer; 00095 typedef const value_type* const_pointer; 00097 typedef value_type& reference; 00099 typedef const value_type& const_reference; 00100 00102 typedef pointer iterator; 00104 typedef const_pointer const_iterator; 00105 00107 typedef Traits traits_type; 00108 00109 protected: 00110 const_pointer m_begin; 00111 00112 // /// Gets a pointer to this null-terminated range. 00113 // LEAN_INLINE operator Char*() const { return m_begin; } 00114 // DESIGN: Only permit implicit conversion to compatible container types, otherwise pointers might accidentally dangle. 00115 00116 public: 00118 LEAN_INLINE nullterminated_implicit(const_pointer begin) 00119 : m_begin(begin) 00120 { 00121 LEAN_ASSERT(m_begin); 00122 } 00124 template <class Compatible> 00125 LEAN_INLINE nullterminated_implicit(const Compatible &from, 00126 typename enable_if<is_nullterminated_compatible<Compatible, value_type, traits_type>::value, const void*>::type = nullptr) 00127 : m_begin(nullterminated_compatible<Compatible, value_type, traits_type>::from(from)) 00128 { 00129 LEAN_ASSERT(m_begin); 00130 } 00131 00133 LEAN_INLINE bool empty() const { return traits_type::empty(m_begin); } 00135 LEAN_INLINE size_type length() const { return traits_type::length(m_begin); } 00137 LEAN_INLINE size_type size() const { return length(); } 00139 LEAN_INLINE size_type count() const { return traits_type::count(m_begin); } 00140 00142 LEAN_INLINE const_reference operator [](size_type pos) const { return m_begin[pos]; } 00143 00145 LEAN_INLINE const_pointer c_str() const { return m_begin; } 00147 LEAN_INLINE const_pointer data() const { return c_str(); } 00148 00150 LEAN_INLINE const_iterator begin() const { return m_begin; } 00152 LEAN_INLINE const_iterator end() const { return m_begin + length(); } 00153 00155 LEAN_INLINE void swap(nullterminated_implicit& right) 00156 { 00157 const_pointer right_begin = right.m_begin; 00158 right.m_begin = m_begin; 00159 m_begin = right_begin; 00160 } 00161 00163 template <class Compatible> 00164 Compatible to() const 00165 { 00166 typedef typename assert_nullterminated_compatible< 00167 Compatible, 00168 value_type, traits_type 00169 >::type assert_compatible; 00170 return nullterminated_compatible<Compatible, value_type, traits_type>::to(m_begin); 00171 } 00172 }; 00173 00175 template < class Char, class Traits = char_traits<typename strip_const<Char>::type> > 00176 class nullterminated : public nullterminated_implicit<Char, Traits> 00177 { 00178 public: 00180 typedef nullterminated_implicit<Char, Traits> implicit_type; 00181 00183 explicit LEAN_INLINE nullterminated(typename implicit_type::const_pointer begin) 00184 : implicit_type(begin) { } 00186 template <class Compatible> 00187 explicit LEAN_INLINE nullterminated(const Compatible &from, 00188 typename enable_if<is_nullterminated_compatible<Compatible, value_type, traits_type>::value, const void*>::type = nullptr) 00189 : implicit_type(from) { } 00191 explicit LEAN_INLINE nullterminated(const implicit_type &right) 00192 : implicit_type(right) { } 00193 }; 00194 00196 template <class Char, class Traits> 00197 LEAN_INLINE nullterminated<Char, Traits> make_nt(const nullterminated_implicit<Char, Traits> &range) 00198 { 00199 return nullterminated<Char, Traits>(range); 00200 } 00202 template <class Char> 00203 LEAN_INLINE nullterminated<Char> make_nt(const Char *range) 00204 { 00205 return nullterminated<Char>(range); 00206 } 00208 template <class Char, class Compatible> 00209 LEAN_INLINE typename enable_if< 00210 is_nullterminated_compatible<Compatible, Char, typename nullterminated<Char>::traits_type>::value, 00211 nullterminated<Char> 00212 >::type make_nt(const Compatible &compatible) 00213 { 00214 return nullterminated<Char>(compatible); 00215 } 00216 00218 template <class Char, class Traits> 00219 LEAN_INLINE bool operator ==(const nullterminated_implicit<Char, Traits>& left, const nullterminated_implicit<Char, Traits>& right) 00220 { 00221 return nullterminated_implicit<Char, Traits>::traits_type::equal(left.c_str(), right.c_str()); 00222 } 00223 00224 template <class Char, class Traits, class Compatible> 00225 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type 00226 operator ==(const nullterminated_implicit<Char, Traits>& left, const Compatible& right) { return left == make_nt<Char, Traits>(right); } 00227 template <class Char, class Traits, class Compatible> 00228 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type 00229 operator ==(const Compatible& left, const nullterminated_implicit<Char, Traits>& right) { return make_nt<Char, Traits>(left) == right; } 00230 00232 template <class Char, class Traits> 00233 LEAN_INLINE bool operator !=(const nullterminated_implicit<Char, Traits>& left, const nullterminated_implicit<Char, Traits>& right) 00234 { 00235 return !(left == right); 00236 } 00237 template <class Char, class Traits, class Compatible> 00238 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type 00239 operator !=(const nullterminated_implicit<Char, Traits>& left, const Compatible& right) { return left != make_nt<Char, Traits>(right); } 00240 template <class Char, class Traits, class Compatible> 00241 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type 00242 operator !=(const Compatible& left, const nullterminated_implicit<Char, Traits>& right) { return make_nt<Char, Traits>(left) != right; } 00243 00245 template <class Char, class Traits> 00246 LEAN_INLINE bool operator <(const nullterminated_implicit<Char, Traits>& left, const nullterminated_implicit<Char, Traits>& right) 00247 { 00248 return nullterminated_implicit<Char, Traits>::traits_type::less(left.c_str(), right.c_str()); 00249 } 00250 template <class Char, class Traits, class Compatible> 00251 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type 00252 operator <(const nullterminated_implicit<Char, Traits>& left, const Compatible& right) { return left < <make_nt<Char, Traits>(right); } 00253 template <class Char, class Traits, class Compatible> 00254 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type 00255 operator <(const Compatible& left, const nullterminated_implicit<Char, Traits>& right) { return make_nt<Char, Traits>(left) < right; } 00256 00258 template <class Char, class Traits> 00259 LEAN_INLINE bool operator >(const nullterminated_implicit<Char, Traits>& left, const nullterminated_implicit<Char, Traits>& right) 00260 { 00261 return (right < left); 00262 } 00263 template <class Char, class Traits, class Compatible> 00264 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type 00265 operator >(const nullterminated_implicit<Char, Traits>& left, const Compatible& right) { return left > <make_nt<Char, Traits>(right); } 00266 template <class Char, class Traits, class Compatible> 00267 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type 00268 operator >(const Compatible& left, const nullterminated_implicit<Char, Traits>& right) { return make_nt<Char, Traits>(left) > right; } 00269 00271 template <class Char, class Traits> 00272 LEAN_INLINE bool operator <=(const nullterminated_implicit<Char, Traits>& left, const nullterminated_implicit<Char, Traits>& right) 00273 { 00274 return !(right < left); 00275 } 00276 template <class Char, class Traits, class Compatible> 00277 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type 00278 operator <=(const nullterminated_implicit<Char, Traits>& left, const Compatible& right) { return left <= <make_nt<Char, Traits>(right); } 00279 template <class Char, class Traits, class Compatible> 00280 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type 00281 operator <=(const Compatible& left, const nullterminated_implicit<Char, Traits>& right) { return make_nt<Char, Traits>(left) <= right; } 00282 00284 template <class Char, class Traits> 00285 LEAN_INLINE bool operator >=(const nullterminated_implicit<Char, Traits>& left, const nullterminated_implicit<Char, Traits>& right) 00286 { 00287 return !(left < right); 00288 } 00289 template <class Char, class Traits, class Compatible> 00290 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type 00291 operator >=(const nullterminated_implicit<Char, Traits>& left, const Compatible& right) { return left >= <make_nt<Char, Traits>(right); } 00292 template <class Char, class Traits, class Compatible> 00293 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type 00294 operator >=(const Compatible& left, const nullterminated_implicit<Char, Traits>& right) { return make_nt<Char, Traits>(left) >= right; } 00295 00297 template <class Char, class Traits> 00298 LEAN_INLINE void swap(nullterminated_implicit<Char, Traits>& left, nullterminated_implicit<Char, Traits>& right) 00299 { 00300 left.swap(right); 00301 } 00302 00303 } // namespace 00304 00305 using strings::nullterminated_implicit; 00306 using strings::nullterminated; 00307 00308 using strings::make_nt; 00309 00310 } // namespace 00311 00312 #endif