lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
nullterminated.h
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