lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
nullterminated_range.h
00001 /*****************************************************/
00002 /* lean Strings                 (c) Tobias Zirr 2011 */
00003 /*****************************************************/
00004 
00005 #ifndef LEAN_STRINGS_NULLTERMINATED_RANGE
00006 #define LEAN_STRINGS_NULLTERMINATED_RANGE
00007 
00008 #include "../lean.h"
00009 #include "../meta/strip.h"
00010 #include "../meta/enable_if.h"
00011 #include "char_traits.h"
00012 #include "nullterminated.h"
00013 
00014 namespace lean
00015 {
00016 namespace strings
00017 {
00018 
00021 template < class Char, class Traits = char_traits<typename strip_const<Char>::type> >
00022 class nullterminated_range_implicit : public nullterminated_implicit<Char, Traits>
00023 {
00024     typedef nullterminated_implicit<Char, Traits> base_type;
00025 
00026 public:
00028     typedef typename base_type::value_type value_type;
00029     
00031     typedef typename base_type::size_type size_type;
00033     typedef typename base_type::difference_type difference_type;
00034 
00036     typedef typename base_type::pointer pointer;
00038     typedef typename base_type::const_pointer const_pointer;
00040     typedef typename base_type::reference reference;
00042     typedef typename base_type::const_reference const_reference;
00043 
00045     typedef typename base_type::pointer iterator;
00047     typedef typename base_type::const_iterator const_iterator;
00048 
00050     typedef typename base_type::traits_type traits_type;
00051 
00052 private:
00054     static LEAN_INLINE void assert_null_terminated(const_pointer end)
00055     {
00056         LEAN_ASSERT(end);
00057         LEAN_ASSERT(traits_type::null(*end));
00058     }
00059 
00061     static LEAN_INLINE const_pointer first_non_null(const_pointer a, const_pointer b)
00062     {
00063         return (a) ? a : b;
00064     }
00065 
00066 protected:
00067     const_pointer m_end;
00068 
00069 public:
00071     LEAN_INLINE nullterminated_range_implicit(const nullterminated_implicit<Char, Traits> &right)
00072         : base_type(right),
00073         m_end(right.end())
00074     {
00075         assert_null_terminated(m_end);
00076     }
00078     LEAN_INLINE nullterminated_range_implicit(const_pointer begin)
00079         : base_type(begin),
00080         m_end(base_type::end())
00081     {
00082         assert_null_terminated(m_end);
00083     }
00085     LEAN_INLINE nullterminated_range_implicit(const_pointer begin, const_pointer end)
00086         : base_type(begin),
00087         m_end(end)
00088     {
00089         assert_null_terminated(m_end);
00090     }
00092     template <class Compatible>
00093     LEAN_INLINE nullterminated_range_implicit(const Compatible &from,
00094             typename enable_if<is_nullterminated_compatible<Compatible, value_type, traits_type>::value, const void*>::type = nullptr)
00095         : base_type(from),
00096         m_end(
00097             first_non_null(
00098                 nullterminated_compatible<Compatible, value_type, traits_type>::from(from, base_type::begin()),
00099                 base_type::end() )
00100             )
00101     {
00102         assert_null_terminated(m_end);
00103     }
00104 
00106     LEAN_INLINE bool empty() const { return (m_begin == m_end); }
00108     LEAN_INLINE size_type length() const { return m_end - m_begin; }
00110     LEAN_INLINE size_type size() const { return length(); }
00112     LEAN_INLINE size_type count() const { return traits_type::count(m_begin, m_end); }
00113     
00115     LEAN_INLINE const_iterator end() const { return m_end; }
00116 
00118     LEAN_INLINE void swap(nullterminated_range_implicit& right)
00119     {
00120         base_type::swap(right);
00121         const_pointer right_end = right.m_end;
00122         right.m_end = m_end;
00123         m_end = right_end;
00124     }
00125 
00127     template <class Compatible>
00128     Compatible to() const
00129     {
00130         typedef typename assert_nullterminated_compatible<
00131                 Compatible,
00132                 value_type, traits_type
00133             >::type assert_compatible;
00134         return nullterminated_compatible<Compatible, value_type, traits_type>::to(m_begin, m_end);
00135     }
00136 };
00137 
00139 template < class Char, class Traits = char_traits<typename strip_const<Char>::type> >
00140 class nullterminated_range : public nullterminated_range_implicit<Char, Traits>
00141 {
00142 public:
00144     typedef nullterminated_range_implicit<Char, Traits> implicit_type;
00145 
00147     explicit LEAN_INLINE nullterminated_range(typename implicit_type::const_pointer begin)
00148         : implicit_type(begin) { }
00150     LEAN_INLINE nullterminated_range(typename implicit_type::const_pointer begin, typename implicit_type::const_pointer end)
00151         : implicit_type(begin, end) { }
00153     template <class Compatible>
00154     explicit LEAN_INLINE nullterminated_range(const Compatible &from,
00155             typename enable_if<is_nullterminated_compatible<Compatible, value_type, traits_type>::value, const void*>::type = nullptr)
00156         : implicit_type(from) { }
00158     explicit LEAN_INLINE nullterminated_range(const implicit_type &right)
00159         : implicit_type(right) { }
00160 
00162     explicit LEAN_INLINE nullterminated_range(const nullterminated_implicit<Char, Traits> &right)
00163         : implicit_type(right) { }
00165     LEAN_INLINE nullterminated_range(const nullterminated<Char, Traits> &right)
00166         : implicit_type(right) { }
00167 
00169     LEAN_INLINE operator nullterminated<Char, Traits>() const
00170     {
00171         return nullterminated<Char, Traits>(*this);
00172     }
00173 };
00174 
00176 template <class Char, class Traits>
00177 LEAN_INLINE nullterminated_range<Char, Traits> make_ntr(const nullterminated_range_implicit<Char, Traits> &range)
00178 {
00179     return nullterminated_range<Char, Traits>(range);
00180 }
00182 template <class Char>
00183 LEAN_INLINE nullterminated_range<Char> make_ntr(const Char *range)
00184 {
00185     return nullterminated_range<Char>(range);
00186 }
00188 template <class Char, class Compatible>
00189 LEAN_INLINE typename enable_if<
00190         is_nullterminated_compatible<Compatible, Char, typename nullterminated_range<Char>::traits_type>::value,
00191         nullterminated_range<Char>
00192     >::type make_ntr(const Compatible &compatible)
00193 {
00194     return nullterminated_range<Char>(compatible);
00195 }
00196 
00198 template <class Char, class Traits>
00199 LEAN_INLINE bool operator ==(const nullterminated_range_implicit<Char, Traits>& left, const nullterminated_range_implicit<Char, Traits>& right)
00200 {
00201     return (left.length() == right.length()) && nullterminated<Char, Traits>::traits_type::equal(left.c_str(), right.c_str());
00202 }
00203 template <class Char, class Traits, class Compatible>
00204 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type
00205     operator ==(const nullterminated_range_implicit<Char, Traits>& left, const Compatible& right) { return left == make_ntr<Char, Traits>(right); }
00206 template <class Char, class Traits, class Compatible>
00207 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type
00208     operator ==(const Compatible& left, const nullterminated_range_implicit<Char, Traits>& right) { return make_ntr<Char, Traits>(left) == right; }
00209 
00211 template <class Char, class Traits>
00212 LEAN_INLINE bool operator !=(const nullterminated_range_implicit<Char, Traits>& left, const nullterminated_range_implicit<Char, Traits>& right)
00213 {
00214     return !(left == right);
00215 }
00216 template <class Char, class Traits, class Compatible>
00217 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type
00218     operator !=(const nullterminated_range_implicit<Char, Traits>& left, const Compatible& right) { return left != make_ntr<Char, Traits>(right); }
00219 template <class Char, class Traits, class Compatible>
00220 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type
00221     operator !=(const Compatible& left, const nullterminated_range_implicit<Char, Traits>& right) { return make_ntr<Char, Traits>(left) != right; }
00222 
00224 template <class Char, class Traits>
00225 LEAN_INLINE bool operator <(const nullterminated_range_implicit<Char, Traits>& left, const nullterminated_range_implicit<Char, Traits>& right)
00226 {
00227     return nullterminated<Char, Traits>::traits_type::less(left.c_str(), right.c_str());
00228 }
00229 template <class Char, class Traits, class Compatible>
00230 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type
00231     operator <(const nullterminated_range_implicit<Char, Traits>& left, const Compatible& right) { return left < make_ntr<Char, Traits>(right); }
00232 template <class Char, class Traits, class Compatible>
00233 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type
00234     operator <(const Compatible& left, const nullterminated_range_implicit<Char, Traits>& right) { return make_ntr<Char, Traits>(left) < right; }
00235 
00237 template <class Char, class Traits>
00238 LEAN_INLINE bool operator >(const nullterminated_range_implicit<Char, Traits>& left, const nullterminated_range_implicit<Char, Traits>& right)
00239 {
00240     return (right < left);
00241 }
00242 template <class Char, class Traits, class Compatible>
00243 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type
00244     operator >(const nullterminated_range_implicit<Char, Traits>& left, const Compatible& right) { return left > make_ntr<Char, Traits>(right); }
00245 template <class Char, class Traits, class Compatible>
00246 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type
00247     operator >(const Compatible& left, const nullterminated_range_implicit<Char, Traits>& right) { return make_ntr<Char, Traits>(left) > right; }
00248 
00250 template <class Char, class Traits>
00251 LEAN_INLINE bool operator <=(const nullterminated_range_implicit<Char, Traits>& left, const nullterminated_range_implicit<Char, Traits>& right)
00252 {
00253     return !(right < left);
00254 }
00255 template <class Char, class Traits, class Compatible>
00256 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type
00257     operator <=(const nullterminated_range_implicit<Char, Traits>& left, const Compatible& right) { return left <= make_ntr<Char, Traits>(right); }
00258 template <class Char, class Traits, class Compatible>
00259 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type
00260     operator <=(const Compatible& left, const nullterminated_range_implicit<Char, Traits>& right) { return make_ntr<Char, Traits>(left) <= right; }
00261 
00263 template <class Char, class Traits>
00264 LEAN_INLINE bool operator >=(const nullterminated_range_implicit<Char, Traits>& left, const nullterminated_range_implicit<Char, Traits>& right)
00265 {
00266     return !(left < right);
00267 }
00268 template <class Char, class Traits, class Compatible>
00269 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type
00270     operator >=(const nullterminated_range_implicit<Char, Traits>& left, const Compatible& right) { return left >= make_ntr<Char, Traits>(right); }
00271 template <class Char, class Traits, class Compatible>
00272 LEAN_INLINE typename enable_if<is_nullterminated_convertible<Compatible, Char, Traits>::value, bool>::type
00273     operator >=(const Compatible& left, const nullterminated_range_implicit<Char, Traits>& right) { return make_ntr<Char, Traits>(left) >= right; }
00274 
00276 template <class Char, class Traits>
00277 LEAN_INLINE void swap(nullterminated_range_implicit<Char, Traits>& left, nullterminated_range_implicit<Char, Traits>& right)
00278 {
00279     left.swap(right);
00280 }
00281 
00282 } // namespace
00283 
00284 using strings::nullterminated_range_implicit;
00285 using strings::nullterminated_range;
00286 
00287 using strings::make_ntr;
00288 
00289 } // namespace
00290 
00291 #endif