OSDN Git Service

crystaledit: Make almost the same code into a common function
[winmerge-jp/winmerge-jp.git] / Externals / crystaledit / editlib / utils / cregexp_poco.cpp
1 ///////////////////////////////////////////////////////////////////////////
2 //  File:    regexp.cpp
3 //  Version: 1.1.0.4
4 //  Updated: 19-Jul-1998
5 //
6 //  Copyright:  Marko Macek
7 //  E-mail:     Marko.Macek@gmx.net or mark@hermes.si
8 //
9 //  Some handy stuff to deal with regular expressions
10 //
11 //  You are free to use or modify this code to the following restrictions:
12 //  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
13 //  will be enough. If you can't (or don't want to), contact me personally.
14 //  - LEAVE THIS HEADER INTACT
15 ////////////////////////////////////////////////////////////////////////////
16
17 #include "StdAfx.h"
18 #include <cassert>
19 #include <cstdio>
20 #include <cstdlib>
21 #include <cstring>
22 #include <cctype>
23 #include <memory>
24 #include <Poco/RegularExpression.h>
25 #include <Poco/UnicodeConverter.h>
26 #include "cregexp.h"
27 #include "unicoder.h"
28
29 using Poco::RegularExpression;
30 using Poco::UnicodeConverter;
31
32 struct _RxNode {
33         std::unique_ptr<RegularExpression> regexp;
34 };
35
36 RxNode *RxCompile(LPCTSTR Regexp, unsigned int RxOpt) {
37     RxNode *n = nullptr;
38     if (Regexp == nullptr) return nullptr;
39     n = new RxNode();
40     if (n == nullptr) return nullptr;
41
42         const char * errormsg = nullptr;
43         int erroroffset = 0;
44         int pcre_opts = 0;
45         std::string regexString;
46 #ifdef UNICODE
47         pcre_opts |= RegularExpression::RE_UTF8;
48         UnicodeConverter::toUTF8(Regexp, regexString);
49 #else
50         regexString = Regexp;
51 #endif
52     // TODO:
53         // pcre_opts |= PCRE_BSR_ANYCRLF;
54     if ((RxOpt & RX_CASE) == 0)
55                 pcre_opts |= RegularExpression::RE_CASELESS;
56
57         try
58         {
59                 n->regexp.reset(new RegularExpression(regexString, pcre_opts));
60         }
61         catch (...)
62         {
63                 return nullptr;
64         }
65
66     return n;
67 }
68
69 void RxFree(RxNode *n) {
70         if (n)
71         {
72                 delete n;
73         }
74 }
75
76 int RxExec(RxNode *Regexp, LPCTSTR Data, size_t Len, LPCTSTR Start, RxMatchRes *Match) {
77     if (Regexp == nullptr) return 0;
78
79         int i;
80     for (i = 0; i < NSEXPS; i++) Match->Open[i] = Match->Close[i] = -1;
81
82         RegularExpression::MatchVec ovector;
83         std::string compString;
84 #ifdef UNICODE
85         size_t startoffset = ucr::Utf8len_of_string(Data, Start - Data);
86         UnicodeConverter::toUTF8(Data, Len, compString);
87 #else
88         int startoffset = Start - Data;
89         compString = Data;
90 #endif
91         int result = 0;
92         try {
93                 result = Regexp->regexp->match(compString, startoffset, ovector);
94         }
95         catch (...)
96         {
97         }
98         if (result >= 0)
99         {
100                 for (i = 0; i < result; i++)
101                 {
102 #ifdef UNICODE
103                         Match->Open[i] = ucr::stringlen_of_utf8(compString.c_str(), ovector[i].offset);
104                         Match->Close[i] = ucr::stringlen_of_utf8(compString.c_str(), ovector[i].offset + ovector[i].length);
105 #else
106                         Match->Open[i] = ovector[i].offset;
107                         Match->Close[i] = ovector[i].offset + ovector[i].length;
108 #endif
109                 }
110         }
111
112     return (result > 0);
113 }
114
115 #define FLAG_UP_CASE     1
116 #define FLAG_DOWN_CASE   2
117 #define FLAG_UP_NEXT     4
118 #define FLAG_DOWN_NEXT   8
119
120 static int add(size_t *len, LPTSTR *s, LPCTSTR a, size_t alen, int &flag) {
121     size_t NewLen = *len + alen;
122     size_t i;
123
124     NewLen = NewLen * 2;
125
126     if (alen == 0)
127         return 0;
128
129     if (*s) {
130         LPTSTR p = (LPTSTR) realloc(*s, NewLen * sizeof(TCHAR));
131                 if (p == nullptr)
132                         return 0;
133                 *s = p;
134                 assert(*s != 0);
135                 memcpy(*s + *len, a, alen * sizeof(TCHAR));
136     } else {
137         *s = (LPTSTR) malloc(NewLen * sizeof(TCHAR));
138         assert(*s != 0);
139         memcpy(*s, a, alen * sizeof(TCHAR));
140         *len = 0;
141     }
142     if (flag & FLAG_UP_CASE) {
143         LPTSTR p = *s + *len;
144
145         for (i = 0; i < alen; i++) {
146             *p = (TCHAR)_totupper(*p);
147             p++;
148         }
149     } else if (flag & FLAG_DOWN_CASE) {
150         LPTSTR p = *s + *len;
151
152         for (i = 0; i < alen; i++) {
153             *p = (TCHAR)_totlower(*p);
154             p++;
155         }
156     }
157     if (flag & FLAG_UP_NEXT) {
158         LPTSTR p = *s + *len;
159
160         *p = (TCHAR)_totupper(*p);
161         flag &= ~FLAG_UP_NEXT;
162     } else if (flag & FLAG_DOWN_NEXT) {
163         LPTSTR p = *s + *len;
164
165         *p = (TCHAR)_totlower(*p);
166         flag &= ~FLAG_DOWN_NEXT;
167     }
168     *len += alen;
169     return 0;
170 }
171
172 int RxReplace(LPCTSTR rep, LPCTSTR Src, int /*len*/, RxMatchRes match, LPTSTR *Dest, int *Dlen) {
173     size_t dlen = 0;
174     LPTSTR dest = 0;
175     TCHAR Ch;
176     int n;
177     int flag = 0;
178
179     *Dest = 0;
180     *Dlen = 0;
181     //    add(&dlen, &dest, Src, match.Open[0]);
182     while (*rep) {
183         switch (Ch = *rep++) {
184             //        case _T('&'):
185             //            add(&dlen, &dest, Src + match.Open[0], match.Close[0] - match.Open[0], flag);
186             //            break;
187         case _T('\\'):
188             switch (Ch = *rep++) {
189             case _T('0'):
190             case _T('1'): case _T('2'): case _T('3'):
191             case _T('4'): case _T('5'): case _T('6'):
192             case _T('7'): case _T('8'): case _T('9'):
193                 n = Ch - 48;
194
195                 if (match.Open[n] != -1 && match.Close[n] != -1) {
196                     add(&dlen, &dest, Src + match.Open[n], match.Close[n] - match.Open[n], flag);
197                 } else return -1;
198                 break;
199             case 0:
200                 if (dest) free(dest);
201                 return -1; // error
202             case _T('r'): Ch = _T('\r'); add(&dlen, &dest, &Ch, 1, flag); break;
203             case _T('n'): Ch = _T('\n'); add(&dlen, &dest, &Ch, 1, flag); break;
204             case _T('b'): Ch = _T('\b'); add(&dlen, &dest, &Ch, 1, flag); break;
205             case _T('a'): Ch = _T('\a'); add(&dlen, &dest, &Ch, 1, flag); break;
206             case _T('t'): Ch = _T('\t'); add(&dlen, &dest, &Ch, 1, flag); break;
207             case _T('U'): flag |= FLAG_UP_CASE; break;
208             case _T('u'): flag |= FLAG_UP_NEXT; break;
209             case _T('L'): flag |= FLAG_DOWN_CASE; break;
210             case _T('l'): flag |= FLAG_DOWN_NEXT; break;
211             case _T('E'):
212             case _T('e'): flag &= ~(FLAG_UP_CASE | FLAG_DOWN_CASE); break;
213             case _T('x'):
214                 {
215                     int N = 0;
216                     int A = 0;
217
218                     if (*rep == 0) return 0;
219                     N = _totupper(*rep) - 48; if (N > 9) N = N + 48 - 65 + 10; if (N > 15) return 0;
220                     rep++;
221                     A = N << 4;
222                     if (*rep == 0) return 0;
223                     N = _totupper(*rep) - 48; if (N > 9) N = N + 48 - 65 + 10; if (N > 15) return 0;
224                     rep++;
225                     A = A + N;
226                     Ch = (TCHAR)A;
227                 }
228                 add(&dlen, &dest, &Ch, 1, flag);
229                 break;
230             case _T('d'):
231                 {
232                     int N = 0;
233                     int A = 0;
234
235                     if (*rep == 0) return 0;
236                     N = _totupper(*rep) - 48; if (N > 9) return 0;
237                     rep++;
238                     A = N * 100;
239                     if (*rep == 0) return 0;
240                     N = _totupper(*rep) - 48; if (N > 9) return 0;
241                     rep++;
242                     A = N * 10;
243                     if (*rep == 0) return 0;
244                     N = _totupper(*rep) - 48; if (N > 9) return 0;
245                     rep++;
246                     A = A + N;
247                     Ch = (TCHAR)A;
248                 }
249                 add(&dlen, &dest, &Ch, 1, flag);
250                 break;
251             case _T('o'):
252                 {
253                     int N = 0;
254                     int A = 0;
255
256                     if (*rep == 0) return 0;
257                     N = _totupper(*rep) - 48; if (N > 7) return 0;
258                     rep++;
259                     A = N * 64;
260                     if (*rep == 0) return 0;
261                     N = _totupper(*rep) - 48; if (N > 7) return 0;
262                     rep++;
263                     A = N * 8;
264                     if (*rep == 0) return 0;
265                     N = _totupper(*rep) - 48; if (N > 7) return 0;
266                     rep++;
267                     A = A + N;
268                     Ch = (TCHAR)A;
269                 }
270                 add(&dlen, &dest, &Ch, 1, flag);
271                 break;
272             default:
273                 add(&dlen, &dest, &Ch, 1, flag);
274                 break;
275             }
276             break;
277         default:
278             add(&dlen, &dest, &Ch, 1, flag);
279             break;
280         }
281     }
282     //    add(&dlen, &dest, Src + match.Close[0], len - match.Close[0]);
283         ASSERT(dlen < INT_MAX);
284     *Dlen = static_cast<int>(dlen);
285     *Dest = dest;
286     return 0;
287 }