]> git.saurik.com Git - wxWidgets.git/blob - samples/regextest/regextest.cpp
62805d83b0c2cbb33ba12d748f9ecefbcbcb11ef
[wxWidgets.git] / samples / regextest / regextest.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: regextest.cpp
3 // Purpose: Test regex libs and some gui components
4 // Author: Ryan Norton
5 // Modified by:
6 // RCS-ID: $Id$
7 // Copyright: (c) 2003 Ryan Norton <wxprojects@comcast.net>
8 // Licence: wxWindows license
9 /////////////////////////////////////////////////////////////////////////////
10
11 //===========================================================================
12 // REGEX LIBS
13 //===========================================================================
14
15 //wxWindows regular expression library
16 #define wxUSE_WXREGEX
17
18 //RN (Ryan Norton's) regular expression library
19 //#define wxUSE_RNWXRE
20
21 //GRETA, Microsoft Research's templated regex library
22 //[http://research.microsoft.com/projects/greta/]
23 //Install - Get it from .net powertools, put the directory in this directory
24 //#define wxUSE_GRETA
25
26 //PCRE (Perl Compatible Regular Expressions) [sourceforge.net/projects/pcre]
27 //Install - Get the GnuWin32 version and put the files in this directory
28 //#define wxUSE_PCRE
29
30 //===========================================================================
31 // HEADERS
32 //===========================================================================
33
34 // For compilers that support precompilation, includes "wx/wx.h".
35 #include "wx/wxprec.h"
36
37 #ifdef __BORLANDC__
38 #pragma hdrstop
39 #endif
40
41 // for all others, include the necessary headers (this file is usually all you
42 // need because it includes almost all "standard" wxWindows headers)
43 #ifndef WX_PRECOMP
44 #include "wx/wx.h"
45 #endif
46
47 #include "wx/file.h"
48
49 #ifdef wxUSE_WXREGEX
50 //
51 // This is the required header for wxRegEx
52 //
53 # include <wx/regex.h>
54 #endif
55
56 #ifdef wxUSE_RNWXRE
57 # include "re.h"
58 #endif
59
60 #ifdef wxUSE_GRETA
61 # ifdef _MSC_VER
62 # pragma warning(disable:4018)
63 # pragma warning(disable:4100)
64 # pragma warning(disable:4146)
65 # pragma warning(disable:4244)
66 # pragma warning(disable:4663)
67 extern "C" {
68 int __cdecl _resetstkoflw(void) {return 0;}
69 }
70 # endif //_MSC_VER
71 # include "greta/regexpr2.h"
72 using namespace regex;
73 #endif //wxUSE_GRETA
74
75 #ifdef wxUSE_PCRE
76 # include "pcre.h"
77 # ifdef _MSC_VER
78 # pragma comment(lib, "libpcre.a")
79 # endif
80 #endif
81
82 //===========================================================================
83 // IMPLEMENTATION
84 //===========================================================================
85
86 //
87 // One of the best sources for regex info is IEEE document/standard 1003.2
88 // From the open group.
89 // A current link - (http://www.opengroup.org/onlinepubs/007904975/basedefs/xbd_chap09.html).
90 //
91
92 //---------------------------------------------------------------------------
93 // MyFrame
94 //---------------------------------------------------------------------------
95
96 class MyFrame : public wxFrame
97 {
98 public:
99
100 //IDs for our controls
101 enum
102 {
103 PatternTextID,
104 SearchTextID,
105 OkButtonID
106 };
107
108 //Menu IDs
109 enum
110 {
111 ExtendedID,
112 ICaseID,
113 NewLineID,
114 NotBolID,
115 NotEolID,
116 CompID,
117 MatchID
118 };
119
120
121 void AddMenuItem(wxMenu* pMenu, int nID = wxID_SEPARATOR, const wxChar* szTitle = _(""),
122 const wxChar* szToolTip = _(""))
123 {
124 wxMenuItem* pItem;
125
126 if (nID == wxID_SEPARATOR)
127 pItem = new wxMenuItem (NULL, wxID_SEPARATOR, szTitle, szToolTip, wxITEM_SEPARATOR);
128 else
129 pItem = new wxMenuItem (NULL, nID, szTitle, szToolTip, wxITEM_CHECK);
130
131 pItem->SetBackgroundColour(wxColour(115, 113, 115));
132 pItem->SetTextColour(*wxBLACK);
133
134 pMenu->Append(pItem);
135 }
136
137 #if defined( __WXMSW__ ) || defined( __WXMAC__ )
138 void OnContextMenu(wxContextMenuEvent& event)
139 { PopupMenu(OptionsMenu, ScreenToClient(event.GetPosition())); }
140 #else
141 void OnRightUp(wxMouseEvent& event)
142 { PopupMenu(OptionsMenu, event.GetPosition()); }
143 #endif
144
145 MyFrame() : wxFrame( NULL, -1, _("regextest - wxRegEx Testing App"),
146 wxPoint(20,20), wxSize(300,400), wxDEFAULT_FRAME_STYLE | wxTAB_TRAVERSAL )
147 {
148 //Set the background to something light gray-ish
149 SetBackgroundColour(wxColour(150,150,150));
150
151 //
152 // Create the menus (Exit & About)
153 //
154 #if wxUSE_MENUS
155 wxMenu *FileMenu = new wxMenu;
156 OptionsMenu = new wxMenu;
157 wxMenu *HelpMenu = new wxMenu;
158
159 AddMenuItem(FileMenu, wxID_EXIT, _("&Exit"), _("Quit this program"));
160
161 AddMenuItem(OptionsMenu, ExtendedID, _T("wxRE_EXTENDED"), _("Extended Regular Expressions?"));
162 AddMenuItem(OptionsMenu, ICaseID, _T("wxRE_ICASE"), _("Enable case-insensitive matching?"));
163 AddMenuItem(OptionsMenu, NewLineID, _T("wxRE_NEWLINE"), _("Treat \n as special?"));
164 AddMenuItem(OptionsMenu);
165 AddMenuItem(OptionsMenu, NotBolID, _T("wxRE_NOTBOL"), _("Use functionality of ^ character?"));
166 AddMenuItem(OptionsMenu, NotEolID, _T("wxRE_NOTEOL"), _("Use functionality of $ character?"));
167 AddMenuItem(OptionsMenu);
168 AddMenuItem(OptionsMenu);
169 AddMenuItem(OptionsMenu, CompID, _("Test Compile"), _("Added Compiling to Match Time?"));
170 AddMenuItem(OptionsMenu, MatchID, _("Test Match"), _("Added Matching to Match Time?"));
171
172 AddMenuItem(HelpMenu, wxID_ABOUT, _T("&About...\tF1"), _("Show about dialog"));
173
174 OptionsMenu->Check(ExtendedID, true);
175 OptionsMenu->Check(MatchID, true);
176
177 wxMenuBar *MenuBar = new wxMenuBar();
178 MenuBar->Append(FileMenu, _T("&File"));
179 MenuBar->Append(OptionsMenu, _T("&Options"));
180 MenuBar->Append(HelpMenu, _T("&Help"));
181
182 SetMenuBar(MenuBar);
183 #endif // wxUSE_MENUS
184
185 // Text controls
186 PatternText.Create(this, PatternTextID, _(""), wxPoint(5, 30));
187 SearchText.Create(this, SearchTextID, _(""), wxPoint(5, 75));
188 //reset size of text controls
189 wxSize TextSize = PatternText.GetSize();
190 TextSize.SetWidth(200);
191 PatternText.SetSize(TextSize);
192 SearchText.SetSize(TextSize);
193
194 // StaticText
195 PatternHeader.Create(this, -1, _("Regular Expression:"), wxPoint(5, 10));
196 SearchHeader.Create(this, -1, _("String to Search:"), wxPoint(5, 55));
197 IterHeader.Create(this, -1, _("Iterations (Match Time):"), wxPoint(100, 100));
198
199 ResultText.Create(this, -1, _(""), wxPoint(5, 150), wxSize(100,200), wxST_NO_AUTORESIZE);
200 ResultText2.Create(this, -1, _(""), wxPoint(115, 150), wxSize(100,200), wxST_NO_AUTORESIZE);
201
202 // Button
203 OkButton.Create(this, OkButtonID, _("OK"), wxPoint(20, 120));
204
205 NumIters.Create(this, -1, _("15000"), wxPoint(100, 120));
206 }
207
208 void OnAbout(wxCommandEvent& WXUNUSED(evt))
209 {
210 wxChar* szBuffer;
211 wxFile f;
212
213 f.Open(_("README.txt"), wxFile::read);
214 szBuffer = new wxChar[f.Length() + 1];
215 f.Read(szBuffer, f.Length());
216 f.Close();
217
218 wxMessageBox(wxString::Format(
219 _("%s%s%s%s"),
220 _("-----------Regular Expression Test Application-----------\n"),
221 szBuffer,
222 _("\n\n\n(c) 2003 Ryan Norton <wxprojects@comcast.net>\n"),
223 wxVERSION_STRING
224 )
225 );
226
227 delete szBuffer;
228 }
229
230 void OnMatch(wxCommandEvent& WXUNUSED(evt))
231 {
232 wxString szPattern = PatternText.GetValue();
233 wxString szSearch = SearchText.GetValue();
234 wxString szResult, szResult2, szResult3, szResult4; //Will be displayed in ResultText
235 wxString szStatus, szStatus2, szStatus3, szStatus4;
236
237 int nCompileFlags = 0, nCompileFlags2 = 0, nCompileFlags3 = 0, nCompileFlags4 = 0;
238 int nMatchFlags = 0, nMatchFlags2 = 0, nMatchFlags3 = 0, nMatchFlags4 = 0;
239
240 if (!(OptionsMenu->IsChecked(ExtendedID)))
241 {
242 #ifdef wxUSE_WXREGEX
243 nCompileFlags |= wxRE_BASIC;
244 #endif
245 }
246 else
247 {
248 #ifdef wxUSE_RNWXRE
249 nCompileFlags2 |= wxRe::wxRE_EXTENDED;
250 #endif
251 // nCompileFlags3 |= EXTENDED;
252 }
253
254 if (OptionsMenu->IsChecked(ICaseID))
255 {
256 #ifdef wxUSE_WXREGEX
257 nCompileFlags |= wxRE_ICASE;
258 #endif
259 #ifdef wxUSE_RNWXRE
260 nCompileFlags2 |= wxRe::wxRE_ICASE;
261 #endif
262 #ifdef wxUSE_GRETA
263 nCompileFlags3 |= NOCASE;
264 #endif
265 }
266
267 if (OptionsMenu->IsChecked(NewLineID))
268 {
269 #ifdef wxUSE_WXREGEX
270 nCompileFlags |= wxRE_NEWLINE;
271 #endif
272 #ifdef wxUSE_RNWXRE
273 nCompileFlags2 |= wxRe::wxRE_NEWLINE;
274 #endif
275 #ifdef wxUSE_GRETA
276 nCompileFlags3 |= MULTILINE;
277 #endif
278 }
279
280 if (OptionsMenu->IsChecked(NotBolID))
281 {
282 #ifdef wxUSE_WXREGEX
283 nMatchFlags |= wxRE_NOTBOL;
284 #endif
285 #ifdef wxUSE_RNWXRE
286 nMatchFlags2 |= wxRe::wxRE_NOTBOL;
287 #endif
288 }
289
290 if (OptionsMenu->IsChecked(NotEolID))
291 {
292 #ifdef wxUSE_WXREGEX
293 nMatchFlags |= wxRE_NOTEOL;
294 #endif
295 #ifdef wxUSE_RNWXRE
296 nMatchFlags2 |= wxRe::wxRE_NOTEOL;
297 #endif
298 }
299
300 //Our regular expression object
301
302 //Success! Here we'll display some
303 //information to the user
304 size_t dwStartIndex = 0, dwEndIndex = 0,
305 dwStartIndex2= 0, dwEndIndex2= 0,
306 dwStartIndex3= 0, dwEndIndex3= 0,
307 dwStartIndex4= 0, dwEndIndex4= 0;
308
309 time_t dwStartTime = 0, dwEndTime = 0,
310 dwStartTime2= 0, dwEndTime2= 0,
311 dwStartTime3= 0, dwEndTime3= 0,
312 dwStartTime4= 0, dwEndTime4= 0;
313
314 int i = 0;
315 long n;
316 if (!NumIters.GetValue().ToLong(&n))
317 n = 0;
318
319
320 #ifdef wxUSE_WXREGEX
321 wxRegEx Regex;
322 //Regular Expressions must be compiled before
323 //you can search a string with them, or
324 //at least most implementations do.
325 //(Boost and Microsoft have templated
326 //versions that don't require compilation)
327 //Basically compilation breaks it down into
328 //something that's easier to parse, due
329 //to the syntax of regular expressions
330 if (!Regex.Compile(szPattern, nCompileFlags))
331 szStatus += _("\nCompile Failed!\n");
332 else
333 {
334 //Here's where we actually search our string
335 if (!Regex.Matches(szSearch, nMatchFlags))
336 szStatus += _("\nExecution/Matching Failed!\n");
337 else
338 {
339 Regex.GetMatch(&dwStartIndex, &dwEndIndex);
340
341 szStatus = _("Success");
342
343 //We're going to go ahead and time the match
344 //for fun (clock() is a c library routine that
345 //returns the current time since a certian point
346 //in milliseconds
347 dwStartTime = clock();
348
349 if (OptionsMenu->IsChecked(CompID))
350 {
351 for(i = 0; i < n; ++i)
352 {
353 Regex.Compile(szPattern, nCompileFlags);
354 }
355 }
356 if (OptionsMenu->IsChecked(MatchID))
357 {
358 for(i = 0; i < n; ++i)
359 {
360 Regex.Matches(szSearch, nMatchFlags);
361 }
362 }
363
364 //This line gets the difference in time between now
365 //and when we first initialized dwStartTime.
366 dwEndTime = clock() - dwStartTime;
367 }
368 }
369
370
371 szResult = wxString::Format(
372 _("--wxRegEx--\nIndex:[%i]-[%i]\nString:%s\nMatch Time:%ums\nStatus:%s"),
373 dwStartIndex, dwEndIndex+dwStartIndex,
374 szSearch.Mid(dwStartIndex, dwEndIndex),
375 dwEndTime,
376 szStatus
377 );
378
379 #endif //wxUSE_WXREGEX
380
381 #ifdef wxUSE_RNWXRE
382 wxRe Re;
383 wxRe::wxReError e;
384 if ((e = Re.Comp(szPattern, nCompileFlags2)) != wxRe::wxRE_OK)
385 szStatus2 = wxString::Format(_("\nCompile Failed!\n%s\n"), wxRe::ErrorToString(e));
386 else
387 {
388 //Here's where we actually search our string
389 if ((e = Re.Exec(szSearch, nMatchFlags2)) != wxRe::wxRE_OK)
390 szStatus2 = wxString::Format(_("\nExecution/Matching Failed!\n%s\n"), wxRe::ErrorToString(e));
391 else
392 {
393 dwStartIndex2 = Re.GetMatch(0).first;
394 dwEndIndex2 = Re.GetMatch(0).second;
395
396 szStatus2 = _("Success");
397
398 dwStartTime2 = clock();
399
400 if (OptionsMenu->IsChecked(CompID))
401 {
402 for(i = 0; i < n; ++i)
403 {
404 Re.Comp(szPattern, nCompileFlags2);
405 }
406 }
407 if (OptionsMenu->IsChecked(MatchID))
408 {
409 for(i = 0; i < n; ++i)
410 {
411 Re.Exec(szSearch, nMatchFlags2);
412 }
413 }
414
415 dwEndTime2 = clock() - dwStartTime2;
416 }
417 }
418 szResult2 = wxString::Format(
419 _("--Ryan's wxRe--\nIndex:[%i]-[%i]\nString:%s\nMatch Time:%ums\nStatus:%s"),
420 dwStartIndex2, dwEndIndex2+dwStartIndex2,
421 szSearch.Mid(dwStartIndex2, dwEndIndex2),
422 dwEndTime2,
423 szStatus2
424 );
425 #endif //wxUSE_RNWXRE
426
427 #ifdef wxUSE_GRETA
428 std::string stdszPattern(szPattern);
429 rpattern Greta (stdszPattern,EXTENDED,MODE_MIXED);
430 match_results r;
431 std::string stdszSearch(szSearch);
432
433 //Here's where we actually search our string
434 if (!Greta.match(stdszSearch, r).matched)
435 szStatus3 += _("\nExecution/Matching Failed!\n");
436 else
437 {
438 szStatus3 = _("Success");
439
440 dwStartTime3 = clock();
441
442 if (OptionsMenu->IsChecked(CompID))
443 {
444 for(i = 0; i < n; ++i)
445 {
446 //Supposively GRETA doesn't compile, but
447 //it's clear that it slows performance greatly
448 //when creating a rpattern object,
449 //so one can only surmize that it performs
450 //some kind of optimizations in the constructor
451 Greta = rpattern(stdszPattern,EXTENDED,MODE_MIXED);
452 }
453 }
454 if (OptionsMenu->IsChecked(MatchID))
455 {
456 for(i = 0; i < n; ++i)
457 {
458 Greta.match(stdszSearch, r);
459 }
460 }
461
462 dwEndTime3 = clock() - dwStartTime3;
463 }
464
465 szResult3 = wxString::Format(
466 _("--Greta--\nIndex:[%i]-[%i]\nString:%s\nMatch Time:%ums\nStatus:%s"),
467 r.rstart(), r.rlength() + r.rstart(),
468 szSearch.Mid(r.rstart(), r.rlength()),
469 dwEndTime3,
470 szStatus3);
471 #endif //wxUSE_GRETA
472
473 #ifdef wxUSE_PCRE
474 pcre* pPcre;
475 const wxChar* szError;
476 int nErrOff;
477
478 if ((pPcre = pcre_compile(szPattern, nCompileFlags4, &szError, &nErrOff, 0)) == NULL)
479 szStatus4 = wxString::Format(_("\nCompile Failed!\nError:%s\nOffset:%i\n"), szError, nErrOff);
480 else
481 {
482 size_t msize;
483 pcre_fullinfo(pPcre, 0, PCRE_INFO_CAPTURECOUNT, &msize);
484 msize = 3*(msize+1);
485 int *m = new int[msize];
486
487 //Here's where we actually search our string
488 if (!pcre_exec(pPcre, 0, szSearch, szSearch.Length(), 0, 0, m, msize))
489 szStatus4 = wxString::Format(_("\nExecution/Matching Failed!\n"));
490 else
491 {
492 dwStartIndex4 = m[0];
493 dwEndIndex4 = m[1] - m[0];
494
495 szStatus4 = _("Success");
496
497 dwStartTime4 = clock();
498
499
500 if (OptionsMenu->IsChecked(CompID))
501 {
502 for(i = 0; i < n; ++i)
503 {
504 pPcre = pcre_compile(szPattern, nCompileFlags4, &szError, &nErrOff, 0);
505 }
506 }
507 if (OptionsMenu->IsChecked(MatchID))
508 {
509 for(i = 0; i < n; ++i)
510 {
511 pcre_exec(pPcre, 0, szSearch, szSearch.Length(), 0, 0, m, msize);
512 }
513 }
514
515 dwEndTime4 = clock() - dwStartTime4;
516 }
517 }
518 szResult4 = wxString::Format(
519 _("--PCRE--\nIndex:[%i]-[%i]\nString:%s\nMatch Time:%ums\nStatus:%s"),
520 dwStartIndex4, dwEndIndex4+dwStartIndex4,
521 szSearch.Mid(dwStartIndex4, dwEndIndex4),
522 dwEndTime4,
523 szStatus4
524 );
525 #endif //wxUSE_PCRE
526
527 ResultText.SetLabel(szResult + _("\n\n") + szResult2);
528 ResultText2.SetLabel(szResult3 + _("\n\n") + szResult4);
529 }
530
531 void OnQuit(wxCommandEvent& WXUNUSED(evt))
532 {
533 Close(TRUE);
534 }
535
536 wxTextCtrl PatternText, SearchText, NumIters;
537 wxStaticText PatternHeader, SearchHeader, IterHeader, ResultText, ResultText2;
538 wxButton OkButton;
539
540 wxMenu *OptionsMenu;
541
542 DECLARE_EVENT_TABLE()
543 };
544
545 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
546
547 //menu
548 EVT_MENU(wxID_EXIT, MyFrame::OnQuit)
549 EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
550
551 //text
552 EVT_TEXT_ENTER(MyFrame::PatternTextID, MyFrame::OnMatch)
553 EVT_TEXT_ENTER(MyFrame::SearchTextID, MyFrame::OnMatch)
554
555 //button
556 EVT_BUTTON(MyFrame::OkButtonID, MyFrame::OnMatch)
557
558 #if defined( __WXMSW__ ) || defined( __WXMAC__ )
559 EVT_CONTEXT_MENU(MyFrame::OnContextMenu)
560 #else
561 EVT_RIGHT_UP(MyFrame::OnRightUp)
562 #endif
563
564 END_EVENT_TABLE()
565
566 //---------------------------------------------------------------------------
567 // MyApp
568 //---------------------------------------------------------------------------
569
570 class MyApp : public wxApp
571 {
572 public:
573 bool OnInit()
574 {
575 MyFrame* dialog = new MyFrame();
576 dialog->Show();
577 return true;
578 }
579 };
580
581 IMPLEMENT_APP(MyApp)
582