• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright (c) 2004
4  * John Maddock
5  *
6  * Use, modification and distribution are subject to the
7  * Boost Software License, Version 1.0. (See accompanying file
8  * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9  *
10  */
11 
12  /*
13   *   LOCATION:    see http://www.boost.org for most recent version.
14   *   FILE:        c_regex_traits.cpp
15   *   VERSION:     see <boost/version.hpp>
16   *   DESCRIPTION: Implements out of line c_regex_traits<char> members
17   */
18 
19 
20 #define BOOST_REGEX_SOURCE
21 
22 #include <boost/config.hpp>
23 #include <boost/detail/workaround.hpp>
24 #include "internals.hpp"
25 
26 #if !BOOST_WORKAROUND(BOOST_BORLANDC, < 0x560)
27 
28 #include <boost/regex/v4/c_regex_traits.hpp>
29 #include <boost/regex/v4/primary_transform.hpp>
30 #include <boost/regex/v4/regex_traits_defaults.hpp>
31 
32 #ifdef BOOST_NO_STDC_NAMESPACE
33 namespace std{
34    using ::strxfrm; using ::isspace;
35    using ::ispunct; using ::isalpha;
36    using ::isalnum; using ::iscntrl;
37    using ::isprint; using ::isupper;
38    using ::islower; using ::isdigit;
39    using ::isxdigit; using ::strtol;
40 }
41 #endif
42 
43 #ifdef BOOST_HAS_ABI_HEADERS
44 #  include BOOST_ABI_PREFIX
45 #endif
46 
47 namespace boost{
48 
transform(const char * p1,const char * p2)49 c_regex_traits<char>::string_type BOOST_REGEX_CALL c_regex_traits<char>::transform(const char* p1, const char* p2)
50 {
51    std::string result(10, ' ');
52    std::size_t s = result.size();
53    std::size_t r;
54    std::string src(p1, p2);
55    while(s < (r = std::strxfrm(&*result.begin(), src.c_str(), s)))
56    {
57 #if defined(_CPPLIB_VER)
58       //
59       // A bug in VC11 and 12 causes the program to hang if we pass a null-string
60       // to std::strxfrm, but only for certain locales :-(
61       // Probably effects Intel and Clang or any compiler using the VC std library (Dinkumware).
62       //
63       if(r == INT_MAX)
64       {
65          result.erase();
66          result.insert(result.begin(), static_cast<char>(0));
67          return result;
68       }
69 #endif
70       result.append(r - s + 3, ' ');
71       s = result.size();
72    }
73    result.erase(r);
74    return result;
75 }
76 
transform_primary(const char * p1,const char * p2)77 c_regex_traits<char>::string_type BOOST_REGEX_CALL c_regex_traits<char>::transform_primary(const char* p1, const char* p2)
78 {
79    static char s_delim;
80    static const int s_collate_type = ::boost::BOOST_REGEX_DETAIL_NS::find_sort_syntax(static_cast<c_regex_traits<char>*>(0), &s_delim);
81    std::string result;
82    //
83    // What we do here depends upon the format of the sort key returned by
84    // sort key returned by this->transform:
85    //
86    switch(s_collate_type)
87    {
88    case ::boost::BOOST_REGEX_DETAIL_NS::sort_C:
89    case ::boost::BOOST_REGEX_DETAIL_NS::sort_unknown:
90       // the best we can do is translate to lower case, then get a regular sort key:
91       {
92          result.assign(p1, p2);
93          for(std::string::size_type i = 0; i < result.size(); ++i)
94             result[i] = static_cast<char>((std::tolower)(static_cast<unsigned char>(result[i])));
95          result = transform(&*result.begin(), &*result.begin() + result.size());
96          break;
97       }
98    case ::boost::BOOST_REGEX_DETAIL_NS::sort_fixed:
99       {
100          // get a regular sort key, and then truncate it:
101          result = transform(p1, p2);
102          result.erase(s_delim);
103          break;
104       }
105    case ::boost::BOOST_REGEX_DETAIL_NS::sort_delim:
106          // get a regular sort key, and then truncate everything after the delim:
107          result = transform(p1, p2);
108          if(result.size() && (result[0] == s_delim))
109             break;
110          std::size_t i;
111          for(i = 0; i < result.size(); ++i)
112          {
113             if(result[i] == s_delim)
114                break;
115          }
116          result.erase(i);
117          break;
118    }
119    if(result.empty())
120       result = std::string(1, char(0));
121    return result;
122 }
123 
lookup_classname(const char * p1,const char * p2)124 c_regex_traits<char>::char_class_type BOOST_REGEX_CALL c_regex_traits<char>::lookup_classname(const char* p1, const char* p2)
125 {
126    static const char_class_type masks[] =
127    {
128       0,
129       char_class_alnum,
130       char_class_alpha,
131       char_class_blank,
132       char_class_cntrl,
133       char_class_digit,
134       char_class_digit,
135       char_class_graph,
136       char_class_horizontal,
137       char_class_lower,
138       char_class_lower,
139       char_class_print,
140       char_class_punct,
141       char_class_space,
142       char_class_space,
143       char_class_upper,
144       char_class_unicode,
145       char_class_upper,
146       char_class_vertical,
147       char_class_alnum | char_class_word,
148       char_class_alnum | char_class_word,
149       char_class_xdigit,
150    };
151 
152    int idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2);
153    if(idx < 0)
154    {
155       std::string s(p1, p2);
156       for(std::string::size_type i = 0; i < s.size(); ++i)
157          s[i] = static_cast<char>((std::tolower)(static_cast<unsigned char>(s[i])));
158       idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(&*s.begin(), &*s.begin() + s.size());
159    }
160    BOOST_ASSERT(std::size_t(idx) + 1u < sizeof(masks) / sizeof(masks[0]));
161    return masks[idx+1];
162 }
163 
isctype(char c,char_class_type mask)164 bool BOOST_REGEX_CALL c_regex_traits<char>::isctype(char c, char_class_type mask)
165 {
166    return
167       ((mask & char_class_space) && (std::isspace)(static_cast<unsigned char>(c)))
168       || ((mask & char_class_print) && (std::isprint)(static_cast<unsigned char>(c)))
169       || ((mask & char_class_cntrl) && (std::iscntrl)(static_cast<unsigned char>(c)))
170       || ((mask & char_class_upper) && (std::isupper)(static_cast<unsigned char>(c)))
171       || ((mask & char_class_lower) && (std::islower)(static_cast<unsigned char>(c)))
172       || ((mask & char_class_alpha) && (std::isalpha)(static_cast<unsigned char>(c)))
173       || ((mask & char_class_digit) && (std::isdigit)(static_cast<unsigned char>(c)))
174       || ((mask & char_class_punct) && (std::ispunct)(static_cast<unsigned char>(c)))
175       || ((mask & char_class_xdigit) && (std::isxdigit)(static_cast<unsigned char>(c)))
176       || ((mask & char_class_blank) && (std::isspace)(static_cast<unsigned char>(c)) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c))
177       || ((mask & char_class_word) && (c == '_'))
178       || ((mask & char_class_vertical) && (::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) || (c == '\v')))
179       || ((mask & char_class_horizontal) && (std::isspace)(static_cast<unsigned char>(c)) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) && (c != '\v'));
180 }
181 
lookup_collatename(const char * p1,const char * p2)182 c_regex_traits<char>::string_type BOOST_REGEX_CALL c_regex_traits<char>::lookup_collatename(const char* p1, const char* p2)
183 {
184    std::string s(p1, p2);
185    s = ::boost::BOOST_REGEX_DETAIL_NS::lookup_default_collate_name(s);
186    if(s.empty() && (p2-p1 == 1))
187       s.append(1, *p1);
188    return s;
189 }
190 
value(char c,int radix)191 int BOOST_REGEX_CALL c_regex_traits<char>::value(char c, int radix)
192 {
193    char b[2] = { c, '\0', };
194    char* ep;
195    int result = std::strtol(b, &ep, radix);
196    if(ep == b)
197       return -1;
198    return result;
199 }
200 
201 }
202 #ifdef BOOST_HAS_ABI_HEADERS
203 #  include BOOST_ABI_SUFFIX
204 #endif
205 
206 #endif
207