source: NonGTP/Boost/boost/regex/v4/match_results.hpp @ 857

Revision 857, 12.8 KB checked in by igarcia, 18 years ago (diff)
Line 
1/*
2 *
3 * Copyright (c) 1998-2002
4 * John Maddock
5 *
6 * Use, modification and distribution are subject to the
7 * Boost Software License, Version 1.0. (See accompanying file
8 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 *
10 */
11
12 /*
13  *   LOCATION:    see http://www.boost.org for most recent version.
14  *   FILE         match_results.cpp
15  *   VERSION      see <boost/version.hpp>
16  *   DESCRIPTION: Declares template class match_results.
17  */
18
19#ifndef BOOST_REGEX_V4_MATCH_RESULTS_HPP
20#define BOOST_REGEX_V4_MATCH_RESULTS_HPP
21
22#ifdef BOOST_HAS_ABI_HEADERS
23#  include BOOST_ABI_PREFIX
24#endif
25
26namespace boost{
27#ifdef BOOST_MSVC
28#pragma warning(push)
29#pragma warning(disable : 4251 4231 4660)
30#endif
31
32template <class BidiIterator, class Allocator>
33class match_results
34{
35private:
36#ifndef BOOST_NO_STD_ALLOCATOR
37   typedef          std::vector<sub_match<BidiIterator>, Allocator> vector_type;
38#else
39   typedef          std::vector<sub_match<BidiIterator> >           vector_type;
40#endif
41public:
42   typedef          sub_match<BidiIterator>                         value_type;
43#if  !defined(BOOST_NO_STD_ALLOCATOR) && !(defined(BOOST_MSVC) && defined(_STLPORT_VERSION))
44   typedef typename Allocator::const_reference                              const_reference;
45#else
46   typedef          const value_type&                                       const_reference;
47#endif
48   typedef          const_reference                                         reference;
49   typedef typename vector_type::const_iterator                             const_iterator;
50   typedef          const_iterator                                          iterator;
51   typedef typename re_detail::regex_iterator_traits<
52                                    BidiIterator>::difference_type          difference_type;
53   typedef typename Allocator::size_type                                    size_type;
54   typedef          Allocator                                               allocator_type;
55   typedef typename re_detail::regex_iterator_traits<
56                                    BidiIterator>::value_type               char_type;
57   typedef          std::basic_string<char_type>                            string_type;
58
59   // construct/copy/destroy:
60   explicit match_results(const Allocator& a = Allocator())
61#ifndef BOOST_NO_STD_ALLOCATOR
62      : m_subs(a), m_base() {}
63#else
64      : m_subs(), m_base() { (void)a; }
65#endif
66   match_results(const match_results& m)
67      : m_subs(m.m_subs), m_base(m.m_base) {}
68   match_results& operator=(const match_results& m)
69   {
70      m_subs = m.m_subs;
71      m_base = m.m_base;
72      return *this;
73   }
74   ~match_results(){}
75
76   // size:
77   size_type size() const
78   { return empty() ? 0 : m_subs.size() - 2; }
79   size_type max_size() const
80   { return m_subs.max_size(); }
81   bool empty() const
82   { return m_subs.size() < 2; }
83   // element access:
84   difference_type length(int sub = 0) const
85   {
86      sub += 2;
87      if((sub < (int)m_subs.size()) && (sub > 0))
88         return m_subs[sub].length();
89      return 0;
90   }
91   difference_type position(unsigned int sub = 0) const
92   {
93      sub += 2;
94      if(sub < m_subs.size())
95      {
96         const sub_match<BidiIterator>& s = m_subs[sub];
97         if(s.matched)
98         {
99            return ::boost::re_detail::distance((BidiIterator)(m_base), (BidiIterator)(s.first));
100         }
101      }
102      return ~static_cast<difference_type>(0);
103   }
104   string_type str(int sub = 0) const
105   {
106      sub += 2;
107      string_type result;
108      if(sub < (int)m_subs.size() && (sub > 0))
109      {
110         const sub_match<BidiIterator>& s = m_subs[sub];
111         if(s.matched)
112         {
113            result = s.str();
114         }
115      }
116      return result;
117   }
118   const_reference operator[](int sub) const
119   {
120      sub += 2;
121      if(sub < (int)m_subs.size() && (sub >= 0))
122      {
123         return m_subs[sub];
124      }
125      return m_null;
126   }
127
128   const_reference prefix() const
129   {
130      return (*this)[-1];
131   }
132
133   const_reference suffix() const
134   {
135      return (*this)[-2];
136   }
137   const_iterator begin() const
138   {
139      return (m_subs.size() > 2) ? (m_subs.begin() + 2) : m_subs.end();
140   }
141   const_iterator end() const
142   {
143      return m_subs.end();
144   }
145   // format:
146   template <class OutputIterator>
147   OutputIterator format(OutputIterator out,
148                         const string_type& fmt,
149                         match_flag_type flags = format_default) const
150   {
151      re_detail::trivial_format_traits<char_type> traits;
152      return re_detail::regex_format_imp(out, *this, fmt.data(), fmt.data() + fmt.size(), flags, traits);
153   }
154   string_type format(const string_type& fmt,
155                      match_flag_type flags = format_default) const
156   {
157      string_type result;
158      re_detail::string_out_iterator<string_type> i(result);
159      re_detail::trivial_format_traits<char_type> traits;
160      re_detail::regex_format_imp(i, *this, fmt.data(), fmt.data() + fmt.size(), flags, traits);
161      return result;
162   }
163   // format with locale:
164   template <class OutputIterator, class RegexT>
165   OutputIterator format(OutputIterator out,
166                         const string_type& fmt,
167                         match_flag_type flags,
168                         const RegexT& re) const
169   {
170      return ::boost::re_detail::regex_format_imp(out, *this, fmt.data(), fmt.data() + fmt.size(), flags, re.get_traits());
171   }
172   template <class RegexT>
173   string_type format(const string_type& fmt,
174                      match_flag_type flags,
175                      const RegexT& re) const
176   {
177      string_type result;
178      re_detail::string_out_iterator<string_type> i(result);
179      ::boost::re_detail::regex_format_imp(i, *this, fmt.data(), fmt.data() + fmt.size(), flags, re.get_traits());
180      return result;
181   }
182
183   allocator_type get_allocator() const
184   {
185#ifndef BOOST_NO_STD_ALLOCATOR
186      return m_subs.get_allocator();
187#else
188     return allocator_type();
189#endif
190   }
191   void swap(match_results& that)
192   {
193      std::swap(m_subs, that.m_subs);
194      std::swap(m_base, that.m_base);
195   }
196   bool operator==(const match_results& that)const
197   {
198      return (m_subs == that.m_subs) && (m_base == that.m_base);
199   }
200   bool operator!=(const match_results& that)const
201   { return !(*this == that); }
202
203#ifdef BOOST_REGEX_MATCH_EXTRA
204   typedef typename sub_match<BidiIterator>::capture_sequence_type capture_sequence_type;
205
206   const capture_sequence_type& captures(int i)const
207   {
208      return (*this)[i].captures();
209   }
210#endif
211
212   //
213   // private access functions:
214   void BOOST_REGEX_CALL set_second(BidiIterator i)
215   {
216      BOOST_ASSERT(m_subs.size() > 2);
217      m_subs[2].second = i;
218      m_subs[2].matched = true;
219      m_subs[0].first = i;
220      m_subs[0].matched = (m_subs[0].first != m_subs[0].second);
221      m_null.first = i;
222      m_null.second = i;
223      m_null.matched = false;
224   }
225
226   void BOOST_REGEX_CALL set_second(BidiIterator i, size_type pos, bool m = true)
227   {
228      pos += 2;
229      BOOST_ASSERT(m_subs.size() > pos);
230      m_subs[pos].second = i;
231      m_subs[pos].matched = m;
232      if(pos == 2)
233      {
234         m_subs[0].first = i;
235         m_subs[0].matched = (m_subs[0].first != m_subs[0].second);
236         m_null.first = i;
237         m_null.second = i;
238         m_null.matched = false;
239      }
240   }
241   void BOOST_REGEX_CALL set_size(size_type n, BidiIterator i, BidiIterator j)
242   {
243      value_type v(j);
244      size_type len = m_subs.size();
245      if(len > n + 2)
246      {
247         m_subs.erase(m_subs.begin()+n+2, m_subs.end());
248         std::fill(m_subs.begin(), m_subs.end(), v);
249      }
250      else
251      {
252         std::fill(m_subs.begin(), m_subs.end(), v);
253         if(n+2 != len)
254            m_subs.insert(m_subs.end(), n+2-len, v);
255      }
256      m_subs[1].first = i;
257   }
258   void BOOST_REGEX_CALL set_base(BidiIterator pos)
259   {
260      m_base = pos;
261   }
262   BidiIterator base()const
263   {
264      return m_base;
265   }
266   void BOOST_REGEX_CALL set_first(BidiIterator i)
267   {
268      // set up prefix:
269      m_subs[1].second = i;
270      m_subs[1].matched = (m_subs[1].first != i);
271      // set up $0:
272      m_subs[2].first = i;
273      // zero out everything else:
274      for(size_type n = 3; n < m_subs.size(); ++n)
275      {
276         m_subs[n].first = m_subs[n].second = m_subs[0].second;
277         m_subs[n].matched = false;
278      }
279   }
280   void BOOST_REGEX_CALL set_first(BidiIterator i, size_type pos)
281   {
282      BOOST_ASSERT(pos+2 < m_subs.size());
283      if(pos)
284         m_subs[pos+2].first = i;
285      else
286         set_first(i);
287   }
288   void BOOST_REGEX_CALL maybe_assign(const match_results<BidiIterator, Allocator>& m);
289
290
291private:
292   vector_type            m_subs; // subexpressions
293   BidiIterator   m_base; // where the search started from
294   sub_match<BidiIterator> m_null; // a null match
295};
296
297template <class BidiIterator, class Allocator>
298void BOOST_REGEX_CALL match_results<BidiIterator, Allocator>::maybe_assign(const match_results<BidiIterator, Allocator>& m)
299{
300   const_iterator p1, p2;
301   p1 = begin();
302   p2 = m.begin();
303   //
304   // Distances are measured from the start of *this* match, unless this isn't
305   // a valid match in which case we use the start of the whole sequence.  Note that
306   // no subsequent match-candidate can ever be to the left of the first match found.
307   // This ensures that when we are using bidirectional iterators, that distances
308   // measured are as short as possible, and therefore as efficient as possible
309   // to compute.  Finally note that we don't use the "matched" data member to test
310   // whether a sub-expression is a valid match, because partial matches set this
311   // to false for sub-expression 0.
312   //
313   BidiIterator end = this->suffix().second;
314   BidiIterator base = (p1->first == end) ? this->prefix().first : (*this)[0].first;
315   difference_type len1 = 0;
316   difference_type len2 = 0;
317   difference_type base1 = 0;
318   difference_type base2 = 0;
319   std::size_t i;
320   for(i = 0; i < size(); ++i, ++p1, ++p2)
321   {
322      //
323      // Leftmost takes priority over longest; handle special cases
324      // where distances need not be computed first (an optimisation
325      // for bidirectional iterators: ensure that we don't accidently
326      // compute the length of the whole sequence, as this can be really
327      // expensive).
328      //
329      if(p1->first == end)
330      {
331         if(p2->first != end)
332         {
333            // p2 must be better than p1, and no need to calculate
334            // actual distances:
335            base1 = 1;
336            base2 = 0;
337            break;
338         }
339         else
340         {
341            // *p1 and *p2 are either unmatched or match end-of sequence,
342            // either way no need to calculate distances:
343            if((p1->matched == false) && (p2->matched == true))
344               break;
345            if((p1->matched == true) && (p2->matched == false))
346               return;
347            continue;
348         }
349      }
350      else if(p2->first == end)
351      {
352         // p1 better than p2, and no need to calculate distances:
353         return;
354      }
355      base1 = ::boost::re_detail::distance(base, p1->first);
356      base2 = ::boost::re_detail::distance(base, p2->first);
357      BOOST_ASSERT(base1 >= 0);
358      BOOST_ASSERT(base2 >= 0);
359      if(base1 < base2) return;
360      if(base2 < base1) break;
361
362      len1 = ::boost::re_detail::distance((BidiIterator)p1->first, (BidiIterator)p1->second);
363      len2 = ::boost::re_detail::distance((BidiIterator)p2->first, (BidiIterator)p2->second);
364      BOOST_ASSERT(len1 >= 0);
365      BOOST_ASSERT(len2 >= 0);
366      if((len1 != len2) || ((p1->matched == false) && (p2->matched == true)))
367         break;
368      if((p1->matched == true) && (p2->matched == false))
369         return;
370   }
371   if(i == size())
372      return;
373   if(base2 < base1)
374      *this = m;
375   else if((len2 > len1) || ((p1->matched == false) && (p2->matched == true)) )
376      *this = m;
377}
378
379template <class BidiIterator, class Allocator>
380void swap(match_results<BidiIterator, Allocator>& a, match_results<BidiIterator, Allocator>& b)
381{
382   a.swap(b);
383}
384
385#ifndef BOOST_NO_STD_LOCALE
386template <class charT, class traits, class BidiIterator, class Allocator>
387std::basic_ostream<charT, traits>&
388   operator << (std::basic_ostream<charT, traits>& os,
389                const match_results<BidiIterator, Allocator>& s)
390{
391   return (os << s.str());
392}
393#else
394template <class BidiIterator, class Allocator>
395std::ostream& operator << (std::ostream& os,
396                           const match_results<BidiIterator, Allocator>& s)
397{
398   return (os << s.str());
399}
400#endif
401
402#ifdef BOOST_MSVC
403#pragma warning(pop)
404#endif
405} // namespace boost
406
407#ifdef BOOST_HAS_ABI_HEADERS
408#  include BOOST_ABI_SUFFIX
409#endif
410
411#endif
412
Note: See TracBrowser for help on using the repository browser.