]> git.lyx.org Git - lyx.git/blob - boost/libs/regex/src/cpp_regex_traits.cpp
update
[lyx.git] / boost / libs / regex / src / cpp_regex_traits.cpp
1 /*
2  *
3  * Copyright (c) 1998-2002
4  * Dr John Maddock
5  *
6  * Permission to use, copy, modify, distribute and sell this software
7  * and its documentation for any purpose is hereby granted without fee,
8  * provided that the above copyright notice appear in all copies and
9  * that both that copyright notice and this permission notice appear
10  * in supporting documentation.  Dr John Maddock makes no representations
11  * about the suitability of this software for any purpose.  
12  * It is provided "as is" without express or implied warranty.
13  *
14  */
15  
16  /*
17   *   LOCATION:    see http://www.boost.org for most recent version.
18   *   FILE:        c_regex_traits.cpp
19   *   VERSION:     see <boost/version.hpp>
20   *   DESCRIPTION: Implements the cpp_regex_traits<charT> traits class
21   */
22
23
24 #define BOOST_REGEX_SOURCE
25
26 #include <boost/regex/config.hpp>
27
28 #ifndef BOOST_NO_STD_LOCALE
29
30 # ifdef BOOST_MSVC
31 #  pragma warning(disable:4786 4702 4127 4244)
32 #  endif
33
34 #include <clocale>
35 #include <locale>
36 #include <cstdio>
37 #include <list>
38 #include <cctype>
39 #include <iostream>
40 #include <map>
41 #include <boost/regex/regex_traits.hpp>
42 #include <boost/cregex.hpp>
43 #include <boost/scoped_array.hpp>
44 #include "primary_transform.hpp"
45
46 # ifdef BOOST_MSVC
47 #  pragma warning(disable:4786 4702 4127 4244)
48 #  endif
49
50 namespace{
51    const unsigned int re_classes_max = 14;
52    const unsigned int char_set_size = CHAR_MAX - CHAR_MIN + 1;
53
54 boost::uint_fast32_t re_char_class_id[] = {
55    boost::re_detail::cpp_regex_traits_base::char_class_alnum,
56    boost::re_detail::cpp_regex_traits_base::char_class_alpha,
57    boost::re_detail::cpp_regex_traits_base::char_class_cntrl,
58    boost::re_detail::cpp_regex_traits_base::char_class_digit,
59    boost::re_detail::cpp_regex_traits_base::char_class_graph,
60    boost::re_detail::cpp_regex_traits_base::char_class_lower,
61    boost::re_detail::cpp_regex_traits_base::char_class_print,
62    boost::re_detail::cpp_regex_traits_base::char_class_punct,
63    boost::re_detail::cpp_regex_traits_base::char_class_space,
64    boost::re_detail::cpp_regex_traits_base::char_class_upper,
65    boost::re_detail::cpp_regex_traits_base::char_class_xdigit,
66    boost::re_detail::cpp_regex_traits_base::char_class_blank,
67    boost::re_detail::cpp_regex_traits_base::char_class_word,
68    boost::re_detail::cpp_regex_traits_base::char_class_unicode,
69 };
70
71 const char* re_char_class_names[] = {
72 "alnum",
73 "alpha",
74 "cntrl",
75 "digit",
76 "graph",
77 "lower",
78 "print",
79 "punct",
80 "space",
81 "upper",
82 "xdigit",
83 "blank",
84 "word",
85 "unicode",
86 };
87
88 template <class charT,
89           class traits = ::std::char_traits<charT> >
90 class parser_buf : public ::std::basic_streambuf<charT, traits>
91 {
92    typedef ::std::basic_streambuf<charT, traits> base_type;
93    typedef typename base_type::int_type int_type;
94    typedef typename base_type::char_type char_type;
95    typedef typename base_type::pos_type pos_type;
96    typedef ::std::streamsize streamsize;
97    typedef typename base_type::off_type off_type;
98 public:
99    parser_buf() : base_type() { setbuf(0, 0); }
100    const charT* getnext() { return this->gptr(); }
101 protected:
102    std::basic_streambuf<charT, traits>* setbuf(char_type* s, streamsize n);
103    typename parser_buf<charT, traits>::pos_type seekpos(pos_type sp, ::std::ios_base::openmode which);
104    typename parser_buf<charT, traits>::pos_type seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which);
105 private:
106    parser_buf& operator=(const parser_buf&);
107    parser_buf(const parser_buf&);
108 };
109
110 template<class charT, class traits>
111 std::basic_streambuf<charT, traits>*
112 parser_buf<charT, traits>::setbuf(char_type* s, streamsize n)
113 {
114    this->setg(s, s, s + n);
115    return this;
116 }
117
118 template<class charT, class traits>
119 typename parser_buf<charT, traits>::pos_type
120 parser_buf<charT, traits>::seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which)
121 {
122    typedef typename parser_buf<charT, traits>::pos_type pos_type;
123    if(which & ::std::ios_base::out)
124       return pos_type(off_type(-1));
125    std::ptrdiff_t size = this->egptr() - this->eback();
126    std::ptrdiff_t pos = this->gptr() - this->eback();
127    charT* g = this->eback();
128    switch(way)
129    {
130    case ::std::ios_base::beg:
131       if((off < 0) || (off > size))
132          return pos_type(off_type(-1));
133       else
134          this->setg(g, g + off, g + size);
135    case ::std::ios_base::end:
136       if((off < 0) || (off > size))
137          return pos_type(off_type(-1));
138       else
139          this->setg(g, g + size - off, g + size);
140    case ::std::ios_base::cur:
141    {
142       std::ptrdiff_t newpos = pos + off;
143       if((newpos < 0) || (newpos > size))
144          return pos_type(off_type(-1));
145       else
146          this->setg(g, g + newpos, g + size);
147    }
148    }
149    return static_cast<pos_type>(this->gptr() - this->eback());
150 }
151
152 template<class charT, class traits>
153 typename parser_buf<charT, traits>::pos_type
154 parser_buf<charT, traits>::seekpos(pos_type sp, ::std::ios_base::openmode which)
155 {
156    if(which & ::std::ios_base::out)
157       return pos_type(off_type(-1));
158    std::ptrdiff_t size = this->egptr() - this->eback();
159    charT* g = this->eback();
160    if(sp <= size)
161    {
162       this->setg(g, g + ::std::streamsize(sp), g + size);
163    }
164    return pos_type(off_type(-1));
165 }
166
167
168 } // namespace
169
170 namespace boost{
171    namespace re_detail{
172
173 template <>
174 struct message_data<char>
175 {
176    unsigned char syntax_map[CHAR_MAX-CHAR_MIN];
177    std::map<std::string, std::string, std::less<std::string> > collating_elements;
178    std::map<std::string, std::size_t, std::less<std::string> > classes;
179    //std::string _zero;
180    //std::string _ten;
181    parser_buf<char> sbuf;
182    std::istream is;
183    std::string error_strings[boost::REG_E_UNKNOWN+1];
184
185    message_data(const std::locale& l, const std::string& regex_message_catalogue);
186 private:
187    message_data(const message_data&);
188    message_data& operator=(const message_data&);
189 };
190
191
192 message_data<char>::message_data(const std::locale& l, const std::string& regex_message_catalogue)
193    : is(&sbuf)
194 {
195    is.imbue(l);
196 #ifndef BOOST_NO_STD_MESSAGES
197
198    const std::messages<char>* pm = 0;
199    std::messages<char>::catalog cat = -1;
200    if(regex_message_catalogue.size())
201    {
202       pm = &BOOST_USE_FACET(std::messages<char>, l);
203       cat = pm->open(regex_message_catalogue, l);
204 #ifndef BOOST_NO_EXCEPTIONS
205       if(cat < 0)
206       {
207          std::string m("Unable to open message catalog: ");
208          throw std::runtime_error(m + regex_message_catalogue);
209       }
210 #else
211       BOOST_REGEX_NOEH_ASSERT(cat >= 0);
212 #endif
213    } 
214 #endif
215    std::memset(syntax_map, cpp_regex_traits<char>::syntax_char, 256);
216    unsigned i;
217    scoped_array<char> a;
218    std::size_t array_size = 0;
219    std::size_t new_size;
220    for(i = 1; i < cpp_regex_traits<char>::syntax_max; ++i)
221    {
222       new_size = re_get_default_message(0, 0, i+100);
223       if(new_size > array_size)
224       {
225          a.reset(new char[new_size]);
226          array_size = new_size;
227       }
228       re_get_default_message(a.get(), array_size, i+100);
229       std::string s = a.get();
230 #ifndef BOOST_NO_STD_MESSAGES
231       if((int)cat >= 0)
232          s = pm->get(cat, 0, i+100, s);
233 #endif
234       for(std::size_t j = 0; j < s.size(); ++j)
235       {
236          syntax_map[s[j]] = (unsigned char)(i);
237       }
238    }
239
240 #ifndef BOOST_NO_STD_MESSAGES
241    // load any custom collate names:
242    //
243    // for some reason Borland C++ Builder 6 won't let us use
244    // std::isspace(char, std::locale) unless we call it
245    // unqualifed - weird.  This seems to be affecting other
246    // STLport users as well (gcc3.1+STLport5), so enable the
247    // workaround for all STLport users...
248    //
249 #if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
250    using namespace std;
251 #  define BOOST_REGEX_STD
252 #else
253 #  define BOOST_REGEX_STD std::
254 #endif
255
256    std::string c1, c2;
257    i = 400;
258    if((int)cat >= 0)
259    {
260       c2 = pm->get(cat, 0, i, c1);
261       while(c2.size())
262       {
263          const char* p1, *p2, *p3, *p4;;
264          p1 = c2.c_str();
265          while(*p1 && BOOST_REGEX_STD isspace((char)*p1, l))++p1;
266          p2 = p1;
267          while(*p2 && !BOOST_REGEX_STD isspace((char)*p2, l))++p2;
268          p3 = p2;
269          while(*p3 && BOOST_REGEX_STD isspace((char)*p3, l))++p3;
270          p4 = p3;
271          while(*p4 && !BOOST_REGEX_STD isspace((char)*p4, l))++p4;
272          collating_elements[std::string(p1, p2)] = std::string(p3, p4);
273
274          ++i;
275          c2 = pm->get(cat, 0, i, c1);
276       }
277    }
278 #endif
279    std::string m;
280    std::string s;
281 #ifndef BOOST_NO_STD_MESSAGES
282    if((int)cat >= 0)
283    {
284       for(i = 0; i < re_classes_max; ++i)
285       {
286          s = pm->get(cat, 0, i+300, m);
287          if(s.size())
288             classes[s] = i;
289       }
290       for(i = 0; i <= boost::REG_E_UNKNOWN ; ++i)
291       {
292          s = pm->get(cat, 0, i+200, m);
293          error_strings[i] = s;
294       }
295    }
296
297    if((int)cat >= 0)
298       pm->close(cat);
299 #endif
300 }
301
302 std::string BOOST_REGEX_CALL cpp_regex_traits_base::set_message_catalogue(const std::string& l)
303 {
304    if(sizeof(regex_message_cat) <= l.size())
305       return l;
306    std::string old(regex_message_cat);
307    std::strcpy(regex_message_cat, l.c_str());
308    return old;
309 }
310
311 char cpp_regex_traits_base::regex_message_cat[BOOST_REGEX_MAX_PATH] = {0};
312
313
314 } // namespace re_detail
315
316
317 cpp_regex_traits<char>::cpp_regex_traits()
318 {
319    pmd = new re_detail::message_data<char>(locale_inst, regex_message_cat);
320    psyntax = pmd->syntax_map;
321 #ifndef BOOST_NO_EXCEPTIONS
322    try{
323 #endif
324       lower_map = new char[char_set_size];
325       BOOST_REGEX_NOEH_ASSERT(lower_map)
326 #ifndef BOOST_NO_EXCEPTIONS
327    }
328    catch(...)
329    {
330       delete pmd;
331       throw;
332    }
333 #endif
334    for(unsigned int i = 0; i < char_set_size; ++i)
335       lower_map[i] = static_cast<char>(i);
336    pctype = &BOOST_USE_FACET(std::ctype<char>, locale_inst);
337    pctype->tolower(&lower_map[0], &lower_map[char_set_size]);
338    pcollate = &BOOST_USE_FACET(std::collate<char>, locale_inst);
339    sort_type = re_detail::find_sort_syntax(this, &(this->sort_delim));
340 }
341
342 cpp_regex_traits<char>::~cpp_regex_traits()
343 {
344    delete pmd;
345    delete[] lower_map;
346 }
347
348 int BOOST_REGEX_CALL cpp_regex_traits<char>::toi(char c)const
349 {
350    pmd->sbuf.pubsetbuf(&c, 1);
351    pmd->is.clear();
352    pmd->is >> std::dec;
353    int val;
354    if(pmd->is >> val)
355    {
356       return val;
357    }
358    else
359       return 0;
360 }
361
362 int BOOST_REGEX_CALL cpp_regex_traits<char>::toi(const char*& first, const char* last, int radix)const
363 {
364    pmd->sbuf.pubsetbuf(const_cast<char*>(first), static_cast<std::streamsize>(last-first));
365    pmd->is.clear();
366    if(std::abs(radix) == 16) pmd->is >> std::hex;
367    else if(std::abs(radix) == 8) pmd->is >> std::oct;
368    else pmd->is >> std::dec;
369    int val;
370    if(pmd->is >> val)
371    {
372       first = first + ((last - first) - pmd->sbuf.in_avail());
373       return val;
374    }
375    else
376       return 0;
377 }
378
379 boost::uint_fast32_t BOOST_REGEX_CALL cpp_regex_traits<char>::lookup_classname(const char* first, const char* last)const
380 {
381    BOOST_RE_GUARD_STACK
382    unsigned int i;
383    std::string s(first, last);
384
385    std::map<std::string, std::size_t, std::less<std::string> >::const_iterator pos = pmd->classes.find(s);
386    if(pos != pmd->classes.end())
387       return re_char_class_id[(*pos).second];
388
389    for(i = 0; i < re_classes_max; ++i)
390    {
391       if(s == re_char_class_names[i])
392          return re_char_class_id[i];
393    }
394    return 0;
395 }
396
397 bool BOOST_REGEX_CALL cpp_regex_traits<char>::lookup_collatename(std::string& s, const char* first, const char* last)const
398 {
399    BOOST_RE_GUARD_STACK
400    std::string name(first, last);
401    std::map<std::string, std::string, std::less<std::string > >::const_iterator pos = pmd->collating_elements.find(name);
402    if(pos != pmd->collating_elements.end())
403    {
404       s = (*pos).second;
405       return true;
406    }
407    return re_detail::re_lookup_def_collate_name(s, name.c_str());
408 }
409
410 void BOOST_REGEX_CALL cpp_regex_traits<char>::transform_primary(std::string& out, const std::string& in)const
411 {
412    transform(out, in);
413    switch(sort_type)
414    {
415    case re_detail::sort_C:
416    case re_detail::sort_unknown:
417       break;
418    case re_detail::sort_fixed:
419       if((unsigned)sort_delim < out.size())
420          out.erase((int)sort_delim);
421       break;
422    case re_detail::sort_delim:
423       for(unsigned int i = 0; i < out.size(); ++i)
424       {
425          if((out[i] == sort_delim) && (i+1 < out.size()))
426          {
427             out.erase(i+1);
428             break;
429          }
430       }
431    }
432 }
433
434
435 std::string BOOST_REGEX_CALL cpp_regex_traits<char>::error_string(unsigned id)const
436 {
437    if((id <= boost::REG_E_UNKNOWN) && (pmd->error_strings[id].size()))
438       return pmd->error_strings[id];
439    return boost::re_detail::re_default_error_messages[id];
440 }
441
442 cpp_regex_traits<char>::locale_type BOOST_REGEX_CALL cpp_regex_traits<char>::imbue(locale_type l)
443 {
444    locale_type old_l(locale_inst);
445    locale_inst = l;
446    re_detail::message_data<char>* npmd = new re_detail::message_data<char>(locale_inst, regex_message_cat);
447    delete pmd;
448    pmd = npmd;
449    psyntax = pmd->syntax_map;
450    for(unsigned int i = 0; i < char_set_size; ++i)
451       lower_map[i] = static_cast<char>(i);
452    pctype = &BOOST_USE_FACET(std::ctype<char>, locale_inst);
453    pctype->tolower(&lower_map[0], &lower_map[char_set_size]);
454    pcollate = &BOOST_USE_FACET(std::collate<char>, locale_inst);
455    sort_type = re_detail::find_sort_syntax(this, &(this->sort_delim));
456    return old_l;
457 }
458
459 #ifndef BOOST_NO_WREGEX
460
461 namespace re_detail{
462
463 std::string BOOST_REGEX_CALL to_narrow(const std::basic_string<wchar_t>& is, const std::codecvt<wchar_t, char, std::mbstate_t>& cvt)
464 {
465    BOOST_RE_GUARD_STACK
466    std::basic_string<wchar_t>::size_type bufsize = is.size() * 2;
467    //
468    // declare buffer first as VC6 workaround for internal compiler error!
469    char* pc = new char[bufsize];
470    scoped_array<char> t(pc);
471    #if defined(BOOST_MSVC) && !defined(DINKUMWARE_CE)
472    std::mbstate_t state = 0;
473    #else
474    std::mbstate_t state = std::mbstate_t();
475    #endif
476
477    const wchar_t* next_in;
478    char* next_out;
479    while(true)
480    {
481       switch(cvt.out(state, is.c_str(), is.c_str() + is.size(), next_in, t.get(), t.get() + bufsize, next_out))
482       {
483       case std::codecvt_base::ok:
484          return std::string(t.get(), next_out);
485       case std::codecvt_base::partial:
486          bufsize *= 2;
487          t.reset(new char[bufsize]);
488          continue;
489       case std::codecvt_base::error:
490          // not much we can do here but guess:
491       case std::codecvt_base::noconv:
492          std::string out;
493          for(unsigned i = 0; i < is.size(); ++i)
494          {
495             out.append(1, (char)is[i]);
496          }
497          return out;
498       }
499    }
500 }
501
502 std::wstring BOOST_REGEX_CALL to_wide(const std::string& is, const std::codecvt<wchar_t, char, std::mbstate_t>& cvt)
503 {
504    BOOST_RE_GUARD_STACK
505    std::string::size_type bufsize = is.size() + 2;
506    std::string::size_type maxsize = is.size() * 100;
507    //
508    // declare buffer first as VC6 workaround for internal compiler error!
509    wchar_t* pc = new wchar_t[bufsize];
510    scoped_array<wchar_t> t(pc);
511    #if defined(BOOST_MSVC) && !defined(DINKUMWARE_CE)
512    std::mbstate_t state = 0;
513    #else
514    std::mbstate_t state = std::mbstate_t();
515    #endif
516
517
518    wchar_t* next_out;
519    const char* next_in;
520    while(true)
521    {
522       switch(cvt.in(state, is.c_str(), is.c_str() + is.size(), next_in, t.get(), t.get() + bufsize, next_out))
523       {
524       case std::codecvt_base::ok:
525          return std::wstring(t.get(), next_out);
526       case std::codecvt_base::partial:
527          bufsize *= 2;
528          if(bufsize < maxsize)
529          {
530             t.reset(new wchar_t[bufsize]);
531             continue;
532          }
533          //
534          // error fall through:
535       case std::codecvt_base::error:
536          // not much we can do here but guess:
537       case std::codecvt_base::noconv:
538          std::wstring out;
539          for(unsigned i = 0; i < is.size(); ++i)
540          {
541             out.append(1, is[i]);
542          }
543          return out;
544       }
545    }
546 }
547
548
549
550 template <>
551 struct message_data<wchar_t>
552 {
553 #ifndef BOOST_NO_STD_MESSAGES
554    typedef std::messages<wchar_t>::string_type string_type;
555 #else
556    typedef std::wstring string_type;
557 #endif
558
559    string_type name;
560
561    struct syntax_map
562    {
563       wchar_t c;
564       unsigned int type;
565    };
566
567    std::list<syntax_map> syntax;
568    std::map<string_type, std::size_t> classes;
569    std::map<string_type, string_type> collating_elements;
570    unsigned char syntax_[CHAR_MAX-CHAR_MIN+1];
571
572    parser_buf<wchar_t> sbuf;
573    std::wistream is;
574    std::string error_strings[boost::REG_E_UNKNOWN+1];
575
576    message_data(const std::locale& l, const std::string& regex_message_catalogue);
577 private:
578    message_data(const message_data&);
579    message_data& operator=(const message_data&);
580 };
581
582 message_data<wchar_t>::message_data(const std::locale& l, const std::string& regex_message_catalogue)
583    : is(&sbuf)
584 {
585    is.imbue(l);
586    syntax_map m;
587    typedef std::codecvt<wchar_t, char, std::mbstate_t> cvt_type;
588    const cvt_type& cvt = BOOST_USE_FACET(cvt_type, l);
589 #ifndef BOOST_NO_STD_MESSAGES
590    const std::messages<wchar_t>& msgs = BOOST_USE_FACET(std::messages<wchar_t>, l);
591    std::messages<wchar_t>::catalog cat = -1;
592    if(regex_message_catalogue.size())
593    {
594       cat = msgs.open(regex_message_catalogue, l);
595 #ifndef BOOST_NO_EXCEPTIONS
596       if(cat < 0)
597       {
598          std::string m("Unable to open message catalog: ");
599          throw std::runtime_error(m + regex_message_catalogue);
600       }
601 #else
602       BOOST_REGEX_NOEH_ASSERT(cat >= 0);
603 #endif
604    }
605 #endif
606    scoped_array<char> a;
607    std::size_t array_size = 0;
608    std::size_t new_size;
609    std::size_t i;
610    std::memset(syntax_, cpp_regex_traits<wchar_t>::syntax_char, sizeof(syntax_));
611    for(i = 1; i < cpp_regex_traits<wchar_t>::syntax_max; ++i)
612    {
613       new_size = re_get_default_message(0, 0, i+100);
614       if(new_size > array_size)
615       {
616          a.reset(new char[new_size]);
617          array_size = new_size;
618       }
619       re_get_default_message(a.get(), array_size, i+100);
620       std::string ns = a.get();
621       string_type s = to_wide(ns, cvt);
622 #ifndef BOOST_NO_STD_MESSAGES
623       if((int)cat >= 0)
624          s = BOOST_USE_FACET(std::messages<wchar_t>, l).get(cat, 0, (int)i+100, s);
625 #endif
626       for(unsigned int j = 0; j < s.size(); ++j)
627       {
628          if((s[j] <= UCHAR_MAX) && (s[j] >= 0))
629             syntax_[s[j]] = static_cast<unsigned char>(i);
630          else
631          {
632             m.c = s[j];
633             m.type = static_cast<unsigned int>(i);
634             syntax.push_back(m);
635          }
636       }
637    }
638
639 #ifndef BOOST_NO_STD_MESSAGES
640    // load any custom collate names:
641    string_type c1, c2;
642    i = 400;
643    if((int)cat >= 0)
644    {
645       c2 = msgs.get(cat, 0, (int)i, c1);
646       while(c2.size())
647       {
648          const wchar_t* p1, *p2, *p3, *p4;;
649          p1 = c2.c_str();
650          while(*p1 && BOOST_REGEX_STD isspace((wchar_t)*p1, l))++p1;
651          p2 = p1;
652          while(*p2 && !BOOST_REGEX_STD isspace((wchar_t)*p2, l))++p2;
653          p3 = p2;
654          while(*p3 && BOOST_REGEX_STD isspace((wchar_t)*p3, l))++p3;
655          p4 = p3;
656          while(*p4 && !BOOST_REGEX_STD isspace((wchar_t)*p4, l))++p4;
657          collating_elements[std::basic_string<wchar_t>(p1, p2)] = std::basic_string<wchar_t>(p3, p4);
658
659          ++i;
660          c2 = msgs.get(cat, 0, (int)i, c1);
661       }
662    }
663
664    if((int)cat >= 0)
665    {
666       c2.erase();
667       for(i = 0; i < re_classes_max; ++i)
668       {
669          c1 = msgs.get(cat, 0, static_cast<int>(i+300), c2);
670          if(c1.size())
671             classes[c1] = i;
672       }
673       for(i = 0; i <= boost::REG_E_UNKNOWN ; ++i)
674       {
675          c1 = msgs.get(cat, 0, static_cast<int>(i+200), c2);
676          error_strings[i] = to_narrow(c1, cvt);
677       }
678    }
679
680    if((int)cat >= 0)
681       msgs.close(cat);
682 #endif      
683 }
684
685 } // namespace re_detail
686
687 unsigned int BOOST_REGEX_CALL cpp_regex_traits<wchar_t>::do_syntax_type(size_type c)const
688 {
689    std::list<re_detail::message_data<wchar_t>::syntax_map>::const_iterator i, j;
690    i = pmd->syntax.begin();
691    j = pmd->syntax.end();
692    while(i != j)
693    {
694       if(((uchar_type)(*i).c) == c)
695          return (*i).type;
696       ++i;
697    }
698    return 0;
699 }
700
701 void BOOST_REGEX_CALL cpp_regex_traits<wchar_t>::transform_primary(std::basic_string<wchar_t>& out, const std::basic_string<wchar_t>& in)const
702 {
703    transform(out, in);
704    switch(sort_type)
705    {
706    case re_detail::sort_C:
707    case re_detail::sort_unknown:
708       break;
709    case re_detail::sort_fixed:
710       if((unsigned)sort_delim < out.size())
711          out.erase((int)sort_delim);
712       break;
713    case re_detail::sort_delim:
714       for(unsigned int i = 0; i < out.size(); ++i)
715       {
716          if((out[i] == sort_delim) && (i+1 < out.size()))
717          {
718             out.erase(i+1);
719             break;
720          }
721       }
722    }
723 }
724
725 int BOOST_REGEX_CALL cpp_regex_traits<wchar_t>::toi(wchar_t c)const
726 {
727    pmd->sbuf.pubsetbuf(&c, 1);
728    pmd->is.clear();
729    pmd->is >> std::dec;
730    int val;
731    if(pmd->is >> val)
732    {
733       return val;
734    }
735    else
736       return 0;
737 }
738
739 int BOOST_REGEX_CALL cpp_regex_traits<wchar_t>::toi(const wchar_t*& first, const wchar_t* last, int radix)const
740 {
741    pmd->sbuf.pubsetbuf(const_cast<wchar_t*>(first), static_cast<std::streamsize>(last-first));
742    pmd->is.clear();
743    if(std::abs(radix) == 16) pmd->is >> std::hex;
744    else if(std::abs(radix) == 8) pmd->is >> std::oct;
745    else pmd->is >> std::dec;
746    int val;
747    if(pmd->is >> val)
748    {
749       first = first + ((last - first) - pmd->sbuf.in_avail());
750       return val;
751    }
752    else
753       return 0;
754 }
755
756 boost::uint_fast32_t BOOST_REGEX_CALL cpp_regex_traits<wchar_t>::lookup_classname(const wchar_t* first, const wchar_t* last)const
757 {
758    BOOST_RE_GUARD_STACK
759    unsigned int i;
760    std::wstring s(first, last);
761
762    std::map<std::wstring, std::size_t>::const_iterator pos = pmd->classes.find(s);
763    if(pos != pmd->classes.end())
764       return re_char_class_id[(*pos).second];
765
766    std::string ns = re_detail::to_narrow(s, *pcdv);
767
768    for(i = 0; i < re_classes_max; ++i)
769    {
770       if(ns == re_char_class_names[i])
771          return re_char_class_id[i];
772    }
773    return 0;
774 }
775
776 bool BOOST_REGEX_CALL cpp_regex_traits<wchar_t>::lookup_collatename(std::basic_string<wchar_t>& s, const wchar_t* first, const wchar_t* last)const
777 {
778    BOOST_RE_GUARD_STACK
779    std::wstring name(first, last);
780    std::map<std::wstring, std::wstring>::const_iterator pos = pmd->collating_elements.find(name);
781    if(pos != pmd->collating_elements.end())
782    {
783       s = (*pos).second;
784       return true;
785    }
786    std::string ns = re_detail::to_narrow(name, *pcdv);
787    std::string ns2;
788    bool result = re_detail::re_lookup_def_collate_name(ns2, ns.c_str());
789    s = re_detail::to_wide(ns2, *pcdv);
790    return result;
791 }
792
793 std::string BOOST_REGEX_CALL cpp_regex_traits<wchar_t>::error_string(unsigned id)const
794 {
795    if((id <= boost::REG_E_UNKNOWN) && (pmd->error_strings[id].size()))
796       return pmd->error_strings[id];
797    return boost::re_detail::re_default_error_messages[id];
798 }
799
800 cpp_regex_traits<wchar_t>::cpp_regex_traits()
801 {
802    pmd = new re_detail::message_data<wchar_t>(locale_inst, std::string(regex_message_cat));
803    psyntax = pmd->syntax_;
804 #ifndef BOOST_NO_EXCEPTIONS
805    try{
806 #endif
807       lower_map = new wchar_t[char_set_size];
808       BOOST_REGEX_NOEH_ASSERT(lower_map)
809 #ifndef BOOST_NO_EXCEPTIONS
810    }
811    catch(...)
812    {
813       delete pmd;
814       throw;
815    }
816 #endif
817    for(unsigned int i = 0; i < char_set_size; ++i)
818       lower_map[i] = static_cast<wchar_t>(i);
819    pctype = &BOOST_USE_FACET(std::ctype<wchar_t>, locale_inst);
820    pctype->tolower(&lower_map[0], &lower_map[char_set_size]);
821    pcollate = &BOOST_USE_FACET(std::collate<wchar_t>, locale_inst);
822    typedef std::codecvt<wchar_t, char, std::mbstate_t> cvt_t;
823    pcdv = &BOOST_USE_FACET(cvt_t, locale_inst);
824    sort_type = re_detail::find_sort_syntax(this, &(this->sort_delim));
825 }
826
827 cpp_regex_traits<wchar_t>::~cpp_regex_traits()
828 {
829    delete pmd;
830    delete[] lower_map;
831 }
832
833 cpp_regex_traits<wchar_t>::locale_type BOOST_REGEX_CALL cpp_regex_traits<wchar_t>::imbue(locale_type l)
834 {
835    locale_type old_l(locale_inst);
836    locale_inst = l;
837    re_detail::message_data<wchar_t>* npmd = new re_detail::message_data<wchar_t>(locale_inst, std::string(regex_message_cat));
838    delete pmd;
839    pmd = npmd;
840    psyntax = pmd->syntax_;
841    for(unsigned int i = 0; i < char_set_size; ++i)
842       lower_map[i] = static_cast<wchar_t>(i);
843    pctype = &BOOST_USE_FACET(std::ctype<wchar_t>, locale_inst);
844    pctype->tolower(&lower_map[0], &lower_map[char_set_size]);
845    pcollate = &BOOST_USE_FACET(std::collate<wchar_t>, locale_inst);
846    typedef std::codecvt<wchar_t, char, std::mbstate_t> cvt_t;
847    pcdv = &BOOST_USE_FACET(cvt_t, locale_inst);
848    sort_type = re_detail::find_sort_syntax(this, &(this->sort_delim));
849    return old_l;
850 }
851
852 std::size_t BOOST_REGEX_CALL cpp_regex_traits<wchar_t>::strwiden(wchar_t *s1, std::size_t len, const char *s2)const
853 {
854    std::string s(s2);
855    std::wstring ws = re_detail::to_wide(s2, *pcdv);
856    if(len > ws.size())
857       std::wcscpy(s1, ws.c_str());
858    return ws.size()+1;
859 }
860
861 #endif // BOOST_NO_WREGEX
862
863
864 } // namespace boost
865
866 #endif
867