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

« back to all changes in this revision

Viewing changes to boost/libs/regex/src/c_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 c_regex_traits<charT> traits class
 
21
  */
 
22
 
 
23
#define BOOST_REGEX_SOURCE
 
24
 
 
25
#include <boost/config.hpp>
 
26
 
 
27
# ifdef BOOST_MSVC
 
28
#  pragma warning(disable: 4702)
 
29
#  endif
 
30
 
 
31
#include <clocale>
 
32
#include <cstdio>
 
33
#include <list>
 
34
#include <cctype>
 
35
#include <cstdio>
 
36
#include <boost/cregex.hpp>
 
37
#include <boost/regex/regex_traits.hpp>
 
38
#include <boost/regex/v3/regex_synch.hpp>
 
39
#include <boost/regex/v3/regex_cstring.hpp>
 
40
#include <boost/scoped_array.hpp>
 
41
 
 
42
#include "primary_transform.hpp"
 
43
 
 
44
 
 
45
#if defined(BOOST_HAS_NL_TYPES_H)
 
46
#include <nl_types.h>
 
47
#endif
 
48
 
 
49
// Fixes a very strange bug in Comeau 4.2.45.2 that would otherwise result in
 
50
// an instantiation loop
 
51
#if defined(__COMO__) && __COMO_VERSION__ <= 4245
 
52
void c_regex_adopted_no_longer_needed_loop_shutter_upper() { }
 
53
#endif
 
54
 
 
55
namespace{
 
56
 
 
57
//
 
58
// helper function to get the locale name,
 
59
// works around possibly broken setlocale implementations:
 
60
//
 
61
const char* getlocale(int id)
 
62
{
 
63
   static const char* def = "Unknown";
 
64
   const char* pl = std::setlocale(id, 0);
 
65
   return pl ? pl : def;
 
66
}
 
67
 
 
68
//
 
69
// character classes:
 
70
//
 
71
boost::uint_fast32_t re_char_class_id[] = {
 
72
   boost::re_detail::c_traits_base::char_class_alnum,
 
73
   boost::re_detail::c_traits_base::char_class_alpha,
 
74
   boost::re_detail::c_traits_base::char_class_cntrl,
 
75
   boost::re_detail::c_traits_base::char_class_digit,
 
76
   boost::re_detail::c_traits_base::char_class_graph,
 
77
   boost::re_detail::c_traits_base::char_class_lower,
 
78
   boost::re_detail::c_traits_base::char_class_print,
 
79
   boost::re_detail::c_traits_base::char_class_punct,
 
80
   boost::re_detail::c_traits_base::char_class_space,
 
81
   boost::re_detail::c_traits_base::char_class_upper,
 
82
   boost::re_detail::c_traits_base::char_class_xdigit,
 
83
   boost::re_detail::c_traits_base::char_class_blank,
 
84
   boost::re_detail::c_traits_base::char_class_word,
 
85
   boost::re_detail::c_traits_base::char_class_unicode,
 
86
};
 
87
 
 
88
const char* re_char_class_names[] = {
 
89
"alnum",
 
90
"alpha",
 
91
"cntrl",
 
92
"digit",
 
93
"graph",
 
94
"lower",
 
95
"print",
 
96
"punct",
 
97
"space",
 
98
"upper",
 
99
"xdigit",
 
100
"blank",
 
101
"word",
 
102
"unicode",
 
103
};
 
104
 
 
105
std::string* re_cls_name;
 
106
std::string* pclasses;
 
107
unsigned int classes_count = 0;
 
108
const unsigned int re_classes_max = 14;
 
109
 
 
110
//
 
111
// collate names:
 
112
 
 
113
struct collate_name_t
 
114
{
 
115
   std::string name;
 
116
   std::string value;
 
117
   collate_name_t(const char* p1, const char* p2, const char* p3, const char* p4)
 
118
      : name(p1, p2), value(p3, p4) {}
 
119
};
 
120
 
 
121
std::string* re_coll_name;
 
122
std::list<collate_name_t>* pcoll_names;
 
123
unsigned int collate_count = 0;
 
124
 
 
125
//
 
126
// message handling:
 
127
#ifndef BOOST_RE_MESSAGE_BASE
 
128
#define BOOST_RE_MESSAGE_BASE 0
 
129
#endif
 
130
 
 
131
#if defined(BOOST_HAS_NL_TYPES_H)
 
132
nl_catd message_cat = (nl_catd)-1;
 
133
#endif
 
134
 
 
135
unsigned int message_count = 0;
 
136
std::string* mess_locale;
 
137
 
 
138
BOOST_REGEX_DECL char* re_custom_error_messages[] = {
 
139
   0,
 
140
   0,
 
141
   0,
 
142
   0,
 
143
   0,
 
144
   0,
 
145
   0,
 
146
   0,
 
147
   0,
 
148
   0,
 
149
   0,
 
150
   0,
 
151
   0,
 
152
   0,
 
153
   0,
 
154
   0,
 
155
   0,
 
156
   0,
 
157
   0,
 
158
   0,
 
159
   0,
 
160
   0,
 
161
   0,
 
162
};
 
163
 
 
164
#if !defined(LC_MESSAGES)
 
165
#define LC_MESSAGES LC_CTYPE
 
166
#endif
 
167
 
 
168
char re_zero;
 
169
char re_ten;
 
170
 
 
171
unsigned int entry_count = 0;
 
172
 
 
173
std::string* ctype_name;
 
174
std::string* collate_name;
 
175
enum syntax_map_size
 
176
{
 
177
   map_size = UCHAR_MAX + 1
 
178
};
 
179
 
 
180
std::size_t BOOST_REGEX_CALL _re_get_message(char* buf, std::size_t len, std::size_t id);
 
181
 
 
182
#ifndef BOOST_NO_WREGEX
 
183
 
 
184
BOOST_REGEX_DECL wchar_t re_zero_w;
 
185
BOOST_REGEX_DECL wchar_t re_ten_w;
 
186
 
 
187
unsigned int nlsw_count = 0;
 
188
std::string* wlocale_name = 0;
 
189
 
 
190
struct syntax_map_t
 
191
{
 
192
   wchar_t c;
 
193
   unsigned int type;
 
194
};
 
195
 
 
196
std::list<syntax_map_t>* syntax;
 
197
 
 
198
std::size_t BOOST_REGEX_CALL re_get_message(wchar_t* buf, std::size_t len, std::size_t id)
 
199
{
 
200
   std::size_t size = _re_get_message(static_cast<char*>(0), 0, id);
 
201
   if(len < size)
 
202
      return size;
 
203
   boost::scoped_array<char> cb(new char[size]);
 
204
   _re_get_message(cb.get(), size, id);
 
205
   size = boost::c_regex_traits<wchar_t>::strwiden(buf, len, cb.get());
 
206
   return size;
 
207
}
 
208
#endif
 
209
 
 
210
inline std::size_t BOOST_REGEX_CALL re_get_message(char* buf, std::size_t len, std::size_t id)
 
211
{
 
212
   return _re_get_message(buf, len, id);
 
213
}
 
214
 
 
215
void BOOST_REGEX_CALL re_init_classes()
 
216
{
 
217
   BOOST_RE_GUARD_STACK
 
218
   if(classes_count == 0)
 
219
   {
 
220
      re_cls_name = new std::string("xxxxxxxx");
 
221
#ifndef BOOST_NO_EXCEPTIONS
 
222
      try{
 
223
#endif
 
224
         pclasses = new std::string[re_classes_max];
 
225
         BOOST_REGEX_NOEH_ASSERT(pclasses)
 
226
#ifndef BOOST_NO_EXCEPTIONS
 
227
      }
 
228
      catch(...)
 
229
      {
 
230
         delete re_cls_name;
 
231
         throw;
 
232
      }
 
233
#endif
 
234
   }
 
235
   ++classes_count;
 
236
}
 
237
 
 
238
void BOOST_REGEX_CALL re_free_classes()
 
239
{
 
240
   BOOST_RE_GUARD_STACK
 
241
   if(--classes_count == 0)
 
242
   {
 
243
      delete re_cls_name;
 
244
      delete[] pclasses;
 
245
   }
 
246
}
 
247
 
 
248
void BOOST_REGEX_CALL re_update_classes()
 
249
{
 
250
   BOOST_RE_GUARD_STACK
 
251
   if(*re_cls_name != getlocale(LC_CTYPE))
 
252
   {
 
253
      *re_cls_name = getlocale(LC_CTYPE);
 
254
      char buf[256];
 
255
      unsigned int i;
 
256
      for(i = 0; i < re_classes_max; ++i)
 
257
      {
 
258
         re_get_message(buf, 256, i+300);
 
259
         pclasses[i] = buf;
 
260
      }
 
261
   }
 
262
}
 
263
 
 
264
void BOOST_REGEX_CALL re_init_collate()
 
265
{
 
266
   BOOST_RE_GUARD_STACK
 
267
   if(collate_count == 0)
 
268
   {
 
269
      re_coll_name = new std::string("xxxxxxxx");
 
270
#ifndef BOOST_NO_EXCEPTIONS
 
271
      try{
 
272
#endif
 
273
         pcoll_names = new std::list<collate_name_t>();
 
274
         BOOST_REGEX_NOEH_ASSERT(pcoll_names)
 
275
#ifndef BOOST_NO_EXCEPTIONS
 
276
      }
 
277
      catch(...)
 
278
      {
 
279
         delete re_coll_name;
 
280
         throw;
 
281
      }
 
282
#endif
 
283
   }
 
284
   ++collate_count;
 
285
}
 
286
 
 
287
void BOOST_REGEX_CALL re_free_collate()
 
288
{
 
289
   BOOST_RE_GUARD_STACK
 
290
   if(--collate_count == 0)
 
291
   {
 
292
      delete re_coll_name;
 
293
      delete pcoll_names;
 
294
   }
 
295
}
 
296
 
 
297
void BOOST_REGEX_CALL re_update_collate()
 
298
{
 
299
   BOOST_RE_GUARD_STACK
 
300
   if(*re_coll_name != getlocale(LC_COLLATE))
 
301
   {
 
302
      *re_coll_name = getlocale(LC_COLLATE);
 
303
      char buf[256];
 
304
      unsigned int i = 400;
 
305
      re_get_message(buf, 256, i);
 
306
      while(*buf)
 
307
      {
 
308
         char* p1, *p2, *p3, *p4;;
 
309
         p1 = buf;
 
310
         while(*p1 && std::isspace((unsigned char)*p1))++p1;
 
311
         p2 = p1;
 
312
         while(*p2 && !std::isspace((unsigned char)*p2))++p2;
 
313
         p3 = p2;
 
314
         while(*p3 && std::isspace((unsigned char)*p3))++p3;
 
315
         p4 = p3;
 
316
         while(*p4 && !std::isspace((unsigned char)*p4))++p4;
 
317
         pcoll_names->push_back(collate_name_t(p1, p2, p3, p4));
 
318
         ++i;
 
319
         re_get_message(buf, 256, i);
 
320
      }
 
321
   }
 
322
}
 
323
 
 
324
std::size_t BOOST_REGEX_CALL _re_get_message(char* buf, std::size_t len, std::size_t id)
 
325
{
 
326
   BOOST_RE_GUARD_STACK
 
327
   // get the customised message if any:
 
328
   #if defined(BOOST_HAS_NL_TYPES_H)
 
329
   if(message_cat != (nl_catd)-1)
 
330
   {
 
331
      const char* m = catgets(message_cat, 0, id, 0);
 
332
      if(m)
 
333
      {
 
334
         std::size_t size = std::strlen(m) + 1;
 
335
         if(size > len)
 
336
            return size;
 
337
         std::strcpy(buf, m);
 
338
         return size;
 
339
      }
 
340
   }
 
341
   #endif
 
342
 
 
343
   //
 
344
   // now get the default message if any:
 
345
   return boost::re_detail::re_get_default_message(buf, len, id);
 
346
}
 
347
 
 
348
void BOOST_REGEX_CALL re_message_init()
 
349
{
 
350
   BOOST_RE_GUARD_STACK
 
351
   if(message_count == 0)
 
352
   {
 
353
      mess_locale = new std::string("xxxxxxxxxxxxxxxx");
 
354
   }
 
355
   ++message_count;
 
356
}
 
357
 
 
358
void BOOST_REGEX_CALL re_message_update()
 
359
{
 
360
   BOOST_RE_GUARD_STACK
 
361
   //
 
362
   // called whenever the global locale changes:
 
363
   //
 
364
   std::string l(getlocale(LC_MESSAGES));
 
365
   if(*mess_locale != l)
 
366
   {
 
367
      *mess_locale = l;
 
368
#if defined(BOOST_HAS_NL_TYPES_H)
 
369
      if(message_cat != (nl_catd)-1)
 
370
      {
 
371
         catclose(message_cat);
 
372
         message_cat = (nl_catd)-1;
 
373
      }
 
374
      if(*boost::re_detail::c_traits_base::get_catalogue())
 
375
      {
 
376
         message_cat = catopen(boost::re_detail::c_traits_base::get_catalogue(), 0);
 
377
#ifndef BOOST_NO_EXCEPTIONS
 
378
         if(message_cat == (nl_catd)-1)
 
379
         {
 
380
            std::string m("Unable to open message catalog: ");
 
381
            throw std::runtime_error(m + boost::re_detail::c_traits_base::get_catalogue());
 
382
         }
 
383
#else
 
384
         BOOST_REGEX_NOEH_ASSERT(message_cat != (nl_catd)-1);
 
385
#endif
 
386
      }
 
387
#endif
 
388
      for(int i = 0; i < boost::REG_E_UNKNOWN; ++i)
 
389
      {
 
390
         if(re_custom_error_messages[i])
 
391
         {
 
392
            boost::re_detail::re_strfree(re_custom_error_messages[i]);
 
393
            re_custom_error_messages[i] = 0;
 
394
         }
 
395
      }
 
396
   }
 
397
}
 
398
 
 
399
void BOOST_REGEX_CALL re_message_free()
 
400
{
 
401
   BOOST_RE_GUARD_STACK
 
402
   --message_count;
 
403
   if(message_count == 0)
 
404
   {
 
405
#if defined(BOOST_HAS_NL_TYPES_H)
 
406
      if(message_cat != (nl_catd)-1)
 
407
         catclose(message_cat);
 
408
#endif
 
409
      delete mess_locale;
 
410
      for(int i = 0; i < boost::REG_E_UNKNOWN; ++i)
 
411
      {
 
412
         if(re_custom_error_messages[i])
 
413
         {
 
414
            boost::re_detail::re_strfree(re_custom_error_messages[i]);
 
415
            re_custom_error_messages[i] = 0;
 
416
         }
 
417
      }
 
418
   }
 
419
}
 
420
 
 
421
 
 
422
const char* BOOST_REGEX_CALL re_get_error_str(unsigned int id)
 
423
{
 
424
   BOOST_RE_GUARD_STACK
 
425
#ifdef BOOST_HAS_THREADS
 
426
   boost::re_detail::cs_guard g(*boost::re_detail::p_re_lock);
 
427
#endif
 
428
   if(re_custom_error_messages[id] == 0)
 
429
   {
 
430
      char buf[256];
 
431
      _re_get_message(buf, 256, id + 200);
 
432
      if(*buf)
 
433
      {
 
434
         re_custom_error_messages[id] = boost::re_detail::re_strdup(buf);
 
435
         return re_custom_error_messages[id];
 
436
      }
 
437
      return boost::re_detail::re_default_error_messages[id];
 
438
   }
 
439
   return re_custom_error_messages[id];
 
440
}
 
441
 
 
442
} // namespace
 
443
 
 
444
namespace boost{
 
445
namespace re_detail{
 
446
 
 
447
char c_traits_base::regex_message_catalogue[BOOST_REGEX_MAX_PATH] = {0};
 
448
 
 
449
std::string BOOST_REGEX_CALL c_traits_base::error_string(unsigned id)
 
450
{
 
451
   return re_get_error_str(id);
 
452
}
 
453
 
 
454
void BOOST_REGEX_CALL c_traits_base::do_update_collate()
 
455
{
 
456
   BOOST_RE_GUARD_STACK
 
457
   re_update_collate();
 
458
   std::string s;
 
459
   const char* p = "zero";
 
460
   if(c_regex_traits<char>::lookup_collatename(s, p, p+4))
 
461
   {
 
462
      jm_assert(s.size() == 1);
 
463
      re_zero = *s.c_str();
 
464
   }
 
465
   else
 
466
      re_zero = '0';
 
467
 
 
468
   p = "ten";
 
469
   if(c_regex_traits<char>::lookup_collatename(s, p, p+3))
 
470
   {
 
471
      jm_assert(s.size() == 1);
 
472
      re_ten = *s.c_str();
 
473
   }
 
474
   else
 
475
      re_ten = 'a';
 
476
}
 
477
 
 
478
void BOOST_REGEX_CALL c_traits_base::do_update_ctype()
 
479
{
 
480
   BOOST_RE_GUARD_STACK
 
481
   // start by updating the syntax map:
 
482
   unsigned int i;
 
483
   char buf[map_size+2];
 
484
   std::memset(syntax_map, syntax_char, map_size);
 
485
   for(i = 1; i < syntax_max; ++i)
 
486
   {
 
487
      char* ptr = buf;
 
488
      re_get_message(static_cast<char*>(buf), map_size, i+100);
 
489
      for(; *ptr; ++ptr)
 
490
      {
 
491
         syntax_map[(unsigned char)*ptr] = (unsigned char)i;
 
492
      }
 
493
   }
 
494
 
 
495
   // now update the character class map,
 
496
   // and lower case map:
 
497
   std::memset(class_map, 0, map_size);
 
498
   for(i = 0; i < map_size; ++i)
 
499
   {
 
500
      if(std::isalpha(i))
 
501
         class_map[i] |= char_class_alpha;
 
502
      if(std::iscntrl(i))
 
503
         class_map[i] |= char_class_cntrl;
 
504
      if(std::isdigit(i))
 
505
         class_map[i] |= char_class_digit;
 
506
      if(std::islower(i))
 
507
         class_map[i] |= char_class_lower;
 
508
      if(std::isupper(i))
 
509
         class_map[i] |= char_class_upper;
 
510
      if(std::ispunct(i))
 
511
         class_map[i] |= char_class_punct;
 
512
      if(std::isspace(i))
 
513
         class_map[i] |= char_class_space;
 
514
      if(std::isxdigit(i))
 
515
         class_map[i] |= char_class_xdigit;
 
516
   }
 
517
   class_map[(unsigned char)'_'] |= char_class_underscore;
 
518
   class_map[(unsigned char)' '] |= char_class_blank;
 
519
   class_map[(unsigned char)'\t'] |= char_class_blank;
 
520
   for(i = 0; i < map_size; ++i)
 
521
   {
 
522
      lower_case_map[i] = (char)std::tolower(i);
 
523
   }
 
524
   re_update_classes();
 
525
}
 
526
 
 
527
boost::uint_fast32_t BOOST_REGEX_CALL c_traits_base::do_lookup_class(const char* p)
 
528
{
 
529
   BOOST_RE_GUARD_STACK
 
530
   unsigned int i;
 
531
   for(i = 0; i < re_classes_max; ++i)
 
532
   {
 
533
      if(pclasses[i] == p)
 
534
      {
 
535
         return re_char_class_id[i];
 
536
      }
 
537
   }
 
538
   for(i = 0; i < re_classes_max; ++i)
 
539
   {
 
540
      if(std::strcmp(re_char_class_names[i], p) == 0)
 
541
      {
 
542
         return re_char_class_id[i];
 
543
      }
 
544
   }
 
545
   return 0;
 
546
}
 
547
 
 
548
bool BOOST_REGEX_CALL c_traits_base::do_lookup_collate(std::string& buf, const char* p)
 
549
{
 
550
   BOOST_RE_GUARD_STACK
 
551
   std::list<collate_name_t>::iterator first, last;
 
552
   first = pcoll_names->begin();
 
553
   last = pcoll_names->end();
 
554
   while(first != last)
 
555
   {
 
556
      if((*first).name == p)
 
557
      {
 
558
         buf = (*first).value;
 
559
         return true;
 
560
      }
 
561
      ++first;
 
562
   }
 
563
 
 
564
   bool result = re_detail::re_lookup_def_collate_name(buf, p);
 
565
   if((result == 0) && (std::strlen(p) == 1))
 
566
   {
 
567
      result = true;
 
568
      buf = *p;
 
569
   }
 
570
   return result;
 
571
}
 
572
 
 
573
std::string BOOST_REGEX_CALL c_traits_base::set_message_catalogue(const std::string& l)
 
574
{
 
575
   if(sizeof(regex_message_catalogue) <= l.size())
 
576
      return l;
 
577
   std::string old(regex_message_catalogue);
 
578
   std::strcpy(regex_message_catalogue, l.c_str());
 
579
   return old;
 
580
}
 
581
 
 
582
unsigned char c_traits_base::syntax_map[map_size];
 
583
unsigned short c_traits_base::class_map[map_size];
 
584
char c_traits_base::lower_case_map[map_size];
 
585
 
 
586
} // namespace re_detail
 
587
 
 
588
#ifndef BOOST_NO_WREGEX
 
589
bool BOOST_REGEX_CALL c_regex_traits<wchar_t>::lookup_collatename(std::basic_string<wchar_t>& out, const wchar_t* first, const wchar_t* last)
 
590
{
 
591
   BOOST_RE_GUARD_STACK
 
592
   std::basic_string<wchar_t> s(first, last);
 
593
   std::size_t len = strnarrow(static_cast<char*>(0), 0, s.c_str());
 
594
   scoped_array<char> buf(new char[len]);
 
595
   strnarrow(buf.get(), len, s.c_str());
 
596
   std::string t_out;
 
597
   bool result = base_type::do_lookup_collate(t_out, buf.get());
 
598
   if(t_out.size() == 0) result = false;
 
599
   if(result)
 
600
   {
 
601
      if(t_out[0])
 
602
      {
 
603
         len = strwiden(static_cast<wchar_t*>(0), 0, t_out.c_str());
 
604
         scoped_array<wchar_t> wb(new wchar_t[len]);
 
605
         strwiden(wb.get(), len, t_out.c_str());
 
606
         out = wb.get();
 
607
      }
 
608
      else
 
609
         out.append(1, (wchar_t)0);
 
610
   }
 
611
   return result;
 
612
}
 
613
#endif
 
614
 
 
615
c_regex_traits<char> c_regex_traits<char>::i;
 
616
 
 
617
void BOOST_REGEX_CALL c_regex_traits<char>::init()
 
618
{
 
619
   BOOST_RE_GUARD_STACK
 
620
#ifdef BOOST_HAS_THREADS
 
621
   re_detail::re_init_threads();
 
622
   re_detail::cs_guard g(*re_detail::p_re_lock);
 
623
#endif
 
624
   // just keep track of entry_count
 
625
   if(entry_count == 0)
 
626
   {
 
627
      ctype_name = new std::string("xxxxxxxxxxxxxxxx");
 
628
#ifndef BOOST_NO_EXCEPTIONS
 
629
      try{
 
630
#endif
 
631
         collate_name = new std::string("xxxxxxxxxxxxxxxx");
 
632
         BOOST_REGEX_NOEH_ASSERT(collate_name)
 
633
#ifndef BOOST_NO_EXCEPTIONS
 
634
      }
 
635
      catch(...)
 
636
      {
 
637
         delete ctype_name;
 
638
         throw;
 
639
      }
 
640
#endif
 
641
   }
 
642
   re_message_init();
 
643
   re_init_classes();
 
644
   re_init_collate();
 
645
   ++entry_count;
 
646
}
 
647
 
 
648
void BOOST_REGEX_CALL c_regex_traits<char>::update()
 
649
{
 
650
   BOOST_RE_GUARD_STACK
 
651
   #ifdef BOOST_HAS_THREADS
 
652
   re_detail::cs_guard g(*re_detail::p_re_lock);
 
653
   #endif
 
654
   re_message_update();
 
655
   if(*collate_name != getlocale(LC_COLLATE))
 
656
   {
 
657
      do_update_collate();
 
658
      *collate_name = getlocale(LC_COLLATE);
 
659
   }
 
660
   if(*ctype_name != getlocale(LC_CTYPE))
 
661
   {
 
662
      do_update_ctype();
 
663
      *ctype_name = getlocale(LC_CTYPE);
 
664
   }
 
665
   sort_type = re_detail::find_sort_syntax(&i, &sort_delim);
 
666
}
 
667
 
 
668
void BOOST_REGEX_CALL c_regex_traits<char>::m_free()
 
669
{
 
670
   BOOST_RE_GUARD_STACK
 
671
   #ifdef BOOST_HAS_THREADS
 
672
   re_detail::cs_guard g(*re_detail::p_re_lock);
 
673
   #endif
 
674
   re_message_free();
 
675
   re_free_classes();
 
676
   re_free_collate();
 
677
   --entry_count;
 
678
   // add reference to static member here to ensure
 
679
   // that the linker includes it in the .exe:
 
680
   if((entry_count == 0) && (0 != &c_regex_traits<char>::i))
 
681
   {
 
682
      delete ctype_name;
 
683
      delete collate_name;
 
684
   }
 
685
#ifdef BOOST_HAS_THREADS
 
686
   g.acquire(false);
 
687
   re_detail::re_free_threads();
 
688
#endif
 
689
}
 
690
 
 
691
void BOOST_REGEX_CALL c_regex_traits<char>::transform(std::string& out, const std::string& in)
 
692
{
 
693
   BOOST_RE_GUARD_STACK
 
694
   std::size_t n = std::strxfrm(0, in.c_str(), 0);
 
695
   if(n == (std::size_t)(-1))
 
696
   {
 
697
      out = in;
 
698
      return;
 
699
   }
 
700
   scoped_array<char> buf(new char[n+1]);
 
701
   n = std::strxfrm(buf.get(), in.c_str(), n+1);
 
702
   if(n == (std::size_t)(-1))
 
703
   {
 
704
      out = in;
 
705
      return;
 
706
   }
 
707
   out = buf.get();
 
708
}
 
709
 
 
710
void BOOST_REGEX_CALL c_regex_traits<char>::transform_primary(std::string& out, const std::string& in)
 
711
{
 
712
   transform(out, in);
 
713
   switch(sort_type)
 
714
   {
 
715
   case re_detail::sort_C:
 
716
   case re_detail::sort_unknown:
 
717
      break;
 
718
   case re_detail::sort_fixed:
 
719
      out.erase((int)sort_delim);
 
720
      break;
 
721
   case re_detail::sort_delim:
 
722
      for(unsigned int i = 0; i < out.size(); ++i)
 
723
      {
 
724
         if((out[i] == sort_delim) && (i+1 < out.size()))
 
725
         {
 
726
            out.erase(i+1);
 
727
            break;
 
728
         }
 
729
      }
 
730
   }
 
731
}
 
732
 
 
733
unsigned c_regex_traits<char>::sort_type;
 
734
char c_regex_traits<char>::sort_delim;
 
735
 
 
736
 
 
737
int BOOST_REGEX_CALL c_regex_traits<char>::toi(char c)
 
738
{
 
739
   if(is_class(c, char_class_digit))
 
740
      return c - re_zero;
 
741
   if(is_class(c, char_class_xdigit))
 
742
      return 10 + translate(c, true) - translate(re_ten, true);
 
743
   return -1; // error!!
 
744
}
 
745
 
 
746
int BOOST_REGEX_CALL c_regex_traits<char>::toi(const char*& first, const char* last, int radix)
 
747
{
 
748
   unsigned int maxval;
 
749
   if(radix < 0)
 
750
   {
 
751
      // if radix is less than zero, then restrict
 
752
      // return value to charT. NB assumes sizeof(charT) <= sizeof(int)
 
753
      radix *= -1;
 
754
      maxval = 1u << (sizeof(*first) * CHAR_BIT - 1);
 
755
      maxval /= radix;
 
756
      maxval *= 2;
 
757
      maxval -= 1;
 
758
   }
 
759
   else
 
760
   {
 
761
      maxval = (unsigned int)-1;
 
762
      maxval /= radix;
 
763
   }
 
764
 
 
765
   unsigned int result = 0;
 
766
   unsigned int type = (radix > 10) ? char_class_xdigit : char_class_digit;
 
767
   while((first != last) && is_class(*first, type) && (result <= maxval))
 
768
   {
 
769
      result *= radix;
 
770
      result += toi(*first);
 
771
      ++first;
 
772
   }
 
773
   return result;
 
774
}
 
775
 
 
776
#ifndef BOOST_NO_WREGEX
 
777
 
 
778
unsigned int BOOST_REGEX_CALL c_regex_traits<wchar_t>::syntax_type(size_type c)
 
779
{
 
780
   BOOST_RE_GUARD_STACK
 
781
   std::list<syntax_map_t>::const_iterator first, last;
 
782
   first = syntax->begin();
 
783
   last = syntax->end();
 
784
   while(first != last)
 
785
   {
 
786
      if((uchar_type)(*first).c == c)
 
787
         return (*first).type;
 
788
      ++first;
 
789
   }
 
790
   return 0;
 
791
}
 
792
 
 
793
void BOOST_REGEX_CALL c_regex_traits<wchar_t>::init()
 
794
{
 
795
   BOOST_RE_GUARD_STACK
 
796
   re_detail::re_init_threads();
 
797
#ifdef BOOST_HAS_THREADS
 
798
   re_detail::cs_guard g(*re_detail::p_re_lock);
 
799
#endif
 
800
   re_message_init();
 
801
   re_init_classes();
 
802
   re_init_collate();
 
803
   if(nlsw_count == 0)
 
804
   {
 
805
      wlocale_name = new std::string("xxxxxxxxxxxxxxxx");
 
806
#ifndef BOOST_NO_EXCEPTIONS
 
807
      try{
 
808
#endif
 
809
         syntax = new std::list<syntax_map_t>();
 
810
         BOOST_REGEX_NOEH_ASSERT(syntax)
 
811
#ifndef BOOST_NO_EXCEPTIONS
 
812
      }
 
813
      catch(...)
 
814
      {
 
815
         delete wlocale_name;
 
816
         throw;
 
817
      }
 
818
#endif
 
819
   }
 
820
   ++nlsw_count;
 
821
}
 
822
 
 
823
bool BOOST_REGEX_CALL c_regex_traits<wchar_t>::do_lookup_collate(std::basic_string<wchar_t>& out, const wchar_t* first, const wchar_t* last)
 
824
{
 
825
   BOOST_RE_GUARD_STACK
 
826
   std::basic_string<wchar_t> s(first, last);
 
827
   std::size_t len = strnarrow(static_cast<char*>(0), 0, s.c_str());
 
828
   scoped_array<char> buf(new char[len]);
 
829
   strnarrow(buf.get(), len, s.c_str());
 
830
   std::string t_out;
 
831
   bool result = base_type::do_lookup_collate(t_out, buf.get());
 
832
   if(result)
 
833
   {
 
834
      len = strwiden(static_cast<wchar_t*>(0), 0, t_out.c_str());
 
835
      scoped_array<wchar_t> wb(new wchar_t[len]);
 
836
      strwiden(wb.get(), len, t_out.c_str());
 
837
      out = wb.get();
 
838
   }
 
839
   return result;
 
840
}
 
841
 
 
842
 
 
843
void BOOST_REGEX_CALL c_regex_traits<wchar_t>::update()
 
844
{
 
845
   BOOST_RE_GUARD_STACK
 
846
#ifdef BOOST_HAS_THREADS
 
847
   re_detail::cs_guard g(*re_detail::p_re_lock);
 
848
#endif
 
849
   re_message_update();
 
850
   re_update_classes();
 
851
   re_update_collate();
 
852
   std::string l(getlocale(LC_CTYPE));
 
853
   if(*wlocale_name != l)
 
854
   {
 
855
      *wlocale_name = l;
 
856
      std::basic_string<wchar_t> s;
 
857
      const wchar_t* p = L"zero";
 
858
      if(do_lookup_collate(s, p, p+4))
 
859
      {
 
860
         jm_assert(s.size() == 1);
 
861
         re_zero_w = *s.c_str();
 
862
      }
 
863
      else
 
864
         re_zero_w = L'0';
 
865
 
 
866
      p = L"ten";
 
867
      if(do_lookup_collate(s, p, p+3))
 
868
      {
 
869
         jm_assert(s.size() == 1);
 
870
         re_ten_w = *s.c_str();
 
871
      }
 
872
      else
 
873
         re_ten_w = L'a';
 
874
 
 
875
      unsigned int i;
 
876
      wchar_t buf[256];
 
877
      syntax_map_t sm;
 
878
      syntax->clear();
 
879
      for(i = 1; i < syntax_max; ++i)
 
880
      {
 
881
         wchar_t* ptr = buf;
 
882
         re_get_message(static_cast<wchar_t*>(buf), 256, i+100);
 
883
         for(; *ptr; ++ptr)
 
884
         {
 
885
            sm.c = *ptr;
 
886
            sm.type = i;
 
887
            syntax->push_back(sm);
 
888
         }
 
889
      }
 
890
      sort_type = re_detail::find_sort_syntax(&init_, &sort_delim);
 
891
   }
 
892
}
 
893
 
 
894
void BOOST_REGEX_CALL c_regex_traits<wchar_t>::m_free()
 
895
{
 
896
   BOOST_RE_GUARD_STACK
 
897
#ifdef BOOST_HAS_THREADS
 
898
   re_detail::cs_guard g(*re_detail::p_re_lock);
 
899
#endif
 
900
   --nlsw_count;
 
901
   re_message_free();
 
902
   re_free_classes();
 
903
   re_free_collate();
 
904
   // add reference to static member here to ensure
 
905
   // that the linker includes it in the .exe:
 
906
   if((nlsw_count == 0) && (0 != &c_regex_traits<wchar_t>::init_))
 
907
   {
 
908
      // cleanup:
 
909
      delete wlocale_name;
 
910
      delete syntax;
 
911
   }
 
912
#ifdef BOOST_HAS_THREADS
 
913
   g.acquire(false);
 
914
   re_detail::re_free_threads();
 
915
#endif
 
916
}
 
917
 
 
918
bool BOOST_REGEX_CALL c_regex_traits<wchar_t>::do_iswclass(wchar_t c, boost::uint_fast32_t f)
 
919
{
 
920
   BOOST_RE_GUARD_STACK
 
921
   if((c & ~0xFF) == 0)
 
922
      return BOOST_REGEX_MAKE_BOOL(re_detail::wide_unicode_classes[(uchar_type)c] & f);
 
923
   if((f & char_class_alpha) && std::iswalpha(c))
 
924
      return true;
 
925
   if((f & char_class_cntrl) && std::iswcntrl(c))
 
926
      return true;
 
927
   if((f & char_class_digit) && std::iswdigit(c))
 
928
      return true;
 
929
   if((f & char_class_lower) && std::iswlower(c))
 
930
      return true;
 
931
   if((f & char_class_punct) && std::iswpunct(c))
 
932
      return true;
 
933
   if((f & char_class_space) && std::iswspace(c))
 
934
      return true;
 
935
   if((f & char_class_upper) && std::iswupper(c))
 
936
      return true;
 
937
   if((f & char_class_xdigit) && std::iswxdigit(c))
 
938
      return true;
 
939
   if(f & char_class_unicode)
 
940
      return true;
 
941
   return false;
 
942
}
 
943
 
 
944
void BOOST_REGEX_CALL c_regex_traits<wchar_t>::transform(std::basic_string<wchar_t>& out, const std::basic_string<wchar_t>& in)
 
945
{
 
946
   BOOST_RE_GUARD_STACK
 
947
#ifndef BOOST_MSVC
 
948
   std::size_t n = std::wcsxfrm(0, in.c_str(), 0);
 
949
#else
 
950
   // broken wcsxfrm under VC6 doesn't check size of
 
951
   // output buffer, we have no choice but to guess!
 
952
   std::size_t n = 100 * in.size();
 
953
#endif
 
954
   if((n == (std::size_t)(-1)) || (n == 0))
 
955
   {
 
956
      out = in;
 
957
      return;
 
958
   }
 
959
   scoped_array<wchar_t> buf(new wchar_t[n+1]);
 
960
   n = std::wcsxfrm(buf.get(), in.c_str(), n+1);
 
961
   if(n == (std::size_t)(-1))
 
962
   {
 
963
      out = in;
 
964
      return;
 
965
   }
 
966
   out = buf.get();
 
967
}
 
968
 
 
969
void BOOST_REGEX_CALL c_regex_traits<wchar_t>::transform_primary(std::basic_string<wchar_t>& out, const std::basic_string<wchar_t>& in)
 
970
{
 
971
   transform(out, in);
 
972
   switch(sort_type)
 
973
   {
 
974
   case re_detail::sort_C:
 
975
   case re_detail::sort_unknown:
 
976
      break;
 
977
   case re_detail::sort_fixed:
 
978
      if((unsigned)sort_delim < out.size())
 
979
         out.erase((int)sort_delim);
 
980
      break;
 
981
   case re_detail::sort_delim:
 
982
      for(unsigned int i = 0; i < out.size(); ++i)
 
983
      {
 
984
         if((out[i] == sort_delim) && (i+1 < out.size()))
 
985
         {
 
986
            out.erase(i+1);
 
987
            break;
 
988
         }
 
989
      }
 
990
   }
 
991
}
 
992
 
 
993
unsigned c_regex_traits<wchar_t>::sort_type;
 
994
wchar_t c_regex_traits<wchar_t>::sort_delim;
 
995
 
 
996
 
 
997
int BOOST_REGEX_CALL c_regex_traits<wchar_t>::toi(wchar_t c)
 
998
{
 
999
   if(is_class(c, char_class_digit))
 
1000
      return c - re_zero_w;
 
1001
   if(is_class(c, char_class_xdigit))
 
1002
      return 10 + translate(c, true) - translate(re_ten_w, true);
 
1003
   return -1; // error!!
 
1004
}
 
1005
 
 
1006
int BOOST_REGEX_CALL c_regex_traits<wchar_t>::toi(const wchar_t*& first, const wchar_t* last, int radix)
 
1007
{
 
1008
   unsigned int maxval;
 
1009
   if(radix < 0)
 
1010
   {
 
1011
      // if radix is less than zero, then restrict
 
1012
      // return value to charT. NB assumes sizeof(charT) <= sizeof(int)
 
1013
      radix *= -1;
 
1014
      maxval = 1u << (sizeof(*first) * CHAR_BIT - 1);
 
1015
      maxval /= radix;
 
1016
      maxval *= 2;
 
1017
      maxval -= 1;
 
1018
   }
 
1019
   else
 
1020
   {
 
1021
      maxval = (unsigned int)-1;
 
1022
      maxval /= radix;
 
1023
   }
 
1024
 
 
1025
   unsigned int result = 0;
 
1026
   unsigned int type = (radix > 10) ? char_class_xdigit : char_class_digit;
 
1027
   while((first != last) && is_class(*first, type) && (result <= maxval))
 
1028
   {
 
1029
      result *= radix;
 
1030
      result += toi(*first);
 
1031
      ++first;
 
1032
   }
 
1033
   return result;
 
1034
}
 
1035
 
 
1036
boost::uint_fast32_t BOOST_REGEX_CALL c_regex_traits<wchar_t>::lookup_classname(const wchar_t* first, const wchar_t* last)
 
1037
{
 
1038
   std::basic_string<wchar_t> s(first, last);
 
1039
   std::size_t len = strnarrow(static_cast<char*>(0), 0, s.c_str());
 
1040
   scoped_array<char> buf(new char[len]);
 
1041
   strnarrow(buf.get(), len, s.c_str());
 
1042
   boost::uint_fast32_t result =  do_lookup_class(buf.get());
 
1043
   return result;
 
1044
}
 
1045
 
 
1046
c_regex_traits<wchar_t> c_regex_traits<wchar_t>::init_;
 
1047
 
 
1048
std::size_t BOOST_REGEX_CALL c_regex_traits<wchar_t>::strnarrow(char *s1, std::size_t len, const wchar_t *s2)
 
1049
{
 
1050
   BOOST_RE_GUARD_STACK
 
1051
   std::size_t size = std::wcslen(s2) + 1;
 
1052
   if(size > len)
 
1053
      return size;
 
1054
   return std::wcstombs(s1, s2, len);
 
1055
}
 
1056
 
 
1057
std::size_t BOOST_REGEX_CALL c_regex_traits<wchar_t>::strwiden(wchar_t *s1, std::size_t len, const char *s2)
 
1058
{
 
1059
   BOOST_RE_GUARD_STACK
 
1060
   std::size_t size = std::strlen(s2) + 1;
 
1061
   if(size > len)
 
1062
      return size;
 
1063
   size = std::mbstowcs(s1, s2, len);
 
1064
   s1[size] = 0;
 
1065
   return size + 1;
 
1066
}
 
1067
 
 
1068
#endif // BOOST_NO_WREGEX
 
1069
 
 
1070
} // namespace boost
 
1071
 
 
1072
 
 
1073