~ubuntu-branches/ubuntu/warty/aqsis/warty

« back to all changes in this revision

Viewing changes to boost/libs/regex/src/cpp_regex_traits.cpp

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2004-08-24 07:25:04 UTC
  • Revision ID: james.westby@ubuntu.com-20040824072504-zf993vnevvisdsvb
Tags: upstream-0.9.1
ImportĀ upstreamĀ versionĀ 0.9.1

Show diffs side-by-side

added added

removed removed

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