/* * * Copyright (c) 2003 * John Maddock * * Use, modification and distribution are subject to 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) * */ /* * LOCATION: see http://www.boost.org for most recent version. * FILE regex_token_iterator.hpp * VERSION see * DESCRIPTION: Provides regex_token_iterator implementation. */ #ifndef BOOST_REGEX_V4_REGEX_TOKEN_ITERATOR_HPP #define BOOST_REGEX_V4_REGEX_TOKEN_ITERATOR_HPP #include #include #if (BOOST_WORKAROUND(__BORLANDC__, >= 0x560) && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570)))\ || BOOST_WORKAROUND(BOOST_MSVC, < 1300) \ || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) // // Borland C++ Builder 6, and Visual C++ 6, // can't cope with the array template constructor // so we have a template member that will accept any type as // argument, and then assert that is really is an array: // #include #include #endif namespace cutl_details_boost{ #ifdef BOOST_MSVC #pragma warning(push) #pragma warning(disable: 4103) #endif #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif #ifdef BOOST_MSVC #pragma warning(pop) #endif #if BOOST_WORKAROUND(BOOST_MSVC, > 1300) # pragma warning(push) # pragma warning(disable:4700) #endif template class regex_token_iterator_implementation { typedef basic_regex regex_type; typedef sub_match value_type; match_results what; // current match BidirectionalIterator base; // start of search area BidirectionalIterator end; // end of search area const regex_type re; // the expression match_flag_type flags; // match flags value_type result; // the current string result int N; // the current sub-expression being enumerated std::vector subs; // the sub-expressions to enumerate public: regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, int sub, match_flag_type f) : end(last), re(*p), flags(f){ subs.push_back(sub); } regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const std::vector& v, match_flag_type f) : end(last), re(*p), flags(f), subs(v){} #if !BOOST_WORKAROUND(__HP_aCC, < 60700) #if (BOOST_WORKAROUND(__BORLANDC__, >= 0x560) && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570)))\ || BOOST_WORKAROUND(BOOST_MSVC, < 1300) \ || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) \ || BOOST_WORKAROUND(__HP_aCC, < 60700) template regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const T& submatches, match_flag_type f) : end(last), re(*p), flags(f) { // assert that T really is an array: BOOST_STATIC_ASSERT(::cutl_details_boost::is_array::value); const std::size_t array_size = sizeof(T) / sizeof(submatches[0]); for(std::size_t i = 0; i < array_size; ++i) { subs.push_back(submatches[i]); } } #else template regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const int (&submatches)[CN], match_flag_type f) : end(last), re(*p), flags(f) { for(std::size_t i = 0; i < CN; ++i) { subs.push_back(submatches[i]); } } #endif #endif bool init(BidirectionalIterator first) { N = 0; base = first; if(regex_search(first, end, what, re, flags, base) == true) { N = 0; result = ((subs[N] == -1) ? what.prefix() : what[(int)subs[N]]); return true; } else if((subs[N] == -1) && (first != end)) { result.first = first; result.second = end; result.matched = (first != end); N = -1; return true; } return false; } bool compare(const regex_token_iterator_implementation& that) { if(this == &that) return true; return (&re.get_data() == &that.re.get_data()) && (end == that.end) && (flags == that.flags) && (N == that.N) && (what[0].first == that.what[0].first) && (what[0].second == that.what[0].second); } const value_type& get() { return result; } bool next() { if(N == -1) return false; if(N+1 < (int)subs.size()) { ++N; result =((subs[N] == -1) ? what.prefix() : what[subs[N]]); return true; } //if(what.prefix().first != what[0].second) // flags |= /*match_prev_avail |*/ regex_constants::match_not_bob; BidirectionalIterator last_end(what[0].second); if(regex_search(last_end, end, what, re, ((what[0].first == what[0].second) ? flags | regex_constants::match_not_initial_null : flags), base)) { N =0; result =((subs[N] == -1) ? what.prefix() : what[subs[N]]); return true; } else if((last_end != end) && (subs[0] == -1)) { N =-1; result.first = last_end; result.second = end; result.matched = (last_end != end); return true; } return false; } private: regex_token_iterator_implementation& operator=(const regex_token_iterator_implementation&); }; template ::value_type, class traits = regex_traits > class regex_token_iterator #ifndef BOOST_NO_STD_ITERATOR : public std::iterator< std::forward_iterator_tag, sub_match, typename re_detail::regex_iterator_traits::difference_type, const sub_match*, const sub_match& > #endif { private: typedef regex_token_iterator_implementation impl; typedef shared_ptr pimpl; public: typedef basic_regex regex_type; typedef sub_match value_type; typedef typename re_detail::regex_iterator_traits::difference_type difference_type; typedef const value_type* pointer; typedef const value_type& reference; typedef std::forward_iterator_tag iterator_category; regex_token_iterator(){} regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, int submatch = 0, match_flag_type m = match_default) : pdata(new impl(&re, b, submatch, m)) { if(!pdata->init(a)) pdata.reset(); } regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, const std::vector& submatches, match_flag_type m = match_default) : pdata(new impl(&re, b, submatches, m)) { if(!pdata->init(a)) pdata.reset(); } #if !BOOST_WORKAROUND(__HP_aCC, < 60700) #if (BOOST_WORKAROUND(__BORLANDC__, >= 0x560) && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570)))\ || BOOST_WORKAROUND(BOOST_MSVC, < 1300) \ || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) \ || BOOST_WORKAROUND(__HP_aCC, < 60700) template regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, const T& submatches, match_flag_type m = match_default) : pdata(new impl(&re, b, submatches, m)) { if(!pdata->init(a)) pdata.reset(); } #else template regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, const int (&submatches)[N], match_flag_type m = match_default) : pdata(new impl(&re, b, submatches, m)) { if(!pdata->init(a)) pdata.reset(); } #endif #endif regex_token_iterator(const regex_token_iterator& that) : pdata(that.pdata) {} regex_token_iterator& operator=(const regex_token_iterator& that) { pdata = that.pdata; return *this; } bool operator==(const regex_token_iterator& that)const { if((pdata.get() == 0) || (that.pdata.get() == 0)) return pdata.get() == that.pdata.get(); return pdata->compare(*(that.pdata.get())); } bool operator!=(const regex_token_iterator& that)const { return !(*this == that); } const value_type& operator*()const { return pdata->get(); } const value_type* operator->()const { return &(pdata->get()); } regex_token_iterator& operator++() { cow(); if(0 == pdata->next()) { pdata.reset(); } return *this; } regex_token_iterator operator++(int) { regex_token_iterator result(*this); ++(*this); return result; } private: pimpl pdata; void cow() { // copy-on-write if(pdata.get() && !pdata.unique()) { pdata.reset(new impl(*(pdata.get()))); } } }; typedef regex_token_iterator cregex_token_iterator; typedef regex_token_iterator sregex_token_iterator; #ifndef BOOST_NO_WREGEX typedef regex_token_iterator wcregex_token_iterator; typedef regex_token_iterator wsregex_token_iterator; #endif template inline regex_token_iterator make_regex_token_iterator(const charT* p, const basic_regex& e, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default) { return regex_token_iterator(p, p+traits::length(p), e, submatch, m); } template inline regex_token_iterator::const_iterator, charT, traits> make_regex_token_iterator(const std::basic_string& p, const basic_regex& e, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default) { return regex_token_iterator::const_iterator, charT, traits>(p.begin(), p.end(), e, submatch, m); } #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) template inline regex_token_iterator make_regex_token_iterator(const charT* p, const basic_regex& e, const int (&submatch)[N], regex_constants::match_flag_type m = regex_constants::match_default) { return regex_token_iterator(p, p+traits::length(p), e, submatch, m); } template inline regex_token_iterator::const_iterator, charT, traits> make_regex_token_iterator(const std::basic_string& p, const basic_regex& e, const int (&submatch)[N], regex_constants::match_flag_type m = regex_constants::match_default) { return regex_token_iterator::const_iterator, charT, traits>(p.begin(), p.end(), e, submatch, m); } #endif template inline regex_token_iterator make_regex_token_iterator(const charT* p, const basic_regex& e, const std::vector& submatch, regex_constants::match_flag_type m = regex_constants::match_default) { return regex_token_iterator(p, p+traits::length(p), e, submatch, m); } template inline regex_token_iterator::const_iterator, charT, traits> make_regex_token_iterator(const std::basic_string& p, const basic_regex& e, const std::vector& submatch, regex_constants::match_flag_type m = regex_constants::match_default) { return regex_token_iterator::const_iterator, charT, traits>(p.begin(), p.end(), e, submatch, m); } #if BOOST_WORKAROUND(BOOST_MSVC, > 1300) # pragma warning(pop) #endif #ifdef BOOST_MSVC #pragma warning(push) #pragma warning(disable: 4103) #endif #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #ifdef BOOST_MSVC #pragma warning(pop) #endif } // namespace cutl_details_boost #endif // BOOST_REGEX_V4_REGEX_TOKEN_ITERATOR_HPP