Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2004 John Maddock
4 : * Copyright 2011 Garmin Ltd. or its subsidiaries
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 cpp_regex_traits.hpp
15 : * VERSION see <boost/version.hpp>
16 : * DESCRIPTION: Declares regular expression traits class cpp_regex_traits.
17 : */
18 :
19 : #ifndef BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED
20 : #define BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED
21 :
22 : #include <boost/config.hpp>
23 : #include <boost/integer.hpp>
24 : #include <boost/type_traits/make_unsigned.hpp>
25 :
26 : #ifndef BOOST_NO_STD_LOCALE
27 :
28 : #ifndef BOOST_RE_PAT_EXCEPT_HPP
29 : #include <boost/regex/pattern_except.hpp>
30 : #endif
31 : #ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED
32 : #include <boost/regex/v4/regex_traits_defaults.hpp>
33 : #endif
34 : #ifdef BOOST_HAS_THREADS
35 : #include <boost/regex/pending/static_mutex.hpp>
36 : #endif
37 : #ifndef BOOST_REGEX_PRIMARY_TRANSFORM
38 : #include <boost/regex/v4/primary_transform.hpp>
39 : #endif
40 : #ifndef BOOST_REGEX_OBJECT_CACHE_HPP
41 : #include <boost/regex/pending/object_cache.hpp>
42 : #endif
43 :
44 : #include <istream>
45 : #include <ios>
46 : #include <climits>
47 :
48 : #ifdef BOOST_MSVC
49 : #pragma warning(push)
50 : #pragma warning(disable: 4103)
51 : #endif
52 : #ifdef BOOST_HAS_ABI_HEADERS
53 : # include BOOST_ABI_PREFIX
54 : #endif
55 : #ifdef BOOST_MSVC
56 : #pragma warning(pop)
57 : #endif
58 :
59 : #ifdef BOOST_MSVC
60 : #pragma warning(push)
61 : #pragma warning(disable:4786 4251)
62 : #endif
63 :
64 : namespace boost{
65 :
66 : //
67 : // forward declaration is needed by some compilers:
68 : //
69 : template <class charT>
70 : class cpp_regex_traits;
71 :
72 : namespace BOOST_REGEX_DETAIL_NS{
73 :
74 : //
75 : // class parser_buf:
76 : // acts as a stream buffer which wraps around a pair of pointers:
77 : //
78 : template <class charT,
79 : class traits = ::std::char_traits<charT> >
80 : class parser_buf : public ::std::basic_streambuf<charT, traits>
81 : {
82 : typedef ::std::basic_streambuf<charT, traits> base_type;
83 : typedef typename base_type::int_type int_type;
84 : typedef typename base_type::char_type char_type;
85 : typedef typename base_type::pos_type pos_type;
86 : typedef ::std::streamsize streamsize;
87 : typedef typename base_type::off_type off_type;
88 : public:
89 : parser_buf() : base_type() { setbuf(0, 0); }
90 : const charT* getnext() { return this->gptr(); }
91 : protected:
92 : std::basic_streambuf<charT, traits>* setbuf(char_type* s, streamsize n);
93 : typename parser_buf<charT, traits>::pos_type seekpos(pos_type sp, ::std::ios_base::openmode which);
94 : typename parser_buf<charT, traits>::pos_type seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which);
95 : private:
96 : parser_buf& operator=(const parser_buf&);
97 : parser_buf(const parser_buf&);
98 : };
99 :
100 : template<class charT, class traits>
101 : std::basic_streambuf<charT, traits>*
102 : parser_buf<charT, traits>::setbuf(char_type* s, streamsize n)
103 : {
104 : this->setg(s, s, s + n);
105 : return this;
106 : }
107 :
108 : template<class charT, class traits>
109 : typename parser_buf<charT, traits>::pos_type
110 : parser_buf<charT, traits>::seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which)
111 : {
112 : typedef typename boost::int_t<sizeof(way) * CHAR_BIT>::least cast_type;
113 :
114 : if(which & ::std::ios_base::out)
115 : return pos_type(off_type(-1));
116 : std::ptrdiff_t size = this->egptr() - this->eback();
117 : std::ptrdiff_t pos = this->gptr() - this->eback();
118 : charT* g = this->eback();
119 : switch(static_cast<cast_type>(way))
120 : {
121 : case ::std::ios_base::beg:
122 : if((off < 0) || (off > size))
123 : return pos_type(off_type(-1));
124 : else
125 : this->setg(g, g + off, g + size);
126 : break;
127 : case ::std::ios_base::end:
128 : if((off < 0) || (off > size))
129 : return pos_type(off_type(-1));
130 : else
131 : this->setg(g, g + size - off, g + size);
132 : break;
133 : case ::std::ios_base::cur:
134 : {
135 : std::ptrdiff_t newpos = static_cast<std::ptrdiff_t>(pos + off);
136 : if((newpos < 0) || (newpos > size))
137 : return pos_type(off_type(-1));
138 : else
139 : this->setg(g, g + newpos, g + size);
140 : break;
141 : }
142 : default: ;
143 : }
144 : #ifdef BOOST_MSVC
145 : #pragma warning(push)
146 : #pragma warning(disable:4244)
147 : #endif
148 : return static_cast<pos_type>(this->gptr() - this->eback());
149 : #ifdef BOOST_MSVC
150 : #pragma warning(pop)
151 : #endif
152 : }
153 :
154 : template<class charT, class traits>
155 : typename parser_buf<charT, traits>::pos_type
156 : parser_buf<charT, traits>::seekpos(pos_type sp, ::std::ios_base::openmode which)
157 : {
158 : if(which & ::std::ios_base::out)
159 : return pos_type(off_type(-1));
160 : off_type size = static_cast<off_type>(this->egptr() - this->eback());
161 : charT* g = this->eback();
162 : if(off_type(sp) <= size)
163 : {
164 : this->setg(g, g + off_type(sp), g + size);
165 : }
166 : return pos_type(off_type(-1));
167 : }
168 :
169 : //
170 : // class cpp_regex_traits_base:
171 : // acts as a container for locale and the facets we are using.
172 : //
173 : template <class charT>
174 : struct cpp_regex_traits_base
175 : {
176 : cpp_regex_traits_base(const std::locale& l)
177 : { imbue(l); }
178 : std::locale imbue(const std::locale& l);
179 :
180 : std::locale m_locale;
181 : std::ctype<charT> const* m_pctype;
182 : #ifndef BOOST_NO_STD_MESSAGES
183 : std::messages<charT> const* m_pmessages;
184 : #endif
185 : std::collate<charT> const* m_pcollate;
186 :
187 : bool operator<(const cpp_regex_traits_base& b)const
188 : {
189 : if(m_pctype == b.m_pctype)
190 : {
191 : #ifndef BOOST_NO_STD_MESSAGES
192 : if(m_pmessages == b.m_pmessages)
193 : {
194 : return m_pcollate < b.m_pcollate;
195 : }
196 : return m_pmessages < b.m_pmessages;
197 : #else
198 : return m_pcollate < b.m_pcollate;
199 : #endif
200 : }
201 : return m_pctype < b.m_pctype;
202 : }
203 : bool operator==(const cpp_regex_traits_base& b)const
204 : {
205 : return (m_pctype == b.m_pctype)
206 : #ifndef BOOST_NO_STD_MESSAGES
207 : && (m_pmessages == b.m_pmessages)
208 : #endif
209 : && (m_pcollate == b.m_pcollate);
210 : }
211 : };
212 :
213 : template <class charT>
214 : std::locale cpp_regex_traits_base<charT>::imbue(const std::locale& l)
215 : {
216 : std::locale result(m_locale);
217 : m_locale = l;
218 : m_pctype = &BOOST_USE_FACET(std::ctype<charT>, l);
219 : #ifndef BOOST_NO_STD_MESSAGES
220 : m_pmessages = BOOST_HAS_FACET(std::messages<charT>, l) ? &BOOST_USE_FACET(std::messages<charT>, l) : 0;
221 : #endif
222 : m_pcollate = &BOOST_USE_FACET(std::collate<charT>, l);
223 : return result;
224 : }
225 :
226 : //
227 : // class cpp_regex_traits_char_layer:
228 : // implements methods that require specialisation for narrow characters:
229 : //
230 : template <class charT>
231 : class cpp_regex_traits_char_layer : public cpp_regex_traits_base<charT>
232 : {
233 : typedef std::basic_string<charT> string_type;
234 : typedef std::map<charT, regex_constants::syntax_type> map_type;
235 : typedef typename map_type::const_iterator map_iterator_type;
236 : public:
237 : cpp_regex_traits_char_layer(const std::locale& l)
238 : : cpp_regex_traits_base<charT>(l)
239 : {
240 : init();
241 : }
242 : cpp_regex_traits_char_layer(const cpp_regex_traits_base<charT>& b)
243 : : cpp_regex_traits_base<charT>(b)
244 : {
245 : init();
246 : }
247 : void init();
248 :
249 : regex_constants::syntax_type syntax_type(charT c)const
250 : {
251 : map_iterator_type i = m_char_map.find(c);
252 : return ((i == m_char_map.end()) ? 0 : i->second);
253 : }
254 : regex_constants::escape_syntax_type escape_syntax_type(charT c) const
255 : {
256 : map_iterator_type i = m_char_map.find(c);
257 : if(i == m_char_map.end())
258 : {
259 : if(this->m_pctype->is(std::ctype_base::lower, c)) return regex_constants::escape_type_class;
260 : if(this->m_pctype->is(std::ctype_base::upper, c)) return regex_constants::escape_type_not_class;
261 : return 0;
262 : }
263 : return i->second;
264 : }
265 :
266 : private:
267 : string_type get_default_message(regex_constants::syntax_type);
268 : // TODO: use a hash table when available!
269 : map_type m_char_map;
270 : };
271 :
272 : template <class charT>
273 : void cpp_regex_traits_char_layer<charT>::init()
274 : {
275 : // we need to start by initialising our syntax map so we know which
276 : // character is used for which purpose:
277 : #ifndef BOOST_NO_STD_MESSAGES
278 : #ifndef __IBMCPP__
279 : typename std::messages<charT>::catalog cat = static_cast<std::messages<char>::catalog>(-1);
280 : #else
281 : typename std::messages<charT>::catalog cat = reinterpret_cast<std::messages<char>::catalog>(-1);
282 : #endif
283 : std::string cat_name(cpp_regex_traits<charT>::get_catalog_name());
284 : if(cat_name.size() && (this->m_pmessages != 0))
285 : {
286 : cat = this->m_pmessages->open(
287 : cat_name,
288 : this->m_locale);
289 : if((int)cat < 0)
290 : {
291 : std::string m("Unable to open message catalog: ");
292 : std::runtime_error err(m + cat_name);
293 : boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err);
294 : }
295 : }
296 : //
297 : // if we have a valid catalog then load our messages:
298 : //
299 : if((int)cat >= 0)
300 : {
301 : #ifndef BOOST_NO_EXCEPTIONS
302 : try{
303 : #endif
304 : for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
305 : {
306 : string_type mss = this->m_pmessages->get(cat, 0, i, get_default_message(i));
307 : for(typename string_type::size_type j = 0; j < mss.size(); ++j)
308 : {
309 : m_char_map[mss[j]] = i;
310 : }
311 : }
312 : this->m_pmessages->close(cat);
313 : #ifndef BOOST_NO_EXCEPTIONS
314 : }
315 : catch(...)
316 : {
317 : if(this->m_pmessages)
318 : this->m_pmessages->close(cat);
319 : throw;
320 : }
321 : #endif
322 : }
323 : else
324 : {
325 : #endif
326 : for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
327 : {
328 : const char* ptr = get_default_syntax(i);
329 : while(ptr && *ptr)
330 : {
331 : m_char_map[this->m_pctype->widen(*ptr)] = i;
332 : ++ptr;
333 : }
334 : }
335 : #ifndef BOOST_NO_STD_MESSAGES
336 : }
337 : #endif
338 : }
339 :
340 : template <class charT>
341 : typename cpp_regex_traits_char_layer<charT>::string_type
342 : cpp_regex_traits_char_layer<charT>::get_default_message(regex_constants::syntax_type i)
343 : {
344 : const char* ptr = get_default_syntax(i);
345 : string_type result;
346 : while(ptr && *ptr)
347 : {
348 : result.append(1, this->m_pctype->widen(*ptr));
349 : ++ptr;
350 : }
351 : return result;
352 : }
353 :
354 : //
355 : // specialised version for narrow characters:
356 : //
357 : template <>
358 : class BOOST_REGEX_DECL cpp_regex_traits_char_layer<char> : public cpp_regex_traits_base<char>
359 : {
360 : typedef std::string string_type;
361 : public:
362 : cpp_regex_traits_char_layer(const std::locale& l)
363 : : cpp_regex_traits_base<char>(l)
364 : {
365 : init();
366 : }
367 : cpp_regex_traits_char_layer(const cpp_regex_traits_base<char>& l)
368 : : cpp_regex_traits_base<char>(l)
369 : {
370 : init();
371 : }
372 :
373 : regex_constants::syntax_type syntax_type(char c)const
374 : {
375 : return m_char_map[static_cast<unsigned char>(c)];
376 : }
377 : regex_constants::escape_syntax_type escape_syntax_type(char c) const
378 : {
379 : return m_char_map[static_cast<unsigned char>(c)];
380 : }
381 :
382 : private:
383 : regex_constants::syntax_type m_char_map[1u << CHAR_BIT];
384 : void init();
385 : };
386 :
387 : #ifdef BOOST_REGEX_BUGGY_CTYPE_FACET
388 : enum
389 : {
390 : char_class_space=1<<0,
391 : char_class_print=1<<1,
392 : char_class_cntrl=1<<2,
393 : char_class_upper=1<<3,
394 : char_class_lower=1<<4,
395 : char_class_alpha=1<<5,
396 : char_class_digit=1<<6,
397 : char_class_punct=1<<7,
398 : char_class_xdigit=1<<8,
399 : char_class_alnum=char_class_alpha|char_class_digit,
400 : char_class_graph=char_class_alnum|char_class_punct,
401 : char_class_blank=1<<9,
402 : char_class_word=1<<10,
403 : char_class_unicode=1<<11,
404 : char_class_horizontal_space=1<<12,
405 : char_class_vertical_space=1<<13
406 : };
407 :
408 : #endif
409 :
410 : //
411 : // class cpp_regex_traits_implementation:
412 : // provides pimpl implementation for cpp_regex_traits.
413 : //
414 : template <class charT>
415 : class cpp_regex_traits_implementation : public cpp_regex_traits_char_layer<charT>
416 : {
417 : public:
418 : typedef typename cpp_regex_traits<charT>::char_class_type char_class_type;
419 : typedef typename std::ctype<charT>::mask native_mask_type;
420 : typedef typename boost::make_unsigned<native_mask_type>::type unsigned_native_mask_type;
421 : #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
422 : BOOST_STATIC_CONSTANT(char_class_type, mask_blank = 1u << 24);
423 : BOOST_STATIC_CONSTANT(char_class_type, mask_word = 1u << 25);
424 : BOOST_STATIC_CONSTANT(char_class_type, mask_unicode = 1u << 26);
425 : BOOST_STATIC_CONSTANT(char_class_type, mask_horizontal = 1u << 27);
426 : BOOST_STATIC_CONSTANT(char_class_type, mask_vertical = 1u << 28);
427 : #endif
428 :
429 : typedef std::basic_string<charT> string_type;
430 : typedef charT char_type;
431 : //cpp_regex_traits_implementation();
432 : cpp_regex_traits_implementation(const std::locale& l)
433 : : cpp_regex_traits_char_layer<charT>(l)
434 : {
435 : init();
436 : }
437 : cpp_regex_traits_implementation(const cpp_regex_traits_base<charT>& l)
438 : : cpp_regex_traits_char_layer<charT>(l)
439 : {
440 : init();
441 : }
442 0 : std::string error_string(regex_constants::error_type n) const
443 : {
444 0 : if(!m_error_strings.empty())
445 : {
446 0 : std::map<int, std::string>::const_iterator p = m_error_strings.find(n);
447 0 : return (p == m_error_strings.end()) ? std::string(get_default_error_string(n)) : p->second;
448 : }
449 0 : return get_default_error_string(n);
450 : }
451 : char_class_type lookup_classname(const charT* p1, const charT* p2) const
452 : {
453 : char_class_type result = lookup_classname_imp(p1, p2);
454 : if(result == 0)
455 : {
456 : string_type temp(p1, p2);
457 : this->m_pctype->tolower(&*temp.begin(), &*temp.begin() + temp.size());
458 : result = lookup_classname_imp(&*temp.begin(), &*temp.begin() + temp.size());
459 : }
460 : return result;
461 : }
462 : string_type lookup_collatename(const charT* p1, const charT* p2) const;
463 : string_type transform_primary(const charT* p1, const charT* p2) const;
464 : string_type transform(const charT* p1, const charT* p2) const;
465 : private:
466 : std::map<int, std::string> m_error_strings; // error messages indexed by numberic ID
467 : std::map<string_type, char_class_type> m_custom_class_names; // character class names
468 : std::map<string_type, string_type> m_custom_collate_names; // collating element names
469 : unsigned m_collate_type; // the form of the collation string
470 : charT m_collate_delim; // the collation group delimiter
471 : //
472 : // helpers:
473 : //
474 : char_class_type lookup_classname_imp(const charT* p1, const charT* p2) const;
475 : void init();
476 : #ifdef BOOST_REGEX_BUGGY_CTYPE_FACET
477 : public:
478 : bool isctype(charT c, char_class_type m)const;
479 : #endif
480 : };
481 :
482 : #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
483 : #if !defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION)
484 :
485 : template <class charT>
486 : typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_blank;
487 : template <class charT>
488 : typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_word;
489 : template <class charT>
490 : typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_unicode;
491 : template <class charT>
492 : typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_vertical;
493 : template <class charT>
494 : typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_horizontal;
495 :
496 : #endif
497 : #endif
498 :
499 : template <class charT>
500 : typename cpp_regex_traits_implementation<charT>::string_type
501 : cpp_regex_traits_implementation<charT>::transform_primary(const charT* p1, const charT* p2) const
502 : {
503 : //
504 : // PRECONDITIONS:
505 : //
506 : // A bug in gcc 3.2 (and maybe other versions as well) treats
507 : // p1 as a null terminated string, for efficiency reasons
508 : // we work around this elsewhere, but just assert here that
509 : // we adhere to gcc's (buggy) preconditions...
510 : //
511 : BOOST_ASSERT(*p2 == 0);
512 : string_type result;
513 : #if defined(_CPPLIB_VER)
514 : //
515 : // A bug in VC11 and 12 causes the program to hang if we pass a null-string
516 : // to std::collate::transform, but only for certain locales :-(
517 : // Probably effects Intel and Clang or any compiler using the VC std library (Dinkumware).
518 : //
519 : if(*p1 == 0)
520 : {
521 : return string_type(1, charT(0));
522 : }
523 : #endif
524 : //
525 : // swallowing all exceptions here is a bad idea
526 : // however at least one std lib will always throw
527 : // std::bad_alloc for certain arguments...
528 : //
529 : #ifndef BOOST_NO_EXCEPTIONS
530 : try{
531 : #endif
532 : //
533 : // What we do here depends upon the format of the sort key returned by
534 : // sort key returned by this->transform:
535 : //
536 : switch(m_collate_type)
537 : {
538 : case sort_C:
539 : case sort_unknown:
540 : // the best we can do is translate to lower case, then get a regular sort key:
541 : {
542 : result.assign(p1, p2);
543 : this->m_pctype->tolower(&*result.begin(), &*result.begin() + result.size());
544 : result = this->m_pcollate->transform(&*result.begin(), &*result.begin() + result.size());
545 : break;
546 : }
547 : case sort_fixed:
548 : {
549 : // get a regular sort key, and then truncate it:
550 : result.assign(this->m_pcollate->transform(p1, p2));
551 : result.erase(this->m_collate_delim);
552 : break;
553 : }
554 : case sort_delim:
555 : // get a regular sort key, and then truncate everything after the delim:
556 : result.assign(this->m_pcollate->transform(p1, p2));
557 : std::size_t i;
558 : for(i = 0; i < result.size(); ++i)
559 : {
560 : if(result[i] == m_collate_delim)
561 : break;
562 : }
563 : result.erase(i);
564 : break;
565 : }
566 : #ifndef BOOST_NO_EXCEPTIONS
567 : }catch(...){}
568 : #endif
569 : while(result.size() && (charT(0) == *result.rbegin()))
570 : result.erase(result.size() - 1);
571 : if(result.empty())
572 : {
573 : // character is ignorable at the primary level:
574 : result = string_type(1, charT(0));
575 : }
576 : return result;
577 : }
578 :
579 : template <class charT>
580 : typename cpp_regex_traits_implementation<charT>::string_type
581 : cpp_regex_traits_implementation<charT>::transform(const charT* p1, const charT* p2) const
582 : {
583 : //
584 : // PRECONDITIONS:
585 : //
586 : // A bug in gcc 3.2 (and maybe other versions as well) treats
587 : // p1 as a null terminated string, for efficiency reasons
588 : // we work around this elsewhere, but just assert here that
589 : // we adhere to gcc's (buggy) preconditions...
590 : //
591 : BOOST_ASSERT(*p2 == 0);
592 : //
593 : // swallowing all exceptions here is a bad idea
594 : // however at least one std lib will always throw
595 : // std::bad_alloc for certain arguments...
596 : //
597 : string_type result, result2;
598 : #if defined(_CPPLIB_VER)
599 : //
600 : // A bug in VC11 and 12 causes the program to hang if we pass a null-string
601 : // to std::collate::transform, but only for certain locales :-(
602 : // Probably effects Intel and Clang or any compiler using the VC std library (Dinkumware).
603 : //
604 : if(*p1 == 0)
605 : {
606 : return result;
607 : }
608 : #endif
609 : #ifndef BOOST_NO_EXCEPTIONS
610 : try{
611 : #endif
612 : result = this->m_pcollate->transform(p1, p2);
613 : //
614 : // Borland's STLPort version returns a NULL-terminated
615 : // string that has garbage at the end - each call to
616 : // std::collate<wchar_t>::transform returns a different string!
617 : // So as a workaround, we'll truncate the string at the first NULL
618 : // which _seems_ to work....
619 : #if BOOST_WORKAROUND(__BORLANDC__, < 0x580)
620 : result.erase(result.find(charT(0)));
621 : #else
622 : //
623 : // some implementations (Dinkumware) append unnecessary trailing \0's:
624 : while(result.size() && (charT(0) == *result.rbegin()))
625 : result.erase(result.size() - 1);
626 : #endif
627 : //
628 : // We may have NULL's used as separators between sections of the collate string,
629 : // an example would be Boost.Locale. We have no way to detect this case via
630 : // #defines since this can be used with any compiler/platform combination.
631 : // Unfortunately our state machine (which was devised when all implementations
632 : // used underlying C language API's) can't cope with that case. One workaround
633 : // is to replace each character with 2, fortunately this code isn't used that
634 : // much as this is now slower than before :-(
635 : //
636 : typedef typename make_unsigned<charT>::type uchar_type;
637 : result2.reserve(result.size() * 2 + 2);
638 : for(unsigned i = 0; i < result.size(); ++i)
639 : {
640 : if(static_cast<uchar_type>(result[i]) == (std::numeric_limits<uchar_type>::max)())
641 : {
642 : result2.append(1, charT((std::numeric_limits<uchar_type>::max)())).append(1, charT('b'));
643 : }
644 : else
645 : {
646 : result2.append(1, static_cast<charT>(1 + static_cast<uchar_type>(result[i]))).append(1, charT('b') - 1);
647 : }
648 : }
649 : BOOST_ASSERT(std::find(result2.begin(), result2.end(), charT(0)) == result2.end());
650 : #ifndef BOOST_NO_EXCEPTIONS
651 : }
652 : catch(...)
653 : {
654 : }
655 : #endif
656 : return result2;
657 : }
658 :
659 :
660 : template <class charT>
661 : typename cpp_regex_traits_implementation<charT>::string_type
662 : cpp_regex_traits_implementation<charT>::lookup_collatename(const charT* p1, const charT* p2) const
663 : {
664 : typedef typename std::map<string_type, string_type>::const_iterator iter_type;
665 : if(m_custom_collate_names.size())
666 : {
667 : iter_type pos = m_custom_collate_names.find(string_type(p1, p2));
668 : if(pos != m_custom_collate_names.end())
669 : return pos->second;
670 : }
671 : #if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\
672 : && !BOOST_WORKAROUND(__BORLANDC__, <= 0x0551)
673 : std::string name(p1, p2);
674 : #else
675 : std::string name;
676 : const charT* p0 = p1;
677 : while(p0 != p2)
678 : name.append(1, char(*p0++));
679 : #endif
680 : name = lookup_default_collate_name(name);
681 : #if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\
682 : && !BOOST_WORKAROUND(__BORLANDC__, <= 0x0551)
683 : if(name.size())
684 : return string_type(name.begin(), name.end());
685 : #else
686 : if(name.size())
687 : {
688 : string_type result;
689 : typedef std::string::const_iterator iter;
690 : iter b = name.begin();
691 : iter e = name.end();
692 : while(b != e)
693 : result.append(1, charT(*b++));
694 : return result;
695 : }
696 : #endif
697 : if(p2 - p1 == 1)
698 : return string_type(1, *p1);
699 : return string_type();
700 : }
701 :
702 : template <class charT>
703 : void cpp_regex_traits_implementation<charT>::init()
704 : {
705 : #ifndef BOOST_NO_STD_MESSAGES
706 : #ifndef __IBMCPP__
707 : typename std::messages<charT>::catalog cat = static_cast<std::messages<char>::catalog>(-1);
708 : #else
709 : typename std::messages<charT>::catalog cat = reinterpret_cast<std::messages<char>::catalog>(-1);
710 : #endif
711 : std::string cat_name(cpp_regex_traits<charT>::get_catalog_name());
712 : if(cat_name.size() && (this->m_pmessages != 0))
713 : {
714 : cat = this->m_pmessages->open(
715 : cat_name,
716 : this->m_locale);
717 : if((int)cat < 0)
718 : {
719 : std::string m("Unable to open message catalog: ");
720 : std::runtime_error err(m + cat_name);
721 : boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err);
722 : }
723 : }
724 : //
725 : // if we have a valid catalog then load our messages:
726 : //
727 : if((int)cat >= 0)
728 : {
729 : //
730 : // Error messages:
731 : //
732 : for(boost::regex_constants::error_type i = static_cast<boost::regex_constants::error_type>(0);
733 : i <= boost::regex_constants::error_unknown;
734 : i = static_cast<boost::regex_constants::error_type>(i + 1))
735 : {
736 : const char* p = get_default_error_string(i);
737 : string_type default_message;
738 : while(*p)
739 : {
740 : default_message.append(1, this->m_pctype->widen(*p));
741 : ++p;
742 : }
743 : string_type s = this->m_pmessages->get(cat, 0, i+200, default_message);
744 : std::string result;
745 : for(std::string::size_type j = 0; j < s.size(); ++j)
746 : {
747 : result.append(1, this->m_pctype->narrow(s[j], 0));
748 : }
749 : m_error_strings[i] = result;
750 : }
751 : //
752 : // Custom class names:
753 : //
754 : #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
755 : static const char_class_type masks[16] =
756 : {
757 : static_cast<unsigned_native_mask_type>(std::ctype<charT>::alnum),
758 : static_cast<unsigned_native_mask_type>(std::ctype<charT>::alpha),
759 : static_cast<unsigned_native_mask_type>(std::ctype<charT>::cntrl),
760 : static_cast<unsigned_native_mask_type>(std::ctype<charT>::digit),
761 : static_cast<unsigned_native_mask_type>(std::ctype<charT>::graph),
762 : cpp_regex_traits_implementation<charT>::mask_horizontal,
763 : static_cast<unsigned_native_mask_type>(std::ctype<charT>::lower),
764 : static_cast<unsigned_native_mask_type>(std::ctype<charT>::print),
765 : static_cast<unsigned_native_mask_type>(std::ctype<charT>::punct),
766 : static_cast<unsigned_native_mask_type>(std::ctype<charT>::space),
767 : static_cast<unsigned_native_mask_type>(std::ctype<charT>::upper),
768 : cpp_regex_traits_implementation<charT>::mask_vertical,
769 : static_cast<unsigned_native_mask_type>(std::ctype<charT>::xdigit),
770 : cpp_regex_traits_implementation<charT>::mask_blank,
771 : cpp_regex_traits_implementation<charT>::mask_word,
772 : cpp_regex_traits_implementation<charT>::mask_unicode,
773 : };
774 : #else
775 : static const char_class_type masks[16] =
776 : {
777 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_alnum,
778 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_alpha,
779 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_cntrl,
780 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_digit,
781 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_graph,
782 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_horizontal_space,
783 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_lower,
784 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_print,
785 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_punct,
786 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_space,
787 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_upper,
788 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_vertical_space,
789 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_xdigit,
790 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_blank,
791 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_word,
792 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_unicode,
793 : };
794 : #endif
795 : static const string_type null_string;
796 : for(unsigned int j = 0; j <= 13; ++j)
797 : {
798 : string_type s(this->m_pmessages->get(cat, 0, j+300, null_string));
799 : if(s.size())
800 : this->m_custom_class_names[s] = masks[j];
801 : }
802 : }
803 : #endif
804 : //
805 : // get the collation format used by m_pcollate:
806 : //
807 : m_collate_type = BOOST_REGEX_DETAIL_NS::find_sort_syntax(this, &m_collate_delim);
808 : }
809 :
810 : template <class charT>
811 : typename cpp_regex_traits_implementation<charT>::char_class_type
812 : cpp_regex_traits_implementation<charT>::lookup_classname_imp(const charT* p1, const charT* p2) const
813 : {
814 : #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
815 : static const char_class_type masks[22] =
816 : {
817 : 0,
818 : static_cast<unsigned_native_mask_type>(std::ctype<char>::alnum),
819 : static_cast<unsigned_native_mask_type>(std::ctype<char>::alpha),
820 : cpp_regex_traits_implementation<charT>::mask_blank,
821 : static_cast<unsigned_native_mask_type>(std::ctype<char>::cntrl),
822 : static_cast<unsigned_native_mask_type>(std::ctype<char>::digit),
823 : static_cast<unsigned_native_mask_type>(std::ctype<char>::digit),
824 : static_cast<unsigned_native_mask_type>(std::ctype<char>::graph),
825 : cpp_regex_traits_implementation<charT>::mask_horizontal,
826 : static_cast<unsigned_native_mask_type>(std::ctype<char>::lower),
827 : static_cast<unsigned_native_mask_type>(std::ctype<char>::lower),
828 : static_cast<unsigned_native_mask_type>(std::ctype<char>::print),
829 : static_cast<unsigned_native_mask_type>(std::ctype<char>::punct),
830 : static_cast<unsigned_native_mask_type>(std::ctype<char>::space),
831 : static_cast<unsigned_native_mask_type>(std::ctype<char>::space),
832 : static_cast<unsigned_native_mask_type>(std::ctype<char>::upper),
833 : cpp_regex_traits_implementation<charT>::mask_unicode,
834 : static_cast<unsigned_native_mask_type>(std::ctype<char>::upper),
835 : cpp_regex_traits_implementation<charT>::mask_vertical,
836 : static_cast<unsigned_native_mask_type>(std::ctype<char>::alnum) | cpp_regex_traits_implementation<charT>::mask_word,
837 : static_cast<unsigned_native_mask_type>(std::ctype<char>::alnum) | cpp_regex_traits_implementation<charT>::mask_word,
838 : static_cast<unsigned_native_mask_type>(std::ctype<char>::xdigit),
839 : };
840 : #else
841 : static const char_class_type masks[22] =
842 : {
843 : 0,
844 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_alnum,
845 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_alpha,
846 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_blank,
847 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_cntrl,
848 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_digit,
849 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_digit,
850 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_graph,
851 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_horizontal_space,
852 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_lower,
853 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_lower,
854 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_print,
855 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_punct,
856 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_space,
857 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_space,
858 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_upper,
859 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_unicode,
860 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_upper,
861 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_vertical_space,
862 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_alnum | ::boost::BOOST_REGEX_DETAIL_NS::char_class_word,
863 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_alnum | ::boost::BOOST_REGEX_DETAIL_NS::char_class_word,
864 : ::boost::BOOST_REGEX_DETAIL_NS::char_class_xdigit,
865 : };
866 : #endif
867 : if(m_custom_class_names.size())
868 : {
869 : typedef typename std::map<std::basic_string<charT>, char_class_type>::const_iterator map_iter;
870 : map_iter pos = m_custom_class_names.find(string_type(p1, p2));
871 : if(pos != m_custom_class_names.end())
872 : return pos->second;
873 : }
874 : std::size_t state_id = 1 + BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2);
875 : BOOST_ASSERT(state_id < sizeof(masks) / sizeof(masks[0]));
876 : return masks[state_id];
877 : }
878 :
879 : #ifdef BOOST_REGEX_BUGGY_CTYPE_FACET
880 : template <class charT>
881 : bool cpp_regex_traits_implementation<charT>::isctype(const charT c, char_class_type mask) const
882 : {
883 : return
884 : ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_space) && (this->m_pctype->is(std::ctype<charT>::space, c)))
885 : || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_print) && (this->m_pctype->is(std::ctype<charT>::print, c)))
886 : || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_cntrl) && (this->m_pctype->is(std::ctype<charT>::cntrl, c)))
887 : || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_upper) && (this->m_pctype->is(std::ctype<charT>::upper, c)))
888 : || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_lower) && (this->m_pctype->is(std::ctype<charT>::lower, c)))
889 : || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_alpha) && (this->m_pctype->is(std::ctype<charT>::alpha, c)))
890 : || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_digit) && (this->m_pctype->is(std::ctype<charT>::digit, c)))
891 : || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_punct) && (this->m_pctype->is(std::ctype<charT>::punct, c)))
892 : || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_xdigit) && (this->m_pctype->is(std::ctype<charT>::xdigit, c)))
893 : || ((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))
894 : || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_word) && (c == '_'))
895 : || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_unicode) && ::boost::BOOST_REGEX_DETAIL_NS::is_extended(c))
896 : || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_vertical_space) && (is_separator(c) || (c == '\v')))
897 : || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_horizontal_space) && this->m_pctype->is(std::ctype<charT>::space, c) && !(is_separator(c) || (c == '\v')));
898 : }
899 : #endif
900 :
901 :
902 : template <class charT>
903 : inline boost::shared_ptr<const cpp_regex_traits_implementation<charT> > create_cpp_regex_traits(const std::locale& l)
904 : {
905 : cpp_regex_traits_base<charT> key(l);
906 : return ::boost::object_cache<cpp_regex_traits_base<charT>, cpp_regex_traits_implementation<charT> >::get(key, 5);
907 : }
908 :
909 : } // BOOST_REGEX_DETAIL_NS
910 :
911 : template <class charT>
912 : class cpp_regex_traits
913 : {
914 : private:
915 : typedef std::ctype<charT> ctype_type;
916 : public:
917 : typedef charT char_type;
918 : typedef std::size_t size_type;
919 : typedef std::basic_string<char_type> string_type;
920 : typedef std::locale locale_type;
921 : typedef boost::uint_least32_t char_class_type;
922 :
923 : struct boost_extensions_tag{};
924 :
925 : cpp_regex_traits()
926 : : m_pimpl(BOOST_REGEX_DETAIL_NS::create_cpp_regex_traits<charT>(std::locale()))
927 : { }
928 0 : static size_type length(const char_type* p)
929 : {
930 0 : return std::char_traits<charT>::length(p);
931 : }
932 : regex_constants::syntax_type syntax_type(charT c)const
933 : {
934 : return m_pimpl->syntax_type(c);
935 : }
936 : regex_constants::escape_syntax_type escape_syntax_type(charT c) const
937 : {
938 : return m_pimpl->escape_syntax_type(c);
939 : }
940 : charT translate(charT c) const
941 : {
942 : return c;
943 : }
944 : charT translate_nocase(charT c) const
945 : {
946 : return m_pimpl->m_pctype->tolower(c);
947 : }
948 0 : charT translate(charT c, bool icase) const
949 : {
950 0 : return icase ? m_pimpl->m_pctype->tolower(c) : c;
951 : }
952 0 : charT tolower(charT c) const
953 : {
954 0 : return m_pimpl->m_pctype->tolower(c);
955 : }
956 0 : charT toupper(charT c) const
957 : {
958 0 : return m_pimpl->m_pctype->toupper(c);
959 : }
960 0 : string_type transform(const charT* p1, const charT* p2) const
961 : {
962 0 : return m_pimpl->transform(p1, p2);
963 : }
964 0 : string_type transform_primary(const charT* p1, const charT* p2) const
965 : {
966 0 : return m_pimpl->transform_primary(p1, p2);
967 : }
968 : char_class_type lookup_classname(const charT* p1, const charT* p2) const
969 : {
970 : return m_pimpl->lookup_classname(p1, p2);
971 : }
972 : string_type lookup_collatename(const charT* p1, const charT* p2) const
973 : {
974 : return m_pimpl->lookup_collatename(p1, p2);
975 : }
976 0 : bool isctype(charT c, char_class_type f) const
977 : {
978 : #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
979 : typedef typename std::ctype<charT>::mask ctype_mask;
980 :
981 : static const ctype_mask mask_base =
982 : static_cast<ctype_mask>(
983 : std::ctype<charT>::alnum
984 : | std::ctype<charT>::alpha
985 : | std::ctype<charT>::cntrl
986 : | std::ctype<charT>::digit
987 : | std::ctype<charT>::graph
988 : | std::ctype<charT>::lower
989 : | std::ctype<charT>::print
990 : | std::ctype<charT>::punct
991 : | std::ctype<charT>::space
992 : | std::ctype<charT>::upper
993 : | std::ctype<charT>::xdigit);
994 :
995 0 : if((f & mask_base)
996 0 : && (m_pimpl->m_pctype->is(
997 : static_cast<ctype_mask>(f & mask_base), c)))
998 : return true;
999 : 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 0 : else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation<charT>::mask_word) && (c == '_'))
1002 : return true;
1003 0 : else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation<charT>::mask_blank)
1004 0 : && m_pimpl->m_pctype->is(std::ctype<charT>::space, c)
1005 0 : && !BOOST_REGEX_DETAIL_NS::is_separator(c))
1006 : return true;
1007 0 : else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation<charT>::mask_vertical)
1008 0 : && (::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) || (c == '\v')))
1009 : return true;
1010 0 : else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation<charT>::mask_horizontal)
1011 0 : && this->isctype(c, std::ctype<charT>::space) && !this->isctype(c, BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation<charT>::mask_vertical))
1012 0 : return true;
1013 : #ifdef __CYGWIN__
1014 : //
1015 : // Cygwin has a buggy ctype facet, see https://www.cygwin.com/ml/cygwin/2012-08/msg00178.html:
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 0 : std::string error_string(regex_constants::error_type n) const
1047 : {
1048 0 : return m_pimpl->error_string(n);
1049 : }
1050 :
1051 : //
1052 : // extension:
1053 : // set the name of the message catalog in use (defaults to "boost_regex").
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 : // catalog name handler:
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; // buffer for parsing numbers.
1075 : std::basic_istream<charT> is(&sbuf); // stream for parsing numbers.
1076 :
1077 : // we do NOT want to parse any thousands separators inside the stream:
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 :
1133 : } // boost
1134 :
1135 : #ifdef BOOST_MSVC
1136 : #pragma warning(pop)
1137 : #endif
1138 :
1139 : #ifdef BOOST_MSVC
1140 : #pragma warning(push)
1141 : #pragma warning(disable: 4103)
1142 : #endif
1143 : #ifdef BOOST_HAS_ABI_HEADERS
1144 : # include BOOST_ABI_SUFFIX
1145 : #endif
1146 : #ifdef BOOST_MSVC
1147 : #pragma warning(pop)
1148 : #endif
1149 :
1150 : #endif
1151 :
1152 : #endif
1153 :
1154 :
|