1 /*
2  *
3  * Copyright (c) 1998-2002
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:        wide_posix_api.cpp
15   *   VERSION:     see <boost/version.hpp>
16   *   DESCRIPTION: Implements the wide character POSIX API wrappers.
17   */
18 
19 #define BOOST_REGEX_SOURCE
20 
21 #include <boost/regex/config.hpp>
22 
23 #ifndef BOOST_NO_WREGEX
24 
25 #include <boost/regex.hpp>
26 #include <boost/cregex.hpp>
27 
28 #include <cwchar>
29 #include <cstring>
30 #include <cstdio>
31 
32 #ifdef BOOST_INTEL
33 #pragma warning(disable:981)
34 #endif
35 
36 #if defined(BOOST_NO_STDC_NAMESPACE) || defined(__NetBSD__)
37 namespace std{
38 #  ifndef BOOST_NO_SWPRINTF
39       using ::swprintf;
40 #  endif
41 }
42 #endif
43 
44 
45 namespace boost{
46 
47 namespace {
48 
49 unsigned int wmagic_value = 28631;
50 
51 const wchar_t* wnames[] = {
52       L"REG_NOERROR",
53       L"REG_NOMATCH",
54       L"REG_BADPAT",
55       L"REG_ECOLLATE",
56       L"REG_ECTYPE",
57       L"REG_EESCAPE",
58       L"REG_ESUBREG",
59       L"REG_EBRACK",
60       L"REG_EPAREN",
61       L"REG_EBRACE",
62       L"REG_BADBR",
63       L"REG_ERANGE",
64       L"REG_ESPACE",
65       L"REG_BADRPT",
66       L"REG_EEND",
67       L"REG_ESIZE",
68       L"REG_ERPAREN",
69       L"REG_EMPTY",
70       L"REG_ECOMPLEXITY",
71       L"REG_ESTACK",
72       L"REG_E_PERL",
73       L"REG_E_UNKNOWN",
74 };
75 }
76 
77 typedef boost::basic_regex<wchar_t, c_regex_traits<wchar_t> > wc_regex_type;
78 
regcompW(regex_tW * expression,const wchar_t * ptr,int f)79 BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompW(regex_tW* expression, const wchar_t* ptr, int f)
80 {
81    if(expression->re_magic != wmagic_value)
82    {
83       expression->guts = 0;
84 #ifndef BOOST_NO_EXCEPTIONS
85       try{
86 #endif
87       expression->guts = new wc_regex_type();
88 #ifndef BOOST_NO_EXCEPTIONS
89       } catch(...)
90       {
91          return REG_ESPACE;
92       }
93 #else
94       if(0 == expression->guts)
95          return REG_E_MEMORY;
96 #endif
97    }
98    // set default flags:
99    boost::uint_fast32_t flags = (f & REG_PERLEX) ? 0 : ((f & REG_EXTENDED) ? wregex::extended : wregex::basic);
100    expression->eflags = (f & REG_NEWLINE) ? match_not_dot_newline : match_default;
101 
102    // and translate those that are actually set:
103    if(f & REG_NOCOLLATE)
104    {
105       flags |= wregex::nocollate;
106 #ifndef BOOST_REGEX_V3
107       flags &= ~wregex::collate;
108 #endif
109    }
110 
111    if(f & REG_NOSUB)
112    {
113       //expression->eflags |= match_any;
114       flags |= wregex::nosubs;
115    }
116 
117    if(f & REG_NOSPEC)
118       flags |= wregex::literal;
119    if(f & REG_ICASE)
120       flags |= wregex::icase;
121    if(f & REG_ESCAPE_IN_LISTS)
122       flags &= ~wregex::no_escape_in_lists;
123    if(f & REG_NEWLINE_ALT)
124       flags |= wregex::newline_alt;
125 
126    const wchar_t* p2;
127    if(f & REG_PEND)
128       p2 = expression->re_endp;
129    else p2 = ptr + std::wcslen(ptr);
130 
131    int result;
132 
133 #ifndef BOOST_NO_EXCEPTIONS
134    try{
135 #endif
136       expression->re_magic = wmagic_value;
137       static_cast<wc_regex_type*>(expression->guts)->set_expression(ptr, p2, flags);
138       expression->re_nsub = static_cast<wc_regex_type*>(expression->guts)->mark_count();
139       result = static_cast<wc_regex_type*>(expression->guts)->error_code();
140 #ifndef BOOST_NO_EXCEPTIONS
141    }
142    catch(const boost::regex_error& be)
143    {
144       result = be.code();
145    }
146    catch(...)
147    {
148       result = REG_E_UNKNOWN;
149    }
150 #endif
151    if(result)
152       regfreeW(expression);
153    return result;
154 
155 }
156 
regerrorW(int code,const regex_tW * e,wchar_t * buf,regsize_t buf_size)157 BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorW(int code, const regex_tW* e, wchar_t* buf, regsize_t buf_size)
158 {
159    std::size_t result = 0;
160    if(code & REG_ITOA)
161    {
162       code &= ~REG_ITOA;
163       if((code <= (int)REG_E_UNKNOWN) && (code >= 0))
164       {
165          result = std::wcslen(wnames[code]) + 1;
166          if(buf_size >= result)
167 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(_WIN32_WCE) && !defined(UNDER_CE)
168             ::wcscpy_s(buf, buf_size, wnames[code]);
169 #else
170             std::wcscpy(buf, wnames[code]);
171 #endif
172          return result;
173       }
174       return result;
175    }
176 #if !defined(BOOST_NO_SWPRINTF)
177    if(code == REG_ATOI)
178    {
179       wchar_t localbuf[5];
180       if(e == 0)
181          return 0;
182       for(int i = 0; i <= (int)REG_E_UNKNOWN; ++i)
183       {
184          if(std::wcscmp(e->re_endp, wnames[i]) == 0)
185          {
186 #if defined(_WIN32_WCE) && !defined(UNDER_CE)
187             (std::swprintf)(localbuf, L"%d", i);
188 #else
189             (std::swprintf)(localbuf, 5, L"%d", i);
190 #endif
191             if(std::wcslen(localbuf) < buf_size)
192 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(_WIN32_WCE) && !defined(UNDER_CE)
193                ::wcscpy_s(buf, buf_size, localbuf);
194 #else
195                std::wcscpy(buf, localbuf);
196 #endif
197             return std::wcslen(localbuf) + 1;
198          }
199       }
200 #if defined(_WIN32_WCE) && !defined(UNDER_CE)
201       (std::swprintf)(localbuf, L"%d", 0);
202 #else
203       (std::swprintf)(localbuf, 5, L"%d", 0);
204 #endif
205       if(std::wcslen(localbuf) < buf_size)
206 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(_WIN32_WCE) && !defined(UNDER_CE)
207          ::wcscpy_s(buf, buf_size, localbuf);
208 #else
209          std::wcscpy(buf, localbuf);
210 #endif
211       return std::wcslen(localbuf) + 1;
212    }
213 #endif
214    if(code <= (int)REG_E_UNKNOWN)
215    {
216       std::string p;
217       if((e) && (e->re_magic == wmagic_value))
218          p = static_cast<wc_regex_type*>(e->guts)->get_traits().error_string(static_cast< ::boost::regex_constants::error_type>(code));
219       else
220       {
221          p = re_detail::get_default_error_string(static_cast< ::boost::regex_constants::error_type>(code));
222       }
223       std::size_t len = p.size();
224       if(len < buf_size)
225       {
226          re_detail::copy(p.c_str(), p.c_str() + p.size() + 1, buf);
227       }
228       return len + 1;
229    }
230    if(buf_size)
231       *buf = 0;
232    return 0;
233 }
234 
regexecW(const regex_tW * expression,const wchar_t * buf,regsize_t n,regmatch_t * array,int eflags)235 BOOST_REGEX_DECL int BOOST_REGEX_CCALL regexecW(const regex_tW* expression, const wchar_t* buf, regsize_t n, regmatch_t* array, int eflags)
236 {
237 #ifdef BOOST_MSVC
238 #pragma warning(push)
239 #pragma warning(disable:4267)
240 #endif
241    bool result = false;
242    match_flag_type flags = match_default | expression->eflags;
243    const wchar_t* end;
244    const wchar_t* start;
245    wcmatch m;
246 
247    if(eflags & REG_NOTBOL)
248       flags |= match_not_bol;
249    if(eflags & REG_NOTEOL)
250       flags |= match_not_eol;
251    if(eflags & REG_STARTEND)
252    {
253       start = buf + array[0].rm_so;
254       end = buf + array[0].rm_eo;
255    }
256    else
257    {
258       start = buf;
259       end = buf + std::wcslen(buf);
260    }
261 
262 #ifndef BOOST_NO_EXCEPTIONS
263    try{
264 #endif
265    if(expression->re_magic == wmagic_value)
266    {
267       result = regex_search(start, end, m, *static_cast<wc_regex_type*>(expression->guts), flags);
268    }
269    else
270       return result;
271 #ifndef BOOST_NO_EXCEPTIONS
272    } catch(...)
273    {
274       return REG_E_UNKNOWN;
275    }
276 #endif
277    if(result)
278    {
279       // extract what matched:
280       std::size_t i;
281       for(i = 0; (i < n) && (i < expression->re_nsub + 1); ++i)
282       {
283          array[i].rm_so = (m[i].matched == false) ? -1 : (m[i].first - buf);
284          array[i].rm_eo = (m[i].matched == false) ? -1 : (m[i].second - buf);
285       }
286       // and set anything else to -1:
287       for(i = expression->re_nsub + 1; i < n; ++i)
288       {
289          array[i].rm_so = -1;
290          array[i].rm_eo = -1;
291       }
292       return 0;
293    }
294    return REG_NOMATCH;
295 #ifdef BOOST_MSVC
296 #pragma warning(pop)
297 #endif
298 }
299 
regfreeW(regex_tW * expression)300 BOOST_REGEX_DECL void BOOST_REGEX_CCALL regfreeW(regex_tW* expression)
301 {
302    if(expression->re_magic == wmagic_value)
303    {
304       delete static_cast<wc_regex_type*>(expression->guts);
305    }
306    expression->re_magic = 0;
307 }
308 
309 } // namespace boost;
310 
311 #endif
312 
313 
314 
315 
316