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