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