File indexing completed on 2025-01-18 09:51:22
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #ifndef BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED
0020 #define BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED
0021
0022 #include <boost/config.hpp>
0023 #include <boost/integer.hpp>
0024 #include <boost/type_traits/make_unsigned.hpp>
0025
0026 #ifndef BOOST_NO_STD_LOCALE
0027
0028 #ifndef BOOST_RE_PAT_EXCEPT_HPP
0029 #include <boost/regex/pattern_except.hpp>
0030 #endif
0031 #ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED
0032 #include <boost/regex/v4/regex_traits_defaults.hpp>
0033 #endif
0034 #ifdef BOOST_HAS_THREADS
0035 #include <boost/regex/pending/static_mutex.hpp>
0036 #endif
0037 #ifndef BOOST_REGEX_PRIMARY_TRANSFORM
0038 #include <boost/regex/v4/primary_transform.hpp>
0039 #endif
0040 #ifndef BOOST_REGEX_OBJECT_CACHE_HPP
0041 #include <boost/regex/v4/object_cache.hpp>
0042 #endif
0043
0044 #include <climits>
0045 #include <ios>
0046 #include <istream>
0047
0048 #ifdef BOOST_MSVC
0049 #pragma warning(push)
0050 #pragma warning(disable: 4103)
0051 #endif
0052 #ifdef BOOST_HAS_ABI_HEADERS
0053 # include BOOST_ABI_PREFIX
0054 #endif
0055 #ifdef BOOST_MSVC
0056 #pragma warning(pop)
0057 #endif
0058
0059 #ifdef BOOST_MSVC
0060 #pragma warning(push)
0061 #pragma warning(disable:4786 4251)
0062 #endif
0063
0064 namespace boost{
0065
0066
0067
0068
0069 template <class charT>
0070 class cpp_regex_traits;
0071
0072 namespace BOOST_REGEX_DETAIL_NS{
0073
0074
0075
0076
0077
0078 template <class charT,
0079 class traits = ::std::char_traits<charT> >
0080 class parser_buf : public ::std::basic_streambuf<charT, traits>
0081 {
0082 typedef ::std::basic_streambuf<charT, traits> base_type;
0083 typedef typename base_type::int_type int_type;
0084 typedef typename base_type::char_type char_type;
0085 typedef typename base_type::pos_type pos_type;
0086 typedef ::std::streamsize streamsize;
0087 typedef typename base_type::off_type off_type;
0088 public:
0089 parser_buf() : base_type() { setbuf(0, 0); }
0090 const charT* getnext() { return this->gptr(); }
0091 protected:
0092 std::basic_streambuf<charT, traits>* setbuf(char_type* s, streamsize n) BOOST_OVERRIDE;
0093 typename parser_buf<charT, traits>::pos_type seekpos(pos_type sp, ::std::ios_base::openmode which) BOOST_OVERRIDE;
0094 typename parser_buf<charT, traits>::pos_type seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which) BOOST_OVERRIDE;
0095 private:
0096 parser_buf& operator=(const parser_buf&);
0097 parser_buf(const parser_buf&);
0098 };
0099
0100 template<class charT, class traits>
0101 std::basic_streambuf<charT, traits>*
0102 parser_buf<charT, traits>::setbuf(char_type* s, streamsize n)
0103 {
0104 this->setg(s, s, s + n);
0105 return this;
0106 }
0107
0108 template<class charT, class traits>
0109 typename parser_buf<charT, traits>::pos_type
0110 parser_buf<charT, traits>::seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which)
0111 {
0112 typedef typename boost::int_t<sizeof(way) * CHAR_BIT>::least cast_type;
0113
0114 if(which & ::std::ios_base::out)
0115 return pos_type(off_type(-1));
0116 std::ptrdiff_t size = this->egptr() - this->eback();
0117 std::ptrdiff_t pos = this->gptr() - this->eback();
0118 charT* g = this->eback();
0119 switch(static_cast<cast_type>(way))
0120 {
0121 case ::std::ios_base::beg:
0122 if((off < 0) || (off > size))
0123 return pos_type(off_type(-1));
0124 else
0125 this->setg(g, g + off, g + size);
0126 break;
0127 case ::std::ios_base::end:
0128 if((off < 0) || (off > size))
0129 return pos_type(off_type(-1));
0130 else
0131 this->setg(g, g + size - off, g + size);
0132 break;
0133 case ::std::ios_base::cur:
0134 {
0135 std::ptrdiff_t newpos = static_cast<std::ptrdiff_t>(pos + off);
0136 if((newpos < 0) || (newpos > size))
0137 return pos_type(off_type(-1));
0138 else
0139 this->setg(g, g + newpos, g + size);
0140 break;
0141 }
0142 default: ;
0143 }
0144 #ifdef BOOST_MSVC
0145 #pragma warning(push)
0146 #pragma warning(disable:4244)
0147 #endif
0148 return static_cast<pos_type>(this->gptr() - this->eback());
0149 #ifdef BOOST_MSVC
0150 #pragma warning(pop)
0151 #endif
0152 }
0153
0154 template<class charT, class traits>
0155 typename parser_buf<charT, traits>::pos_type
0156 parser_buf<charT, traits>::seekpos(pos_type sp, ::std::ios_base::openmode which)
0157 {
0158 if(which & ::std::ios_base::out)
0159 return pos_type(off_type(-1));
0160 off_type size = static_cast<off_type>(this->egptr() - this->eback());
0161 charT* g = this->eback();
0162 if(off_type(sp) <= size)
0163 {
0164 this->setg(g, g + off_type(sp), g + size);
0165 }
0166 return pos_type(off_type(-1));
0167 }
0168
0169
0170
0171
0172
0173 template <class charT>
0174 struct cpp_regex_traits_base
0175 {
0176 cpp_regex_traits_base(const std::locale& l)
0177 { (void)imbue(l); }
0178 std::locale imbue(const std::locale& l);
0179
0180 std::locale m_locale;
0181 std::ctype<charT> const* m_pctype;
0182 #ifndef BOOST_NO_STD_MESSAGES
0183 std::messages<charT> const* m_pmessages;
0184 #endif
0185 std::collate<charT> const* m_pcollate;
0186
0187 bool operator<(const cpp_regex_traits_base& b)const
0188 {
0189 if(m_pctype == b.m_pctype)
0190 {
0191 #ifndef BOOST_NO_STD_MESSAGES
0192 if(m_pmessages == b.m_pmessages)
0193 {
0194 return m_pcollate < b.m_pcollate;
0195 }
0196 return m_pmessages < b.m_pmessages;
0197 #else
0198 return m_pcollate < b.m_pcollate;
0199 #endif
0200 }
0201 return m_pctype < b.m_pctype;
0202 }
0203 bool operator==(const cpp_regex_traits_base& b)const
0204 {
0205 return (m_pctype == b.m_pctype)
0206 #ifndef BOOST_NO_STD_MESSAGES
0207 && (m_pmessages == b.m_pmessages)
0208 #endif
0209 && (m_pcollate == b.m_pcollate);
0210 }
0211 };
0212
0213 template <class charT>
0214 std::locale cpp_regex_traits_base<charT>::imbue(const std::locale& l)
0215 {
0216 std::locale result(m_locale);
0217 m_locale = l;
0218 m_pctype = &BOOST_USE_FACET(std::ctype<charT>, l);
0219 #ifndef BOOST_NO_STD_MESSAGES
0220 m_pmessages = BOOST_HAS_FACET(std::messages<charT>, l) ? &BOOST_USE_FACET(std::messages<charT>, l) : 0;
0221 #endif
0222 m_pcollate = &BOOST_USE_FACET(std::collate<charT>, l);
0223 return result;
0224 }
0225
0226
0227
0228
0229
0230 template <class charT>
0231 class cpp_regex_traits_char_layer : public cpp_regex_traits_base<charT>
0232 {
0233 typedef std::basic_string<charT> string_type;
0234 typedef std::map<charT, regex_constants::syntax_type> map_type;
0235 typedef typename map_type::const_iterator map_iterator_type;
0236 public:
0237 cpp_regex_traits_char_layer(const std::locale& l)
0238 : cpp_regex_traits_base<charT>(l)
0239 {
0240 init();
0241 }
0242 cpp_regex_traits_char_layer(const cpp_regex_traits_base<charT>& b)
0243 : cpp_regex_traits_base<charT>(b)
0244 {
0245 init();
0246 }
0247 void init();
0248
0249 regex_constants::syntax_type syntax_type(charT c)const
0250 {
0251 map_iterator_type i = m_char_map.find(c);
0252 return ((i == m_char_map.end()) ? 0 : i->second);
0253 }
0254 regex_constants::escape_syntax_type escape_syntax_type(charT c) const
0255 {
0256 map_iterator_type i = m_char_map.find(c);
0257 if(i == m_char_map.end())
0258 {
0259 if(this->m_pctype->is(std::ctype_base::lower, c)) return regex_constants::escape_type_class;
0260 if(this->m_pctype->is(std::ctype_base::upper, c)) return regex_constants::escape_type_not_class;
0261 return 0;
0262 }
0263 return i->second;
0264 }
0265
0266 private:
0267 string_type get_default_message(regex_constants::syntax_type);
0268
0269 map_type m_char_map;
0270 };
0271
0272 template <class charT>
0273 void cpp_regex_traits_char_layer<charT>::init()
0274 {
0275
0276
0277 #ifndef BOOST_NO_STD_MESSAGES
0278 #ifndef __IBMCPP__
0279 typename std::messages<charT>::catalog cat = static_cast<std::messages<char>::catalog>(-1);
0280 #else
0281 typename std::messages<charT>::catalog cat = reinterpret_cast<std::messages<char>::catalog>(-1);
0282 #endif
0283 std::string cat_name(cpp_regex_traits<charT>::get_catalog_name());
0284 if((!cat_name.empty()) && (this->m_pmessages != 0))
0285 {
0286 cat = this->m_pmessages->open(
0287 cat_name,
0288 this->m_locale);
0289 if((int)cat < 0)
0290 {
0291 std::string m("Unable to open message catalog: ");
0292 std::runtime_error err(m + cat_name);
0293 boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err);
0294 }
0295 }
0296
0297
0298
0299 if((int)cat >= 0)
0300 {
0301 #ifndef BOOST_NO_EXCEPTIONS
0302 try{
0303 #endif
0304 for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
0305 {
0306 string_type mss = this->m_pmessages->get(cat, 0, i, get_default_message(i));
0307 for(typename string_type::size_type j = 0; j < mss.size(); ++j)
0308 {
0309 m_char_map[mss[j]] = i;
0310 }
0311 }
0312 this->m_pmessages->close(cat);
0313 #ifndef BOOST_NO_EXCEPTIONS
0314 }
0315 catch(...)
0316 {
0317 if(this->m_pmessages)
0318 this->m_pmessages->close(cat);
0319 throw;
0320 }
0321 #endif
0322 }
0323 else
0324 {
0325 #endif
0326 for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
0327 {
0328 const char* ptr = get_default_syntax(i);
0329 while(ptr && *ptr)
0330 {
0331 m_char_map[this->m_pctype->widen(*ptr)] = i;
0332 ++ptr;
0333 }
0334 }
0335 #ifndef BOOST_NO_STD_MESSAGES
0336 }
0337 #endif
0338 }
0339
0340 template <class charT>
0341 typename cpp_regex_traits_char_layer<charT>::string_type
0342 cpp_regex_traits_char_layer<charT>::get_default_message(regex_constants::syntax_type i)
0343 {
0344 const char* ptr = get_default_syntax(i);
0345 string_type result;
0346 while(ptr && *ptr)
0347 {
0348 result.append(1, this->m_pctype->widen(*ptr));
0349 ++ptr;
0350 }
0351 return result;
0352 }
0353
0354
0355
0356
0357 template <>
0358 class cpp_regex_traits_char_layer<char> : public cpp_regex_traits_base<char>
0359 {
0360 typedef std::string string_type;
0361 public:
0362 cpp_regex_traits_char_layer(const std::locale& l)
0363 : cpp_regex_traits_base<char>(l)
0364 {
0365 init();
0366 }
0367 cpp_regex_traits_char_layer(const cpp_regex_traits_base<char>& l)
0368 : cpp_regex_traits_base<char>(l)
0369 {
0370 init();
0371 }
0372
0373 regex_constants::syntax_type syntax_type(char c)const
0374 {
0375 return m_char_map[static_cast<unsigned char>(c)];
0376 }
0377 regex_constants::escape_syntax_type escape_syntax_type(char c) const
0378 {
0379 return m_char_map[static_cast<unsigned char>(c)];
0380 }
0381
0382 private:
0383 regex_constants::syntax_type m_char_map[1u << CHAR_BIT];
0384 void init();
0385 };
0386
0387 #ifdef BOOST_REGEX_BUGGY_CTYPE_FACET
0388 enum
0389 {
0390 char_class_space=1<<0,
0391 char_class_print=1<<1,
0392 char_class_cntrl=1<<2,
0393 char_class_upper=1<<3,
0394 char_class_lower=1<<4,
0395 char_class_alpha=1<<5,
0396 char_class_digit=1<<6,
0397 char_class_punct=1<<7,
0398 char_class_xdigit=1<<8,
0399 char_class_alnum=char_class_alpha|char_class_digit,
0400 char_class_graph=char_class_alnum|char_class_punct,
0401 char_class_blank=1<<9,
0402 char_class_word=1<<10,
0403 char_class_unicode=1<<11,
0404 char_class_horizontal_space=1<<12,
0405 char_class_vertical_space=1<<13
0406 };
0407
0408 #endif
0409
0410
0411
0412
0413
0414 template <class charT>
0415 class cpp_regex_traits_implementation : public cpp_regex_traits_char_layer<charT>
0416 {
0417 public:
0418 typedef typename cpp_regex_traits<charT>::char_class_type char_class_type;
0419 typedef typename std::ctype<charT>::mask native_mask_type;
0420 typedef typename boost::make_unsigned<native_mask_type>::type unsigned_native_mask_type;
0421 #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
0422 BOOST_STATIC_CONSTANT(char_class_type, mask_blank = 1u << 24);
0423 BOOST_STATIC_CONSTANT(char_class_type, mask_word = 1u << 25);
0424 BOOST_STATIC_CONSTANT(char_class_type, mask_unicode = 1u << 26);
0425 BOOST_STATIC_CONSTANT(char_class_type, mask_horizontal = 1u << 27);
0426 BOOST_STATIC_CONSTANT(char_class_type, mask_vertical = 1u << 28);
0427 #endif
0428
0429 typedef std::basic_string<charT> string_type;
0430 typedef charT char_type;
0431
0432 cpp_regex_traits_implementation(const std::locale& l)
0433 : cpp_regex_traits_char_layer<charT>(l)
0434 {
0435 init();
0436 }
0437 cpp_regex_traits_implementation(const cpp_regex_traits_base<charT>& l)
0438 : cpp_regex_traits_char_layer<charT>(l)
0439 {
0440 init();
0441 }
0442 std::string error_string(regex_constants::error_type n) const
0443 {
0444 if(!m_error_strings.empty())
0445 {
0446 std::map<int, std::string>::const_iterator p = m_error_strings.find(n);
0447 return (p == m_error_strings.end()) ? std::string(get_default_error_string(n)) : p->second;
0448 }
0449 return get_default_error_string(n);
0450 }
0451 char_class_type lookup_classname(const charT* p1, const charT* p2) const
0452 {
0453 char_class_type result = lookup_classname_imp(p1, p2);
0454 if(result == 0)
0455 {
0456 string_type temp(p1, p2);
0457 this->m_pctype->tolower(&*temp.begin(), &*temp.begin() + temp.size());
0458 result = lookup_classname_imp(&*temp.begin(), &*temp.begin() + temp.size());
0459 }
0460 return result;
0461 }
0462 string_type lookup_collatename(const charT* p1, const charT* p2) const;
0463 string_type transform_primary(const charT* p1, const charT* p2) const;
0464 string_type transform(const charT* p1, const charT* p2) const;
0465 private:
0466 std::map<int, std::string> m_error_strings;
0467 std::map<string_type, char_class_type> m_custom_class_names;
0468 std::map<string_type, string_type> m_custom_collate_names;
0469 unsigned m_collate_type;
0470 charT m_collate_delim;
0471
0472
0473
0474 char_class_type lookup_classname_imp(const charT* p1, const charT* p2) const;
0475 void init();
0476 #ifdef BOOST_REGEX_BUGGY_CTYPE_FACET
0477 public:
0478 bool isctype(charT c, char_class_type m)const;
0479 #endif
0480 };
0481
0482 #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
0483 #if !defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION)
0484
0485 template <class charT>
0486 typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_blank;
0487 template <class charT>
0488 typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_word;
0489 template <class charT>
0490 typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_unicode;
0491 template <class charT>
0492 typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_vertical;
0493 template <class charT>
0494 typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_horizontal;
0495
0496 #endif
0497 #endif
0498
0499 template <class charT>
0500 typename cpp_regex_traits_implementation<charT>::string_type
0501 cpp_regex_traits_implementation<charT>::transform_primary(const charT* p1, const charT* p2) const
0502 {
0503
0504
0505
0506
0507
0508
0509
0510
0511 BOOST_REGEX_ASSERT(*p2 == 0);
0512 string_type result;
0513 #if defined(_CPPLIB_VER)
0514
0515
0516
0517
0518
0519 if(*p1 == 0)
0520 {
0521 return string_type(1, charT(0));
0522 }
0523 #endif
0524
0525
0526
0527
0528
0529 #ifndef BOOST_NO_EXCEPTIONS
0530 try{
0531 #endif
0532
0533
0534
0535
0536 switch(m_collate_type)
0537 {
0538 case sort_C:
0539 case sort_unknown:
0540
0541 {
0542 result.assign(p1, p2);
0543 this->m_pctype->tolower(&*result.begin(), &*result.begin() + result.size());
0544 result = this->m_pcollate->transform(&*result.begin(), &*result.begin() + result.size());
0545 break;
0546 }
0547 case sort_fixed:
0548 {
0549
0550 result.assign(this->m_pcollate->transform(p1, p2));
0551 result.erase(this->m_collate_delim);
0552 break;
0553 }
0554 case sort_delim:
0555
0556 result.assign(this->m_pcollate->transform(p1, p2));
0557 std::size_t i;
0558 for(i = 0; i < result.size(); ++i)
0559 {
0560 if(result[i] == m_collate_delim)
0561 break;
0562 }
0563 result.erase(i);
0564 break;
0565 }
0566 #ifndef BOOST_NO_EXCEPTIONS
0567 }catch(...){}
0568 #endif
0569 while((!result.empty()) && (charT(0) == *result.rbegin()))
0570 result.erase(result.size() - 1);
0571 if(result.empty())
0572 {
0573
0574 result = string_type(1, charT(0));
0575 }
0576 return result;
0577 }
0578
0579 template <class charT>
0580 typename cpp_regex_traits_implementation<charT>::string_type
0581 cpp_regex_traits_implementation<charT>::transform(const charT* p1, const charT* p2) const
0582 {
0583
0584
0585
0586
0587
0588
0589
0590
0591 BOOST_REGEX_ASSERT(*p2 == 0);
0592
0593
0594
0595
0596
0597 string_type result, result2;
0598 #if defined(_CPPLIB_VER)
0599
0600
0601
0602
0603
0604 if(*p1 == 0)
0605 {
0606 return result;
0607 }
0608 #endif
0609 #ifndef BOOST_NO_EXCEPTIONS
0610 try{
0611 #endif
0612 result = this->m_pcollate->transform(p1, p2);
0613
0614
0615
0616
0617
0618
0619 #if BOOST_WORKAROUND(BOOST_BORLANDC, < 0x580)
0620 result.erase(result.find(charT(0)));
0621 #else
0622
0623
0624 while((!result.empty()) && (charT(0) == *result.rbegin()))
0625 result.erase(result.size() - 1);
0626 #endif
0627
0628
0629
0630
0631
0632
0633
0634
0635
0636 typedef typename make_unsigned<charT>::type uchar_type;
0637 result2.reserve(result.size() * 2 + 2);
0638 for(unsigned i = 0; i < result.size(); ++i)
0639 {
0640 if(static_cast<uchar_type>(result[i]) == (std::numeric_limits<uchar_type>::max)())
0641 {
0642 result2.append(1, charT((std::numeric_limits<uchar_type>::max)())).append(1, charT('b'));
0643 }
0644 else
0645 {
0646 result2.append(1, static_cast<charT>(1 + static_cast<uchar_type>(result[i]))).append(1, charT('b') - 1);
0647 }
0648 }
0649 BOOST_REGEX_ASSERT(std::find(result2.begin(), result2.end(), charT(0)) == result2.end());
0650 #ifndef BOOST_NO_EXCEPTIONS
0651 }
0652 catch(...)
0653 {
0654 }
0655 #endif
0656 return result2;
0657 }
0658
0659
0660 template <class charT>
0661 typename cpp_regex_traits_implementation<charT>::string_type
0662 cpp_regex_traits_implementation<charT>::lookup_collatename(const charT* p1, const charT* p2) const
0663 {
0664 typedef typename std::map<string_type, string_type>::const_iterator iter_type;
0665 if(!m_custom_collate_names.empty())
0666 {
0667 iter_type pos = m_custom_collate_names.find(string_type(p1, p2));
0668 if(pos != m_custom_collate_names.end())
0669 return pos->second;
0670 }
0671 #if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\
0672 && !BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x0551)
0673 std::string name(p1, p2);
0674 #else
0675 std::string name;
0676 const charT* p0 = p1;
0677 while(p0 != p2)
0678 name.append(1, char(*p0++));
0679 #endif
0680 name = lookup_default_collate_name(name);
0681 #if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\
0682 && !BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x0551)
0683 if(!name.empty())
0684 return string_type(name.begin(), name.end());
0685 #else
0686 if(!name.empty())
0687 {
0688 string_type result;
0689 typedef std::string::const_iterator iter;
0690 iter b = name.begin();
0691 iter e = name.end();
0692 while(b != e)
0693 result.append(1, charT(*b++));
0694 return result;
0695 }
0696 #endif
0697 if(p2 - p1 == 1)
0698 return string_type(1, *p1);
0699 return string_type();
0700 }
0701
0702 template <class charT>
0703 void cpp_regex_traits_implementation<charT>::init()
0704 {
0705 #ifndef BOOST_NO_STD_MESSAGES
0706 #ifndef __IBMCPP__
0707 typename std::messages<charT>::catalog cat = static_cast<std::messages<char>::catalog>(-1);
0708 #else
0709 typename std::messages<charT>::catalog cat = reinterpret_cast<std::messages<char>::catalog>(-1);
0710 #endif
0711 std::string cat_name(cpp_regex_traits<charT>::get_catalog_name());
0712 if((!cat_name.empty()) && (this->m_pmessages != 0))
0713 {
0714 cat = this->m_pmessages->open(
0715 cat_name,
0716 this->m_locale);
0717 if((int)cat < 0)
0718 {
0719 std::string m("Unable to open message catalog: ");
0720 std::runtime_error err(m + cat_name);
0721 boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err);
0722 }
0723 }
0724
0725
0726
0727 if((int)cat >= 0)
0728 {
0729
0730
0731
0732 for(boost::regex_constants::error_type i = static_cast<boost::regex_constants::error_type>(0);
0733 i <= boost::regex_constants::error_unknown;
0734 i = static_cast<boost::regex_constants::error_type>(i + 1))
0735 {
0736 const char* p = get_default_error_string(i);
0737 string_type default_message;
0738 while(*p)
0739 {
0740 default_message.append(1, this->m_pctype->widen(*p));
0741 ++p;
0742 }
0743 string_type s = this->m_pmessages->get(cat, 0, i+200, default_message);
0744 std::string result;
0745 for(std::string::size_type j = 0; j < s.size(); ++j)
0746 {
0747 result.append(1, this->m_pctype->narrow(s[j], 0));
0748 }
0749 m_error_strings[i] = result;
0750 }
0751
0752
0753
0754 #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
0755 static const char_class_type masks[16] =
0756 {
0757 static_cast<unsigned_native_mask_type>(std::ctype<charT>::alnum),
0758 static_cast<unsigned_native_mask_type>(std::ctype<charT>::alpha),
0759 static_cast<unsigned_native_mask_type>(std::ctype<charT>::cntrl),
0760 static_cast<unsigned_native_mask_type>(std::ctype<charT>::digit),
0761 static_cast<unsigned_native_mask_type>(std::ctype<charT>::graph),
0762 cpp_regex_traits_implementation<charT>::mask_horizontal,
0763 static_cast<unsigned_native_mask_type>(std::ctype<charT>::lower),
0764 static_cast<unsigned_native_mask_type>(std::ctype<charT>::print),
0765 static_cast<unsigned_native_mask_type>(std::ctype<charT>::punct),
0766 static_cast<unsigned_native_mask_type>(std::ctype<charT>::space),
0767 static_cast<unsigned_native_mask_type>(std::ctype<charT>::upper),
0768 cpp_regex_traits_implementation<charT>::mask_vertical,
0769 static_cast<unsigned_native_mask_type>(std::ctype<charT>::xdigit),
0770 cpp_regex_traits_implementation<charT>::mask_blank,
0771 cpp_regex_traits_implementation<charT>::mask_word,
0772 cpp_regex_traits_implementation<charT>::mask_unicode,
0773 };
0774 #else
0775 static const char_class_type masks[16] =
0776 {
0777 ::boost::BOOST_REGEX_DETAIL_NS::char_class_alnum,
0778 ::boost::BOOST_REGEX_DETAIL_NS::char_class_alpha,
0779 ::boost::BOOST_REGEX_DETAIL_NS::char_class_cntrl,
0780 ::boost::BOOST_REGEX_DETAIL_NS::char_class_digit,
0781 ::boost::BOOST_REGEX_DETAIL_NS::char_class_graph,
0782 ::boost::BOOST_REGEX_DETAIL_NS::char_class_horizontal_space,
0783 ::boost::BOOST_REGEX_DETAIL_NS::char_class_lower,
0784 ::boost::BOOST_REGEX_DETAIL_NS::char_class_print,
0785 ::boost::BOOST_REGEX_DETAIL_NS::char_class_punct,
0786 ::boost::BOOST_REGEX_DETAIL_NS::char_class_space,
0787 ::boost::BOOST_REGEX_DETAIL_NS::char_class_upper,
0788 ::boost::BOOST_REGEX_DETAIL_NS::char_class_vertical_space,
0789 ::boost::BOOST_REGEX_DETAIL_NS::char_class_xdigit,
0790 ::boost::BOOST_REGEX_DETAIL_NS::char_class_blank,
0791 ::boost::BOOST_REGEX_DETAIL_NS::char_class_word,
0792 ::boost::BOOST_REGEX_DETAIL_NS::char_class_unicode,
0793 };
0794 #endif
0795 static const string_type null_string;
0796 for(unsigned int j = 0; j <= 13; ++j)
0797 {
0798 string_type s(this->m_pmessages->get(cat, 0, j+300, null_string));
0799 if(!s.empty())
0800 this->m_custom_class_names[s] = masks[j];
0801 }
0802 }
0803 #endif
0804
0805
0806
0807 m_collate_type = BOOST_REGEX_DETAIL_NS::find_sort_syntax(this, &m_collate_delim);
0808 }
0809
0810 template <class charT>
0811 typename cpp_regex_traits_implementation<charT>::char_class_type
0812 cpp_regex_traits_implementation<charT>::lookup_classname_imp(const charT* p1, const charT* p2) const
0813 {
0814 #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
0815 static const char_class_type masks[22] =
0816 {
0817 0,
0818 static_cast<unsigned_native_mask_type>(std::ctype<char>::alnum),
0819 static_cast<unsigned_native_mask_type>(std::ctype<char>::alpha),
0820 cpp_regex_traits_implementation<charT>::mask_blank,
0821 static_cast<unsigned_native_mask_type>(std::ctype<char>::cntrl),
0822 static_cast<unsigned_native_mask_type>(std::ctype<char>::digit),
0823 static_cast<unsigned_native_mask_type>(std::ctype<char>::digit),
0824 static_cast<unsigned_native_mask_type>(std::ctype<char>::graph),
0825 cpp_regex_traits_implementation<charT>::mask_horizontal,
0826 static_cast<unsigned_native_mask_type>(std::ctype<char>::lower),
0827 static_cast<unsigned_native_mask_type>(std::ctype<char>::lower),
0828 static_cast<unsigned_native_mask_type>(std::ctype<char>::print),
0829 static_cast<unsigned_native_mask_type>(std::ctype<char>::punct),
0830 static_cast<unsigned_native_mask_type>(std::ctype<char>::space),
0831 static_cast<unsigned_native_mask_type>(std::ctype<char>::space),
0832 static_cast<unsigned_native_mask_type>(std::ctype<char>::upper),
0833 cpp_regex_traits_implementation<charT>::mask_unicode,
0834 static_cast<unsigned_native_mask_type>(std::ctype<char>::upper),
0835 cpp_regex_traits_implementation<charT>::mask_vertical,
0836 static_cast<unsigned_native_mask_type>(std::ctype<char>::alnum) | cpp_regex_traits_implementation<charT>::mask_word,
0837 static_cast<unsigned_native_mask_type>(std::ctype<char>::alnum) | cpp_regex_traits_implementation<charT>::mask_word,
0838 static_cast<unsigned_native_mask_type>(std::ctype<char>::xdigit),
0839 };
0840 #else
0841 static const char_class_type masks[22] =
0842 {
0843 0,
0844 ::boost::BOOST_REGEX_DETAIL_NS::char_class_alnum,
0845 ::boost::BOOST_REGEX_DETAIL_NS::char_class_alpha,
0846 ::boost::BOOST_REGEX_DETAIL_NS::char_class_blank,
0847 ::boost::BOOST_REGEX_DETAIL_NS::char_class_cntrl,
0848 ::boost::BOOST_REGEX_DETAIL_NS::char_class_digit,
0849 ::boost::BOOST_REGEX_DETAIL_NS::char_class_digit,
0850 ::boost::BOOST_REGEX_DETAIL_NS::char_class_graph,
0851 ::boost::BOOST_REGEX_DETAIL_NS::char_class_horizontal_space,
0852 ::boost::BOOST_REGEX_DETAIL_NS::char_class_lower,
0853 ::boost::BOOST_REGEX_DETAIL_NS::char_class_lower,
0854 ::boost::BOOST_REGEX_DETAIL_NS::char_class_print,
0855 ::boost::BOOST_REGEX_DETAIL_NS::char_class_punct,
0856 ::boost::BOOST_REGEX_DETAIL_NS::char_class_space,
0857 ::boost::BOOST_REGEX_DETAIL_NS::char_class_space,
0858 ::boost::BOOST_REGEX_DETAIL_NS::char_class_upper,
0859 ::boost::BOOST_REGEX_DETAIL_NS::char_class_unicode,
0860 ::boost::BOOST_REGEX_DETAIL_NS::char_class_upper,
0861 ::boost::BOOST_REGEX_DETAIL_NS::char_class_vertical_space,
0862 ::boost::BOOST_REGEX_DETAIL_NS::char_class_alnum | ::boost::BOOST_REGEX_DETAIL_NS::char_class_word,
0863 ::boost::BOOST_REGEX_DETAIL_NS::char_class_alnum | ::boost::BOOST_REGEX_DETAIL_NS::char_class_word,
0864 ::boost::BOOST_REGEX_DETAIL_NS::char_class_xdigit,
0865 };
0866 #endif
0867 if(!m_custom_class_names.empty())
0868 {
0869 typedef typename std::map<std::basic_string<charT>, char_class_type>::const_iterator map_iter;
0870 map_iter pos = m_custom_class_names.find(string_type(p1, p2));
0871 if(pos != m_custom_class_names.end())
0872 return pos->second;
0873 }
0874 std::size_t state_id = 1 + BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2);
0875 BOOST_REGEX_ASSERT(state_id < sizeof(masks) / sizeof(masks[0]));
0876 return masks[state_id];
0877 }
0878
0879 #ifdef BOOST_REGEX_BUGGY_CTYPE_FACET
0880 template <class charT>
0881 bool cpp_regex_traits_implementation<charT>::isctype(const charT c, char_class_type mask) const
0882 {
0883 return
0884 ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_space) && (this->m_pctype->is(std::ctype<charT>::space, c)))
0885 || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_print) && (this->m_pctype->is(std::ctype<charT>::print, c)))
0886 || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_cntrl) && (this->m_pctype->is(std::ctype<charT>::cntrl, c)))
0887 || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_upper) && (this->m_pctype->is(std::ctype<charT>::upper, c)))
0888 || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_lower) && (this->m_pctype->is(std::ctype<charT>::lower, c)))
0889 || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_alpha) && (this->m_pctype->is(std::ctype<charT>::alpha, c)))
0890 || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_digit) && (this->m_pctype->is(std::ctype<charT>::digit, c)))
0891 || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_punct) && (this->m_pctype->is(std::ctype<charT>::punct, c)))
0892 || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_xdigit) && (this->m_pctype->is(std::ctype<charT>::xdigit, c)))
0893 || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_blank) && (this->m_pctype->is(std::ctype<charT>::space, c)) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c))
0894 || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_word) && (c == '_'))
0895 || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_unicode) && ::boost::BOOST_REGEX_DETAIL_NS::is_extended(c))
0896 || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_vertical_space) && (is_separator(c) || (c == '\v')))
0897 || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_horizontal_space) && this->m_pctype->is(std::ctype<charT>::space, c) && !(is_separator(c) || (c == '\v')));
0898 }
0899 #endif
0900
0901
0902 template <class charT>
0903 inline boost::shared_ptr<const cpp_regex_traits_implementation<charT> > create_cpp_regex_traits(const std::locale& l)
0904 {
0905 cpp_regex_traits_base<charT> key(l);
0906 return ::boost::object_cache<cpp_regex_traits_base<charT>, cpp_regex_traits_implementation<charT> >::get(key, 5);
0907 }
0908
0909 }
0910
0911 template <class charT>
0912 class cpp_regex_traits
0913 {
0914 private:
0915 typedef std::ctype<charT> ctype_type;
0916 public:
0917 typedef charT char_type;
0918 typedef std::size_t size_type;
0919 typedef std::basic_string<char_type> string_type;
0920 typedef std::locale locale_type;
0921 typedef boost::uint_least32_t char_class_type;
0922
0923 struct boost_extensions_tag{};
0924
0925 cpp_regex_traits()
0926 : m_pimpl(BOOST_REGEX_DETAIL_NS::create_cpp_regex_traits<charT>(std::locale()))
0927 { }
0928 static size_type length(const char_type* p)
0929 {
0930 return std::char_traits<charT>::length(p);
0931 }
0932 regex_constants::syntax_type syntax_type(charT c)const
0933 {
0934 return m_pimpl->syntax_type(c);
0935 }
0936 regex_constants::escape_syntax_type escape_syntax_type(charT c) const
0937 {
0938 return m_pimpl->escape_syntax_type(c);
0939 }
0940 charT translate(charT c) const
0941 {
0942 return c;
0943 }
0944 charT translate_nocase(charT c) const
0945 {
0946 return m_pimpl->m_pctype->tolower(c);
0947 }
0948 charT translate(charT c, bool icase) const
0949 {
0950 return icase ? m_pimpl->m_pctype->tolower(c) : c;
0951 }
0952 charT tolower(charT c) const
0953 {
0954 return m_pimpl->m_pctype->tolower(c);
0955 }
0956 charT toupper(charT c) const
0957 {
0958 return m_pimpl->m_pctype->toupper(c);
0959 }
0960 string_type transform(const charT* p1, const charT* p2) const
0961 {
0962 return m_pimpl->transform(p1, p2);
0963 }
0964 string_type transform_primary(const charT* p1, const charT* p2) const
0965 {
0966 return m_pimpl->transform_primary(p1, p2);
0967 }
0968 char_class_type lookup_classname(const charT* p1, const charT* p2) const
0969 {
0970 return m_pimpl->lookup_classname(p1, p2);
0971 }
0972 string_type lookup_collatename(const charT* p1, const charT* p2) const
0973 {
0974 return m_pimpl->lookup_collatename(p1, p2);
0975 }
0976 bool isctype(charT c, char_class_type f) const
0977 {
0978 #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
0979 typedef typename std::ctype<charT>::mask ctype_mask;
0980
0981 static const ctype_mask mask_base =
0982 static_cast<ctype_mask>(
0983 std::ctype<charT>::alnum
0984 | std::ctype<charT>::alpha
0985 | std::ctype<charT>::cntrl
0986 | std::ctype<charT>::digit
0987 | std::ctype<charT>::graph
0988 | std::ctype<charT>::lower
0989 | std::ctype<charT>::print
0990 | std::ctype<charT>::punct
0991 | std::ctype<charT>::space
0992 | std::ctype<charT>::upper
0993 | std::ctype<charT>::xdigit);
0994
0995 if((f & mask_base)
0996 && (m_pimpl->m_pctype->is(
0997 static_cast<ctype_mask>(f & mask_base), c)))
0998 return true;
0999 else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation<charT>::mask_unicode) && BOOST_REGEX_DETAIL_NS::is_extended(c))
1000 return true;
1001 else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation<charT>::mask_word) && (c == '_'))
1002 return true;
1003 else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation<charT>::mask_blank)
1004 && m_pimpl->m_pctype->is(std::ctype<charT>::space, c)
1005 && !BOOST_REGEX_DETAIL_NS::is_separator(c))
1006 return true;
1007 else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation<charT>::mask_vertical)
1008 && (::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) || (c == '\v')))
1009 return true;
1010 else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation<charT>::mask_horizontal)
1011 && this->isctype(c, std::ctype<charT>::space) && !this->isctype(c, BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation<charT>::mask_vertical))
1012 return true;
1013 #ifdef __CYGWIN__
1014
1015
1016
1017 else if((f & std::ctype<charT>::xdigit) == std::ctype<charT>::xdigit)
1018 {
1019 if((c >= 'a') && (c <= 'f'))
1020 return true;
1021 if((c >= 'A') && (c <= 'F'))
1022 return true;
1023 }
1024 #endif
1025 return false;
1026 #else
1027 return m_pimpl->isctype(c, f);
1028 #endif
1029 }
1030 boost::intmax_t toi(const charT*& p1, const charT* p2, int radix)const;
1031 int value(charT c, int radix)const
1032 {
1033 const charT* pc = &c;
1034 return (int)toi(pc, pc + 1, radix);
1035 }
1036 locale_type imbue(locale_type l)
1037 {
1038 std::locale result(getloc());
1039 m_pimpl = BOOST_REGEX_DETAIL_NS::create_cpp_regex_traits<charT>(l);
1040 return result;
1041 }
1042 locale_type getloc()const
1043 {
1044 return m_pimpl->m_locale;
1045 }
1046 std::string error_string(regex_constants::error_type n) const
1047 {
1048 return m_pimpl->error_string(n);
1049 }
1050
1051
1052
1053
1054
1055 static std::string catalog_name(const std::string& name);
1056 static std::string get_catalog_name();
1057
1058 private:
1059 boost::shared_ptr<const BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation<charT> > m_pimpl;
1060
1061
1062
1063 static std::string& get_catalog_name_inst();
1064
1065 #ifdef BOOST_HAS_THREADS
1066 static static_mutex& get_mutex_inst();
1067 #endif
1068 };
1069
1070
1071 template <class charT>
1072 boost::intmax_t cpp_regex_traits<charT>::toi(const charT*& first, const charT* last, int radix)const
1073 {
1074 BOOST_REGEX_DETAIL_NS::parser_buf<charT> sbuf;
1075 std::basic_istream<charT> is(&sbuf);
1076
1077
1078 last = std::find(first, last, BOOST_USE_FACET(std::numpunct<charT>, is.getloc()).thousands_sep());
1079
1080 sbuf.pubsetbuf(const_cast<charT*>(static_cast<const charT*>(first)), static_cast<std::streamsize>(last-first));
1081 is.clear();
1082 if(std::abs(radix) == 16) is >> std::hex;
1083 else if(std::abs(radix) == 8) is >> std::oct;
1084 else is >> std::dec;
1085 boost::intmax_t val;
1086 if(is >> val)
1087 {
1088 first = first + ((last - first) - sbuf.in_avail());
1089 return val;
1090 }
1091 else
1092 return -1;
1093 }
1094
1095 template <class charT>
1096 std::string cpp_regex_traits<charT>::catalog_name(const std::string& name)
1097 {
1098 #ifdef BOOST_HAS_THREADS
1099 static_mutex::scoped_lock lk(get_mutex_inst());
1100 #endif
1101 std::string result(get_catalog_name_inst());
1102 get_catalog_name_inst() = name;
1103 return result;
1104 }
1105
1106 template <class charT>
1107 std::string& cpp_regex_traits<charT>::get_catalog_name_inst()
1108 {
1109 static std::string s_name;
1110 return s_name;
1111 }
1112
1113 template <class charT>
1114 std::string cpp_regex_traits<charT>::get_catalog_name()
1115 {
1116 #ifdef BOOST_HAS_THREADS
1117 static_mutex::scoped_lock lk(get_mutex_inst());
1118 #endif
1119 std::string result(get_catalog_name_inst());
1120 return result;
1121 }
1122
1123 #ifdef BOOST_HAS_THREADS
1124 template <class charT>
1125 static_mutex& cpp_regex_traits<charT>::get_mutex_inst()
1126 {
1127 static static_mutex s_mutex = BOOST_STATIC_MUTEX_INIT;
1128 return s_mutex;
1129 }
1130 #endif
1131
1132 namespace BOOST_REGEX_DETAIL_NS {
1133
1134 inline void cpp_regex_traits_char_layer<char>::init()
1135 {
1136
1137
1138 std::memset(m_char_map, 0, sizeof(m_char_map));
1139 #ifndef BOOST_NO_STD_MESSAGES
1140 #ifndef __IBMCPP__
1141 std::messages<char>::catalog cat = static_cast<std::messages<char>::catalog>(-1);
1142 #else
1143 std::messages<char>::catalog cat = reinterpret_cast<std::messages<char>::catalog>(-1);
1144 #endif
1145 std::string cat_name(cpp_regex_traits<char>::get_catalog_name());
1146 if ((!cat_name.empty()) && (m_pmessages != 0))
1147 {
1148 cat = this->m_pmessages->open(
1149 cat_name,
1150 this->m_locale);
1151 if ((int)cat < 0)
1152 {
1153 std::string m("Unable to open message catalog: ");
1154 std::runtime_error err(m + cat_name);
1155 boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err);
1156 }
1157 }
1158
1159
1160
1161 if ((int)cat >= 0)
1162 {
1163 #ifndef BOOST_NO_EXCEPTIONS
1164 try {
1165 #endif
1166 for (regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
1167 {
1168 string_type mss = this->m_pmessages->get(cat, 0, i, get_default_syntax(i));
1169 for (string_type::size_type j = 0; j < mss.size(); ++j)
1170 {
1171 m_char_map[static_cast<unsigned char>(mss[j])] = i;
1172 }
1173 }
1174 this->m_pmessages->close(cat);
1175 #ifndef BOOST_NO_EXCEPTIONS
1176 }
1177 catch (...)
1178 {
1179 this->m_pmessages->close(cat);
1180 throw;
1181 }
1182 #endif
1183 }
1184 else
1185 {
1186 #endif
1187 for (regex_constants::syntax_type j = 1; j < regex_constants::syntax_max; ++j)
1188 {
1189 const char* ptr = get_default_syntax(j);
1190 while (ptr && *ptr)
1191 {
1192 m_char_map[static_cast<unsigned char>(*ptr)] = j;
1193 ++ptr;
1194 }
1195 }
1196 #ifndef BOOST_NO_STD_MESSAGES
1197 }
1198 #endif
1199
1200
1201
1202 unsigned char i = 'A';
1203 do
1204 {
1205 if (m_char_map[i] == 0)
1206 {
1207 if (this->m_pctype->is(std::ctype_base::lower, i))
1208 m_char_map[i] = regex_constants::escape_type_class;
1209 else if (this->m_pctype->is(std::ctype_base::upper, i))
1210 m_char_map[i] = regex_constants::escape_type_not_class;
1211 }
1212 } while (0xFF != i++);
1213 }
1214
1215 }
1216
1217
1218 }
1219
1220 #ifdef BOOST_MSVC
1221 #pragma warning(pop)
1222 #endif
1223
1224 #ifdef BOOST_MSVC
1225 #pragma warning(push)
1226 #pragma warning(disable: 4103)
1227 #endif
1228 #ifdef BOOST_HAS_ABI_HEADERS
1229 # include BOOST_ABI_SUFFIX
1230 #endif
1231 #ifdef BOOST_MSVC
1232 #pragma warning(pop)
1233 #endif
1234
1235 #endif
1236
1237 #endif