00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00048 #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_STRING_TOKENISER
00049 #define STLSOFT_INCL_STLSOFT_STRING_HPP_STRING_TOKENISER
00050
00051 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00052 # define STLSOFT_VER_STLSOFT_STRING_HPP_STRING_TOKENISER_MAJOR 5
00053 # define STLSOFT_VER_STLSOFT_STRING_HPP_STRING_TOKENISER_MINOR 1
00054 # define STLSOFT_VER_STLSOFT_STRING_HPP_STRING_TOKENISER_REVISION 7
00055 # define STLSOFT_VER_STLSOFT_STRING_HPP_STRING_TOKENISER_EDIT 221
00056 #endif
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 #ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT
00075 # include <stlsoft/stlsoft.h>
00076 #endif
00077
00078 #if defined(STLSOFT_COMPILER_IS_DMC) && \
00079 __DMC__ < 0x0839
00080 # error stlsoft/string/string_tokeniser.hpp is not compatible with Digital Mars C/C++ 3.38 or earlier
00081 #endif
00082 #if defined(STLSOFT_COMPILER_IS_MSVC) && \
00083 _MSC_VER < 1100
00084 # error stlsoft/string/string_tokeniser.hpp is not compatible with Visual C++ 5.0 or earlier
00085 #endif
00086
00087 #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER
00088 # include <stlsoft/util/std/iterator_helper.hpp>
00089 #endif
00090 #ifndef STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING
00091 # include <stlsoft/shims/access/string.hpp>
00092 #endif
00093 #ifndef STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS
00094 # include <stlsoft/collections/util/collections.hpp>
00095 #endif
00096
00097 #ifndef STLSOFT_INCL_ITERATOR
00098 # define STLSOFT_INCL_ITERATOR
00099 # include <iterator>
00100 #endif
00101
00102 #ifdef STLSOFT_UNITTEST
00103 # ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_SIMPLE_STRING
00104 # include <stlsoft/string/simple_string.hpp>
00105 # endif
00106 # ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_STRING_VIEW
00107 # include <stlsoft/string/string_view.hpp>
00108 # endif
00109 # include <string>
00110 #endif
00111
00112
00113
00114
00115
00116 #if defined(STLSOFT_STRING_TOKENISER_USE_DELIMITER_INDIRECTION) || \
00117 ( ( defined(STLSOFT_COMPILER_IS_MSVC) && \
00118 _MSC_VER < 1300) || \
00119 ( defined(STLSOFT_COMPILER_IS_INTEL) && \
00120 defined(WIN32) && \
00121 _MSC_VER < 1300))
00122 # define STLSOFT_STRING_TOKENISER_CF_REQUIRE_DELIMITER_INDIRECTION
00123 #endif
00124
00125
00126
00127
00128
00129 #ifndef _STLSOFT_NO_NAMESPACE
00130 namespace stlsoft
00131 {
00132 #endif
00133
00134
00135
00136
00137
00138
00139
00151 template <ss_bool_t B>
00152 struct string_tokeniser_ignore_blanks
00153 {
00154 enum { value = B };
00155 };
00156
00168 template <ss_bool_t B>
00169 struct skip_blank_tokens
00170 {
00171 enum { value = B };
00172 };
00173
00174
00175
00195 template< ss_typename_param_k S
00196 , ss_typename_param_k V
00197 >
00198 struct string_tokeniser_type_traits
00199 {
00202 private:
00204 typedef S string_type;
00206 typedef V tokeniser_value_type;
00207
00208 public:
00210 typedef ss_typename_type_k S::value_type value_type;
00212 typedef ss_typename_type_k S::const_iterator const_iterator_type;
00214
00217 public:
00219 static const_iterator_type begin(string_type const& s)
00220 {
00221 return s.begin();
00222 }
00223
00225 static const_iterator_type end(string_type const& s)
00226 {
00227 return s.end();
00228 }
00229
00231 static tokeniser_value_type create(const_iterator_type f, const_iterator_type t)
00232 {
00233
00234
00235
00236
00237
00238 #if defined(STLSOFT_COMPILER_IS_MWERKS) || \
00239 ( ( defined(STLSOFT_COMPILER_IS_INTEL) || \
00240 defined(STLSOFT_COMPILER_IS_MSVC) && \
00241 _MSC_VER == 1300))
00242
00244 typedef ss_typename_type_k S::size_type size_type;
00245
00246 return tokeniser_value_type(&*f, static_cast<size_type>(t - f));
00247 #else
00248 return tokeniser_value_type(f, t);
00249 #endif
00250 }
00252 };
00253
00254
00266 template< ss_typename_param_k D
00267 , ss_typename_param_k S
00268 , ss_typename_param_k T
00269 >
00270 struct string_tokeniser_comparator
00271 {
00274 public:
00276 typedef D delimiter_type;
00278 typedef S string_type;
00280 typedef T traits_type;
00282 typedef ss_typename_type_k traits_type::const_iterator_type const_iterator;
00283 private:
00284 typedef string_tokeniser_comparator<D, S, T> class_type;
00286
00289 private:
00290 #if defined(STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT) && \
00291 ( !defined(STLSOFT_COMPILER_IS_MSVC) || \
00292 _MSC_VER >= 1200)
00294 template< ss_typename_param_k I1
00295 , ss_typename_param_k I2
00296 >
00297 static ss_bool_t is_equal_(I1 p1, I2 p2, ss_size_t n)
00298 {
00299 for(; n-- > 0; ++p1, ++p2)
00300 {
00301 if(*p1 != *p2)
00302 {
00303 return false;
00304 }
00305 }
00306
00307 return true;
00308 }
00309
00311 template< ss_typename_param_k D1
00312 , ss_typename_param_k I
00313 >
00314 static ss_bool_t is_equal_(D1 const& delim, I &p2)
00315 {
00316 return class_type::is_equal_(delim.begin(), p2, delim.length());
00317 }
00318
00320 template <ss_typename_param_k D1>
00321 static ss_size_t get_length_(D1 const& delim)
00322 {
00323 return delim.length();
00324 }
00325 #else
00327 static ss_bool_t is_equal_(string_type const& lhs, ss_typename_type_k string_type::value_type const* rhs)
00328 {
00329 { for(ss_size_t i = 0, n = lhs.length(); i < n; ++i)
00330 {
00331 if(lhs[i] != rhs[i])
00332 {
00333 return false;
00334 }
00335 }}
00336
00337 return true;
00338 }
00339
00341 static ss_size_t get_length_(string_type const& s)
00342 {
00343 return s.length();
00344 }
00345 #endif // STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT
00346
00348 static ss_bool_t is_equal_(ss_char_a_t const delim, const_iterator &it)
00349 {
00350 return delim == *it;
00351 }
00353 static ss_bool_t is_equal_(ss_char_w_t const delim, const_iterator &it)
00354 {
00355 return delim == *it;
00356 }
00358 static ss_size_t get_length_(ss_char_a_t const )
00359 {
00360 return 1;
00361 }
00363 static ss_size_t get_length_(ss_char_w_t const )
00364 {
00365 return 1;
00366 }
00367
00368 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00369 static const_iterator advance_(const_iterator it, delimiter_type const& delim)
00370 {
00371 return it + get_length_(delim);
00372 }
00373 #endif
00375
00378 public:
00380 static ss_bool_t not_equal(delimiter_type const& delim, const_iterator &it)
00381 {
00382 return !is_equal_(delim, it);
00383 }
00384
00386 static ss_size_t length(delimiter_type const& delim)
00387 {
00388 return get_length_(delim);
00389 }
00390
00391 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00392 static ss_bool_t test_start_token_advance(const_iterator &it, const_iterator end, delimiter_type const& delim)
00393 {
00394 return is_equal_(delim, it) ? (it = advance_(it, delim), true) : false;
00395 }
00396
00397 static ss_bool_t test_end_token_advance(const_iterator &it, const_iterator end, delimiter_type const& delim)
00398 {
00399 return is_equal_(delim, it) ? (it = advance_(it, delim), true) : false;
00400 }
00401
00402 static const_iterator nonskip_move_to_start(const_iterator it, const_iterator end, delimiter_type const& delim)
00403 {
00404 return it;
00405 }
00406
00407 static ss_bool_t test_end_token(const_iterator it, const_iterator end, delimiter_type const& delim)
00408 {
00409 return is_equal_(delim, it);
00410 }
00411
00412 static const_iterator find_next_start(const_iterator it, const_iterator end, delimiter_type const& delim)
00413 {
00414 return advance_(it, delim);
00415 }
00416 #endif
00418 };
00419
00529 template< ss_typename_param_k S
00530 , ss_typename_param_k D
00531 #ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT
00532 , ss_typename_param_k B = skip_blank_tokens<true>
00533 , ss_typename_param_k V = S
00534 , ss_typename_param_k T = string_tokeniser_type_traits<S, V>
00535 , ss_typename_param_k P = string_tokeniser_comparator<D, S, T>
00536 #else
00537 , ss_typename_param_k B
00538 , ss_typename_param_k V
00539 , ss_typename_param_k T
00540 , ss_typename_param_k P
00541 #endif
00542 >
00543 class string_tokeniser
00544 : public stl_collection_tag
00545 {
00548 public:
00550 typedef string_tokeniser<S, D, B, V, T, P> class_type;
00552 typedef string_tokeniser<S, D, B, V, T, P> tokeniser_type;
00554 typedef S string_type;
00556 typedef D delimiter_type;
00558 typedef B blanks_policy_type;
00559 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00560 typedef B ignore_blanks_type;
00561 #endif
00563 typedef V value_type;
00565 typedef T traits_type;
00567 typedef P comparator_type;
00569 typedef ss_typename_type_k traits_type::value_type char_type;
00574 typedef ss_size_t size_type;
00579 typedef ss_ptrdiff_t difference_type;
00581 typedef const value_type const_reference;
00583 class const_iterator;
00585
00588 public:
00595 string_tokeniser(char_type const* psz, delimiter_type const& delim)
00596 : m_str(psz)
00597 , m_delimiter(delim)
00598 {
00599 STLSOFT_MESSAGE_ASSERT("Delimiter of zero-length", 0 != comparator_type::length(m_delimiter));
00600
00601 STLSOFT_ASSERT(is_valid());
00602 }
00603
00604
00605
00606 #if !defined(STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT) || \
00607 defined(STLSOFT_CF_MEMBER_TEMPLATE_CTOR_OVERLOAD_DISCRIMINATED)
00614 string_tokeniser(string_type const& str, delimiter_type const& delim)
00615 : m_str(str)
00616 , m_delimiter(delim)
00617 {
00618 STLSOFT_MESSAGE_ASSERT("Delimiter of zero-length", 0 != comparator_type::length(m_delimiter));
00619
00620 STLSOFT_ASSERT(is_valid());
00621 }
00622 #endif
00623
00624
00625 #if defined(STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT)
00632 template <ss_typename_param_k S1>
00633 string_tokeniser(S1 const& str, delimiter_type const& delim)
00634 : m_str(c_str_data(str), c_str_len(str))
00635 , m_delimiter(delim)
00636 {
00637 STLSOFT_MESSAGE_ASSERT("Delimiter of zero-length", 0 != comparator_type::length(m_delimiter));
00638
00639 STLSOFT_ASSERT(is_valid());
00640 }
00641 #endif
00642
00650 string_tokeniser(char_type const* psz, size_type cch, delimiter_type const& delim)
00651 : m_str(psz, cch)
00652 , m_delimiter(delim)
00653 {
00654 STLSOFT_MESSAGE_ASSERT("Delimiter of zero-length", 0 != comparator_type::length(m_delimiter));
00655
00656 STLSOFT_ASSERT(is_valid());
00657 }
00658
00659 #if !defined(STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT) || \
00660 defined(STLSOFT_CF_MEMBER_TEMPLATE_CTOR_OVERLOAD_DISCRIMINATED)
00666 string_tokeniser(char_type const* from, char_type const* to, delimiter_type const& delim)
00667 : m_str(from, to)
00668 , m_delimiter(delim)
00669 {
00670 STLSOFT_MESSAGE_ASSERT("Delimiter of zero-length", 0 != comparator_type::length(m_delimiter));
00671
00672 STLSOFT_ASSERT(is_valid());
00673 }
00674 #endif
00675
00676 #if defined(STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT)
00682 template <ss_typename_param_k I>
00683 string_tokeniser(I from, I to, delimiter_type const& delim)
00684 : m_str(from, to)
00685 , m_delimiter(delim)
00686 {
00687 STLSOFT_MESSAGE_ASSERT("Delimiter of zero-length", 0 != comparator_type::length(m_delimiter));
00688
00689 STLSOFT_ASSERT(is_valid());
00690 }
00691 #endif
00693
00696 public:
00698 class const_iterator
00699 : public iterator_base< stlsoft_ns_qual_std(forward_iterator_tag)
00700 , value_type
00701 , ss_ptrdiff_t
00702 , void
00703 , value_type
00704 >
00705 {
00708 public:
00710 typedef const_iterator class_type;
00711 #if ( defined(STLSOFT_COMPILER_IS_DMC) && \
00712 __DMC__ <= 0x0843) || \
00713 defined(STLSOFT_COMPILER_IS_MSVC)
00715 typedef delimiter_type delimiter_type;
00717 typedef value_type value_type;
00719 typedef traits_type traits_type;
00720 #else
00722 typedef ss_typename_type_k tokeniser_type::delimiter_type delimiter_type;
00724 typedef ss_typename_type_k tokeniser_type::value_type value_type;
00726 typedef ss_typename_type_k tokeniser_type::traits_type traits_type;
00727 #endif
00728 typedef value_type effective_const_reference;
00729 private:
00730 typedef ss_typename_type_k traits_type::const_iterator_type underlying_iterator_type;
00731 # if defined(STLSOFT_STRING_TOKENISER_CF_REQUIRE_DELIMITER_INDIRECTION)
00732 typedef delimiter_type const* delimiter_ref_type;
00733 # else
00734 typedef delimiter_type delimiter_ref_type;
00735 # endif
00737
00740 private:
00741 friend class string_tokeniser<S, D, B, V, T, P>;
00742
00744 const_iterator(underlying_iterator_type first, underlying_iterator_type last, delimiter_type const& delimiter)
00745 : m_find0(first)
00746 , m_find1(first)
00747 , m_next(first)
00748 , m_end(last)
00749 # if defined(STLSOFT_STRING_TOKENISER_CF_REQUIRE_DELIMITER_INDIRECTION)
00750 , m_delimiter(&delimiter)
00751 # else
00752 , m_delimiter(delimiter)
00753 # endif
00754 , m_cchDelimiter(comparator_type::length(delimiter))
00755 {
00756 if(m_end != m_find0)
00757 {
00758 increment_();
00759 }
00760 }
00761 public:
00763 const_iterator()
00764 : m_find0(NULL)
00765 , m_find1(NULL)
00766 , m_next(NULL)
00767 , m_end(NULL)
00768 , m_delimiter(delimiter_ref_type())
00769 , m_cchDelimiter(0)
00770 {}
00771
00775 const_iterator(class_type const& rhs)
00776 : m_find0(rhs.m_find0)
00777 , m_find1(rhs.m_find1)
00778 , m_next(rhs.m_next)
00779 , m_end(rhs.m_end)
00780 , m_delimiter(rhs.m_delimiter)
00781 , m_cchDelimiter(comparator_type::length(get_delim_ref_(rhs.m_delimiter)))
00782 {}
00783
00787 class_type const& operator =(class_type const& rhs)
00788 {
00789 m_find0 = rhs.m_find0;
00790 m_find1 = rhs.m_find1;
00791 m_next = rhs.m_next;
00792 m_end = rhs.m_end;
00793 m_delimiter = rhs.m_delimiter;
00794 m_cchDelimiter = rhs.m_cchDelimiter;
00795
00796 return *this;
00797 }
00799
00802 public:
00804
00805
00806 V operator *() const
00807 {
00808 return traits_type::create(m_find0, m_find1);
00809 }
00810
00812 class_type& operator ++()
00813 {
00814 increment_();
00815
00816 return *this;
00817 }
00818
00820 const class_type operator ++(int)
00821 {
00822 class_type ret(*this);
00823
00824 operator ++();
00825
00826 return ret;
00827 }
00828
00830 ss_bool_t equal(class_type const& rhs) const
00831 {
00832 STLSOFT_MESSAGE_ASSERT("Comparing iterators from different tokenisers", m_end == rhs.m_end);
00833
00834 return m_find0 == rhs.m_find0;
00835 }
00836
00838 ss_bool_t operator == (class_type const& rhs) const
00839 {
00840 return equal(rhs);
00841 }
00842
00844 ss_bool_t operator != (class_type const& rhs) const
00845 {
00846 return !equal(rhs);
00847 }
00849
00852 private:
00853 static delimiter_type const& get_delim_ref_(delimiter_ref_type const& delim)
00854 {
00855 # if defined(STLSOFT_STRING_TOKENISER_CF_REQUIRE_DELIMITER_INDIRECTION)
00856 return *delim;
00857 # else
00858 return delim;
00859 # endif
00860 }
00861
00862 void increment_()
00863 {
00864 STLSOFT_MESSAGE_ASSERT("Attempting to increment an invalid iterator", m_find0 != m_end);
00865
00866
00867
00868
00869
00870
00871
00872
00873 if(blanks_policy_type::value)
00874 {
00875
00876 for(m_find0 = m_next; m_find0 != m_end; )
00877 {
00878 if(comparator_type::not_equal(get_delim_ref_(m_delimiter), m_find0))
00879 {
00880 break;
00881 }
00882 else
00883 {
00884 m_find0 += static_cast<ss_ptrdiff_t>(m_cchDelimiter);
00885 }
00886 }
00887 }
00888 else
00889 {
00890 m_find0 = m_next;
00891 }
00892
00893
00894 for(m_find1 = m_find0; ; )
00895 {
00896 if(m_find1 == m_end)
00897 {
00898
00899 m_next = m_find1;
00900 break;
00901 }
00902 else if(comparator_type::not_equal(get_delim_ref_(m_delimiter), m_find1))
00903 {
00904
00905 ++m_find1;
00906 }
00907 else
00908 {
00909
00910
00911 m_next = m_find1 + static_cast<ss_ptrdiff_t>(m_cchDelimiter);
00912
00913 break;
00914 }
00915 }
00916 }
00918
00921 private:
00922 underlying_iterator_type m_find0;
00923 underlying_iterator_type m_find1;
00924 underlying_iterator_type m_next;
00925 underlying_iterator_type m_end;
00926 delimiter_ref_type m_delimiter;
00927 ss_size_t m_cchDelimiter;
00929 };
00930
00934 const_iterator begin() const
00935 {
00936 STLSOFT_ASSERT(is_valid());
00937
00938 return const_iterator(traits_type::begin(m_str), traits_type::end(m_str), m_delimiter);
00939 }
00943 const_iterator end() const
00944 {
00945 STLSOFT_ASSERT(is_valid());
00946
00947 return const_iterator(traits_type::end(m_str), traits_type::end(m_str), m_delimiter);
00948 }
00950
00953 public:
00955 ss_bool_t empty() const
00956 {
00957 STLSOFT_ASSERT(is_valid());
00958
00959 return begin() == end();
00960 }
00962
00965 private:
00966 ss_bool_t is_valid() const
00967 {
00968 return true;
00969 }
00971
00974 private:
00975 string_type const m_str;
00976 delimiter_type const m_delimiter;
00978
00981 private:
00982 class_type const& operator =(class_type const&);
00984 };
00985
00986
00987
00988
00989
00990 #if 0
00991
00995 template< ss_typename_param_k S
00996 , ss_typename_param_k D
00997 , ss_typename_param_k B
00998 , ss_typename_param_k V
00999 , ss_typename_param_k T
01000 , ss_typename_param_k P
01001 >
01002 inline ss_bool_t operator ==( ss_typename_type_k string_tokeniser<S, D, B, V, T, P>::const_iterator const& lhs
01003 , ss_typename_type_k string_tokeniser<S, D, B, V, T, P>::const_iterator const& rhs)
01004 {
01005 return lhs.equal(rhs);
01006 }
01007
01012 template< ss_typename_param_k S
01013 , ss_typename_param_k D
01014 , ss_typename_param_k B
01015 , ss_typename_param_k V
01016 , ss_typename_param_k T
01017 , ss_typename_param_k P
01018 >
01019 inline ss_bool_t operator !=( ss_typename_type_k string_tokeniser<S, D, B, V, T, P>::const_iterator const& lhs
01020 , ss_typename_type_k string_tokeniser<S, D, B, V, T, P>::const_iterator const& rhs)
01021 {
01022 return !lhs.equal(rhs);
01023 }
01024 #endif
01025
01026
01027
01028
01029
01030 #ifdef STLSOFT_UNITTEST
01031 # include "./unittest/string_tokeniser_unittest_.h"
01032 #endif
01033
01034
01035
01036 #if defined(STLSOFT_COMPILER_IS_DMC) && \
01037 !defined(_STLPORT_VERSION)
01038 template< ss_typename_param_k S
01039 , ss_typename_param_k D
01040 , ss_typename_param_k B
01041 , ss_typename_param_k V
01042 , ss_typename_param_k T
01043 , ss_typename_param_k P
01044 >
01045 inline forward_iterator_tag iterator_category(string_tokeniser<S, D, B, V, T, P>::const_iterator const&)
01046 {
01047 return forward_iterator_tag();
01048 }
01049
01050 template< ss_typename_param_k S
01051 , ss_typename_param_k D
01052 , ss_typename_param_k B
01053 , ss_typename_param_k V
01054 , ss_typename_param_k T
01055 , ss_typename_param_k P
01056 >
01057 inline ss_ptrdiff_t* distance_type(string_tokeniser<S, D, B, V, T, P>::const_iterator const&)
01058 {
01059 return static_cast<ss_ptrdiff_t*>(0);
01060 }
01061 #endif
01062
01063
01064
01065 #ifndef _STLSOFT_NO_NAMESPACE
01066 }
01067 #endif
01068
01069
01070
01071 #endif
01072
01073