1 /*
2 *
3 * Copyright (c) 1998-2004
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 basic_regex.cpp
15 * VERSION see <boost/version.hpp>
16 * DESCRIPTION: Declares template class basic_regex.
17 */
18
19 #ifndef BOOST_REGEX_V4_BASIC_REGEX_HPP
20 #define BOOST_REGEX_V4_BASIC_REGEX_HPP
21
22 #ifdef BOOST_HAS_ABI_HEADERS
23 # include BOOST_ABI_PREFIX
24 #endif
25
26 namespace boost{
27 #ifdef BOOST_MSVC
28 #pragma warning(push)
29 #pragma warning(disable : 4251 4231 4660)
30 #endif
31
32 namespace re_detail{
33
34 //
35 // forward declaration, we will need this one later:
36 //
37 template <class charT, class traits>
38 class basic_regex_parser;
39
40 //
41 // class regex_data:
42 // represents the data we wish to expose to the matching algorithms.
43 //
44 template <class charT, class traits>
45 struct regex_data
46 {
47 typedef regex_constants::syntax_option_type flag_type;
48 typedef std::size_t size_type;
49
regex_databoost::re_detail::regex_data50 regex_data(const ::boost::shared_ptr<
51 ::boost::regex_traits_wrapper<traits> >& t)
52 : m_ptraits(t), m_expression(0), m_expression_len(0) {}
regex_databoost::re_detail::regex_data53 regex_data()
54 : m_ptraits(new ::boost::regex_traits_wrapper<traits>()), m_expression(0), m_expression_len(0) {}
55
56 ::boost::shared_ptr<
57 ::boost::regex_traits_wrapper<traits>
58 > m_ptraits; // traits class instance
59 flag_type m_flags; // flags with which we were compiled
60 int m_status; // error code (0 implies OK).
61 const charT* m_expression; // the original expression
62 std::ptrdiff_t m_expression_len; // the length of the original expression
63 size_type m_mark_count; // the number of marked sub-expressions
64 re_detail::re_syntax_base* m_first_state; // the first state of the machine
65 unsigned m_restart_type; // search optimisation type
66 unsigned char m_startmap[1 << CHAR_BIT]; // which characters can start a match
67 unsigned int m_can_be_null; // whether we can match a null string
68 re_detail::raw_storage m_data; // the buffer in which our states are constructed
69 };
70 //
71 // class basic_regex_implementation
72 // pimpl implementation class for basic_regex.
73 //
74 template <class charT, class traits>
75 class basic_regex_implementation
76 : public regex_data<charT, traits>
77 {
78 public:
79 typedef regex_constants::syntax_option_type flag_type;
80 typedef std::ptrdiff_t difference_type;
81 typedef std::size_t size_type;
82 typedef typename traits::locale_type locale_type;
83 typedef const charT* const_iterator;
84
basic_regex_implementation()85 basic_regex_implementation(){}
basic_regex_implementation(const::boost::shared_ptr<::boost::regex_traits_wrapper<traits>> & t)86 basic_regex_implementation(const ::boost::shared_ptr<
87 ::boost::regex_traits_wrapper<traits> >& t)
88 : regex_data<charT, traits>(t) {}
assign(const charT * arg_first,const charT * arg_last,flag_type f)89 void assign(const charT* arg_first,
90 const charT* arg_last,
91 flag_type f)
92 {
93 regex_data<charT, traits>* pdat = this;
94 basic_regex_parser<charT, traits> parser(pdat);
95 parser.parse(arg_first, arg_last, f);
96 }
97
imbue(locale_type l)98 locale_type BOOST_REGEX_CALL imbue(locale_type l)
99 {
100 return this->m_ptraits->imbue(l);
101 }
getloc() const102 locale_type BOOST_REGEX_CALL getloc()const
103 {
104 return this->m_ptraits->getloc();
105 }
str() const106 std::basic_string<charT> BOOST_REGEX_CALL str()const
107 {
108 std::basic_string<charT> result;
109 if(this->m_status == 0)
110 result = std::basic_string<charT>(this->m_expression, this->m_expression_len);
111 return result;
112 }
expression() const113 const_iterator BOOST_REGEX_CALL expression()const
114 {
115 return this->m_expression;
116 }
117 //
118 // begin, end:
begin() const119 const_iterator BOOST_REGEX_CALL begin()const
120 {
121 return (!this->m_status ? 0 : this->m_expression);
122 }
end() const123 const_iterator BOOST_REGEX_CALL end()const
124 {
125 return (!this->m_status ? 0 : this->m_expression + this->m_expression_len);
126 }
flags() const127 flag_type BOOST_REGEX_CALL flags()const
128 {
129 return this->m_flags;
130 }
size() const131 size_type BOOST_REGEX_CALL size()const
132 {
133 return this->m_expression_len;
134 }
status() const135 int BOOST_REGEX_CALL status()const
136 {
137 return this->m_status;
138 }
mark_count() const139 size_type BOOST_REGEX_CALL mark_count()const
140 {
141 return this->m_mark_count;
142 }
get_first_state() const143 const re_detail::re_syntax_base* get_first_state()const
144 {
145 return this->m_first_state;
146 }
get_restart_type() const147 unsigned get_restart_type()const
148 {
149 return this->m_restart_type;
150 }
get_map() const151 const unsigned char* get_map()const
152 {
153 return this->m_startmap;
154 }
get_traits() const155 const ::boost::regex_traits_wrapper<traits>& get_traits()const
156 {
157 return *(this->m_ptraits);
158 }
can_be_null() const159 bool can_be_null()const
160 {
161 return this->m_can_be_null;
162 }
get_data() const163 const regex_data<charT, traits>& get_data()const
164 {
165 basic_regex_implementation<charT, traits> const* p = this;
166 return *static_cast<const regex_data<charT, traits>*>(p);
167 }
168 };
169
170 } // namespace re_detail
171 //
172 // class basic_regex:
173 // represents the compiled
174 // regular expression:
175 //
176
177 #ifdef BOOST_REGEX_NO_FWD
178 template <class charT, class traits = regex_traits<charT> >
179 #else
180 template <class charT, class traits >
181 #endif
182 class basic_regex : public regbase
183 {
184 public:
185 // typedefs:
186 typedef typename traits::size_type traits_size_type;
187 typedef typename traits::string_type traits_string_type;
188 typedef charT char_type;
189 typedef traits traits_type;
190
191 typedef charT value_type;
192 typedef charT& reference;
193 typedef const charT& const_reference;
194 typedef const charT* const_iterator;
195 typedef const_iterator iterator;
196 typedef std::ptrdiff_t difference_type;
197 typedef std::size_t size_type;
198 typedef regex_constants::syntax_option_type flag_type;
199 // locale_type
200 // placeholder for actual locale type used by the
201 // traits class to localise *this.
202 typedef typename traits::locale_type locale_type;
203
204 public:
basic_regex()205 explicit basic_regex(){}
basic_regex(const charT * p,flag_type f=regex_constants::normal)206 explicit basic_regex(const charT* p, flag_type f = regex_constants::normal)
207 {
208 assign(p, f);
209 }
basic_regex(const charT * p1,const charT * p2,flag_type f=regex_constants::normal)210 basic_regex(const charT* p1, const charT* p2, flag_type f = regex_constants::normal)
211 {
212 assign(p1, p2, f);
213 }
basic_regex(const charT * p,size_type len,flag_type f)214 basic_regex(const charT* p, size_type len, flag_type f)
215 {
216 assign(p, len, f);
217 }
basic_regex(const basic_regex & that)218 basic_regex(const basic_regex& that)
219 : m_pimpl(that.m_pimpl) {}
~basic_regex()220 ~basic_regex(){}
operator =(const basic_regex & that)221 basic_regex& BOOST_REGEX_CALL operator=(const basic_regex& that)
222 {
223 return assign(that);
224 }
operator =(const charT * ptr)225 basic_regex& BOOST_REGEX_CALL operator=(const charT* ptr)
226 {
227 return assign(ptr);
228 }
229
230 //
231 // assign:
assign(const basic_regex & that)232 basic_regex& assign(const basic_regex& that)
233 {
234 m_pimpl = that.m_pimpl;
235 return *this;
236 }
assign(const charT * p,flag_type f=regex_constants::normal)237 basic_regex& assign(const charT* p, flag_type f = regex_constants::normal)
238 {
239 return assign(p, p + traits::length(p), f);
240 }
assign(const charT * p,size_type len,flag_type f)241 basic_regex& assign(const charT* p, size_type len, flag_type f)
242 {
243 return assign(p, p + len, f);
244 }
245 private:
246 basic_regex& do_assign(const charT* p1,
247 const charT* p2,
248 flag_type f);
249 public:
assign(const charT * p1,const charT * p2,flag_type f=regex_constants::normal)250 basic_regex& assign(const charT* p1,
251 const charT* p2,
252 flag_type f = regex_constants::normal)
253 {
254 return do_assign(p1, p2, f);
255 }
256 #if !defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(__IBMCPP__)
257
258 template <class ST, class SA>
set_expression(const std::basic_string<charT,ST,SA> & p,flag_type f=regex_constants::normal)259 unsigned int BOOST_REGEX_CALL set_expression(const std::basic_string<charT, ST, SA>& p, flag_type f = regex_constants::normal)
260 {
261 return set_expression(p.data(), p.data() + p.size(), f);
262 }
263
264 template <class ST, class SA>
basic_regex(const std::basic_string<charT,ST,SA> & p,flag_type f=regex_constants::normal)265 explicit basic_regex(const std::basic_string<charT, ST, SA>& p, flag_type f = regex_constants::normal)
266 {
267 assign(p, f);
268 }
269
270 template <class InputIterator>
basic_regex(InputIterator arg_first,InputIterator arg_last,flag_type f=regex_constants::normal)271 basic_regex(InputIterator arg_first, InputIterator arg_last, flag_type f = regex_constants::normal)
272 {
273 typedef typename traits::string_type seq_type;
274 seq_type a(arg_first, arg_last);
275 if(a.size())
276 assign(&*a.begin(), &*a.begin() + a.size(), f);
277 else
278 assign(static_cast<const charT*>(0), static_cast<const charT*>(0), f);
279 }
280
281 template <class ST, class SA>
operator =(const std::basic_string<charT,ST,SA> & p)282 basic_regex& BOOST_REGEX_CALL operator=(const std::basic_string<charT, ST, SA>& p)
283 {
284 return assign(p.data(), p.data() + p.size(), regex_constants::normal);
285 }
286
287 template <class string_traits, class A>
assign(const std::basic_string<charT,string_traits,A> & s,flag_type f=regex_constants::normal)288 basic_regex& BOOST_REGEX_CALL assign(
289 const std::basic_string<charT, string_traits, A>& s,
290 flag_type f = regex_constants::normal)
291 {
292 return assign(s.data(), s.data() + s.size(), f);
293 }
294
295 template <class InputIterator>
assign(InputIterator arg_first,InputIterator arg_last,flag_type f=regex_constants::normal)296 basic_regex& BOOST_REGEX_CALL assign(InputIterator arg_first,
297 InputIterator arg_last,
298 flag_type f = regex_constants::normal)
299 {
300 typedef typename traits::string_type seq_type;
301 seq_type a(arg_first, arg_last);
302 if(a.size())
303 {
304 const charT* p1 = &*a.begin();
305 const charT* p2 = &*a.begin() + a.size();
306 return assign(p1, p2, f);
307 }
308 return assign(static_cast<const charT*>(0), static_cast<const charT*>(0), f);
309 }
310 #else
set_expression(const std::basic_string<charT> & p,flag_type f=regex_constants::normal)311 unsigned int BOOST_REGEX_CALL set_expression(const std::basic_string<charT>& p, flag_type f = regex_constants::normal)
312 {
313 return set_expression(p.data(), p.data() + p.size(), f);
314 }
315
basic_regex(const std::basic_string<charT> & p,flag_type f=regex_constants::normal)316 basic_regex(const std::basic_string<charT>& p, flag_type f = regex_constants::normal)
317 {
318 assign(p, f);
319 }
320
operator =(const std::basic_string<charT> & p)321 basic_regex& BOOST_REGEX_CALL operator=(const std::basic_string<charT>& p)
322 {
323 return assign(p.data(), p.data() + p.size(), regex_constants::normal);
324 }
325
assign(const std::basic_string<charT> & s,flag_type f=regex_constants::normal)326 basic_regex& BOOST_REGEX_CALL assign(
327 const std::basic_string<charT>& s,
328 flag_type f = regex_constants::normal)
329 {
330 return assign(s.data(), s.data() + s.size(), f);
331 }
332
333 #endif
334
335 //
336 // locale:
337 locale_type BOOST_REGEX_CALL imbue(locale_type l);
getloc() const338 locale_type BOOST_REGEX_CALL getloc()const
339 {
340 return m_pimpl.get() ? m_pimpl->getloc() : locale_type();
341 }
342 //
343 // getflags:
344 // retained for backwards compatibility only, "flags"
345 // is now the prefered name:
getflags() const346 flag_type BOOST_REGEX_CALL getflags()const
347 {
348 return flags();
349 }
flags() const350 flag_type BOOST_REGEX_CALL flags()const
351 {
352 return m_pimpl.get() ? m_pimpl->flags() : 0;
353 }
354 //
355 // str:
str() const356 std::basic_string<charT> BOOST_REGEX_CALL str()const
357 {
358 return m_pimpl.get() ? m_pimpl->str() : std::basic_string<charT>();
359 }
360 //
361 // begin, end:
begin() const362 const_iterator BOOST_REGEX_CALL begin()const
363 {
364 return (m_pimpl.get() ? m_pimpl->begin() : 0);
365 }
end() const366 const_iterator BOOST_REGEX_CALL end()const
367 {
368 return (m_pimpl.get() ? m_pimpl->end() : 0);
369 }
370 //
371 // swap:
swap(basic_regex & that)372 void BOOST_REGEX_CALL swap(basic_regex& that)throw()
373 {
374 m_pimpl.swap(that.m_pimpl);
375 }
376 //
377 // size:
size() const378 size_type BOOST_REGEX_CALL size()const
379 {
380 return (m_pimpl.get() ? m_pimpl->size() : 0);
381 }
382 //
383 // max_size:
max_size() const384 size_type BOOST_REGEX_CALL max_size()const
385 {
386 return UINT_MAX;
387 }
388 //
389 // empty:
empty() const390 bool BOOST_REGEX_CALL empty()const
391 {
392 return (m_pimpl.get() ? 0 != m_pimpl->status() : true);
393 }
394
mark_count() const395 size_type BOOST_REGEX_CALL mark_count()const
396 {
397 return (m_pimpl.get() ? m_pimpl->mark_count() : 0);
398 }
399
status() const400 int status()const
401 {
402 return (m_pimpl.get() ? m_pimpl->status() : regex_constants::error_empty);
403 }
404
compare(const basic_regex & that) const405 int BOOST_REGEX_CALL compare(const basic_regex& that) const
406 {
407 if(m_pimpl.get() == that.m_pimpl.get())
408 return 0;
409 if(!m_pimpl.get())
410 return -1;
411 if(!that.m_pimpl.get())
412 return 1;
413 if(status() != that.status())
414 return status() - that.status();
415 if(flags() != that.flags())
416 return flags() - that.flags();
417 return str().compare(that.str());
418 }
operator ==(const basic_regex & e) const419 bool BOOST_REGEX_CALL operator==(const basic_regex& e)const
420 {
421 return compare(e) == 0;
422 }
operator !=(const basic_regex & e) const423 bool BOOST_REGEX_CALL operator != (const basic_regex& e)const
424 {
425 return compare(e) != 0;
426 }
operator <(const basic_regex & e) const427 bool BOOST_REGEX_CALL operator<(const basic_regex& e)const
428 {
429 return compare(e) < 0;
430 }
operator >(const basic_regex & e) const431 bool BOOST_REGEX_CALL operator>(const basic_regex& e)const
432 {
433 return compare(e) > 0;
434 }
operator <=(const basic_regex & e) const435 bool BOOST_REGEX_CALL operator<=(const basic_regex& e)const
436 {
437 return compare(e) <= 0;
438 }
operator >=(const basic_regex & e) const439 bool BOOST_REGEX_CALL operator>=(const basic_regex& e)const
440 {
441 return compare(e) >= 0;
442 }
443
444 //
445 // The following are deprecated as public interfaces
446 // but are available for compatibility with earlier versions.
expression() const447 const charT* BOOST_REGEX_CALL expression()const
448 {
449 return (m_pimpl.get() && !m_pimpl->status() ? m_pimpl->expression() : 0);
450 }
set_expression(const charT * p1,const charT * p2,flag_type f=regex_constants::normal)451 unsigned int BOOST_REGEX_CALL set_expression(const charT* p1, const charT* p2, flag_type f = regex_constants::normal)
452 {
453 assign(p1, p2, f | regex_constants::no_except);
454 return status();
455 }
set_expression(const charT * p,flag_type f=regex_constants::normal)456 unsigned int BOOST_REGEX_CALL set_expression(const charT* p, flag_type f = regex_constants::normal)
457 {
458 assign(p, f | regex_constants::no_except);
459 return status();
460 }
error_code() const461 unsigned int BOOST_REGEX_CALL error_code()const
462 {
463 return status();
464 }
465 //
466 // private access methods:
467 //
get_first_state() const468 const re_detail::re_syntax_base* get_first_state()const
469 {
470 BOOST_ASSERT(0 != m_pimpl.get());
471 return m_pimpl->get_first_state();
472 }
get_restart_type() const473 unsigned get_restart_type()const
474 {
475 BOOST_ASSERT(0 != m_pimpl.get());
476 return m_pimpl->get_restart_type();
477 }
get_map() const478 const unsigned char* get_map()const
479 {
480 BOOST_ASSERT(0 != m_pimpl.get());
481 return m_pimpl->get_map();
482 }
get_traits() const483 const ::boost::regex_traits_wrapper<traits>& get_traits()const
484 {
485 BOOST_ASSERT(0 != m_pimpl.get());
486 return m_pimpl->get_traits();
487 }
can_be_null() const488 bool can_be_null()const
489 {
490 BOOST_ASSERT(0 != m_pimpl.get());
491 return m_pimpl->can_be_null();
492 }
get_data() const493 const re_detail::regex_data<charT, traits>& get_data()const
494 {
495 BOOST_ASSERT(0 != m_pimpl.get());
496 return m_pimpl->get_data();
497 }
498
499 private:
500 shared_ptr<re_detail::basic_regex_implementation<charT, traits> > m_pimpl;
501 };
502
503 //
504 // out of line members;
505 // these are the only members that mutate the basic_regex object,
506 // and are designed to provide the strong exception guarentee
507 // (in the event of a throw, the state of the object remains unchanged).
508 //
509 template <class charT, class traits>
do_assign(const charT * p1,const charT * p2,flag_type f)510 basic_regex<charT, traits>& basic_regex<charT, traits>::do_assign(const charT* p1,
511 const charT* p2,
512 flag_type f)
513 {
514 shared_ptr<re_detail::basic_regex_implementation<charT, traits> > temp;
515 if(!m_pimpl.get())
516 {
517 temp = shared_ptr<re_detail::basic_regex_implementation<charT, traits> >(new re_detail::basic_regex_implementation<charT, traits>());
518 }
519 else
520 {
521 temp = shared_ptr<re_detail::basic_regex_implementation<charT, traits> >(new re_detail::basic_regex_implementation<charT, traits>(m_pimpl->m_ptraits));
522 }
523 temp->assign(p1, p2, f);
524 temp.swap(m_pimpl);
525 return *this;
526 }
527
528 template <class charT, class traits>
imbue(locale_type l)529 typename basic_regex<charT, traits>::locale_type BOOST_REGEX_CALL basic_regex<charT, traits>::imbue(locale_type l)
530 {
531 shared_ptr<re_detail::basic_regex_implementation<charT, traits> > temp(new re_detail::basic_regex_implementation<charT, traits>());
532 locale_type result = temp->imbue(l);
533 temp.swap(m_pimpl);
534 return result;
535 }
536
537 //
538 // non-members:
539 //
540 template <class charT, class traits>
swap(basic_regex<charT,traits> & e1,basic_regex<charT,traits> & e2)541 void swap(basic_regex<charT, traits>& e1, basic_regex<charT, traits>& e2)
542 {
543 e1.swap(e2);
544 }
545
546 #ifndef BOOST_NO_STD_LOCALE
547 template <class charT, class traits, class traits2>
548 std::basic_ostream<charT, traits>&
operator <<(std::basic_ostream<charT,traits> & os,const basic_regex<charT,traits2> & e)549 operator << (std::basic_ostream<charT, traits>& os,
550 const basic_regex<charT, traits2>& e)
551 {
552 return (os << e.str());
553 }
554 #else
555 template <class traits>
operator <<(std::ostream & os,const basic_regex<char,traits> & e)556 std::ostream& operator << (std::ostream& os, const basic_regex<char, traits>& e)
557 {
558 return (os << e.str());
559 }
560 #endif
561
562 //
563 // class reg_expression:
564 // this is provided for backwards compatibility only,
565 // it is deprecated, no not use!
566 //
567 #ifdef BOOST_REGEX_NO_FWD
568 template <class charT, class traits = regex_traits<charT> >
569 #else
570 template <class charT, class traits >
571 #endif
572 class reg_expression : public basic_regex<charT, traits>
573 {
574 public:
575 typedef typename basic_regex<charT, traits>::flag_type flag_type;
576 typedef typename basic_regex<charT, traits>::size_type size_type;
reg_expression()577 explicit reg_expression(){}
reg_expression(const charT * p,flag_type f=regex_constants::normal)578 explicit reg_expression(const charT* p, flag_type f = regex_constants::normal)
579 : basic_regex<charT, traits>(p, f){}
reg_expression(const charT * p1,const charT * p2,flag_type f=regex_constants::normal)580 reg_expression(const charT* p1, const charT* p2, flag_type f = regex_constants::normal)
581 : basic_regex<charT, traits>(p1, p2, f){}
reg_expression(const charT * p,size_type len,flag_type f)582 reg_expression(const charT* p, size_type len, flag_type f)
583 : basic_regex<charT, traits>(p, len, f){}
reg_expression(const reg_expression & that)584 reg_expression(const reg_expression& that)
585 : basic_regex<charT, traits>(that) {}
~reg_expression()586 ~reg_expression(){}
operator =(const reg_expression & that)587 reg_expression& BOOST_REGEX_CALL operator=(const reg_expression& that)
588 {
589 return this->assign(that);
590 }
591
592 #if !defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(__IBMCPP__)
593 template <class ST, class SA>
reg_expression(const std::basic_string<charT,ST,SA> & p,flag_type f=regex_constants::normal)594 explicit reg_expression(const std::basic_string<charT, ST, SA>& p, flag_type f = regex_constants::normal)
595 : basic_regex<charT, traits>(p, f)
596 {
597 }
598
599 template <class InputIterator>
reg_expression(InputIterator arg_first,InputIterator arg_last,flag_type f=regex_constants::normal)600 reg_expression(InputIterator arg_first, InputIterator arg_last, flag_type f = regex_constants::normal)
601 : basic_regex<charT, traits>(arg_first, arg_last, f)
602 {
603 }
604
605 template <class ST, class SA>
operator =(const std::basic_string<charT,ST,SA> & p)606 reg_expression& BOOST_REGEX_CALL operator=(const std::basic_string<charT, ST, SA>& p)
607 {
608 this->assign(p);
609 return *this;
610 }
611 #else
reg_expression(const std::basic_string<charT> & p,flag_type f=regex_constants::normal)612 explicit reg_expression(const std::basic_string<charT>& p, flag_type f = regex_constants::normal)
613 : basic_regex<charT, traits>(p, f)
614 {
615 }
616
operator =(const std::basic_string<charT> & p)617 reg_expression& BOOST_REGEX_CALL operator=(const std::basic_string<charT>& p)
618 {
619 this->assign(p);
620 return *this;
621 }
622 #endif
623
624 };
625
626 #ifdef BOOST_MSVC
627 #pragma warning (pop)
628 #endif
629
630 } // namespace boost
631
632 #ifdef BOOST_HAS_ABI_HEADERS
633 # include BOOST_ABI_SUFFIX
634 #endif
635
636 #endif
637
638