]> git.saurik.com Git - wxWidgets.git/blob - samples/console/console.cpp
Some parts rewritten to use wxSocket events instead of callbacks, as the
[wxWidgets.git] / samples / console / console.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: samples/console/console.cpp
3 // Purpose: a sample console (as opposed to GUI) progam using wxWindows
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 04.10.99
7 // RCS-ID: $Id$
8 // Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #include <stdio.h>
21
22 #include <wx/string.h>
23 #include <wx/file.h>
24 #include <wx/app.h>
25
26 // without this pragma, the stupid compiler precompiles #defines below so that
27 // changing them doesn't "take place" later!
28 #ifdef __VISUALC__
29 #pragma hdrstop
30 #endif
31
32 // ----------------------------------------------------------------------------
33 // conditional compilation
34 // ----------------------------------------------------------------------------
35
36 // what to test (in alphabetic order)?
37
38 //#define TEST_ARRAYS
39 //#define TEST_CMDLINE
40 //#define TEST_DATETIME
41 //#define TEST_DIR
42 //#define TEST_EXECUTE
43 //#define TEST_FILECONF
44 //#define TEST_HASH
45 //#define TEST_LOG
46 //#define TEST_LONGLONG
47 //#define TEST_MIME
48 //#define TEST_SOCKETS
49 //#define TEST_STRINGS
50 //#define TEST_THREADS
51 #define TEST_TIMER
52
53 // ============================================================================
54 // implementation
55 // ============================================================================
56
57 // ----------------------------------------------------------------------------
58 // wxCmdLineParser
59 // ----------------------------------------------------------------------------
60
61 #ifdef TEST_CMDLINE
62
63 #include <wx/cmdline.h>
64 #include <wx/datetime.h>
65
66 static void ShowCmdLine(const wxCmdLineParser& parser)
67 {
68 wxString s = "Input files: ";
69
70 size_t count = parser.GetParamCount();
71 for ( size_t param = 0; param < count; param++ )
72 {
73 s << parser.GetParam(param) << ' ';
74 }
75
76 s << '\n'
77 << "Verbose:\t" << (parser.Found("v") ? "yes" : "no") << '\n'
78 << "Quiet:\t" << (parser.Found("q") ? "yes" : "no") << '\n';
79
80 wxString strVal;
81 long lVal;
82 wxDateTime dt;
83 if ( parser.Found("o", &strVal) )
84 s << "Output file:\t" << strVal << '\n';
85 if ( parser.Found("i", &strVal) )
86 s << "Input dir:\t" << strVal << '\n';
87 if ( parser.Found("s", &lVal) )
88 s << "Size:\t" << lVal << '\n';
89 if ( parser.Found("d", &dt) )
90 s << "Date:\t" << dt.FormatISODate() << '\n';
91
92 wxLogMessage(s);
93 }
94
95 #endif // TEST_CMDLINE
96
97 // ----------------------------------------------------------------------------
98 // wxDir
99 // ----------------------------------------------------------------------------
100
101 #ifdef TEST_DIR
102
103 #include <wx/dir.h>
104
105 static void TestDirEnumHelper(wxDir& dir,
106 int flags = wxDIR_DEFAULT,
107 const wxString& filespec = wxEmptyString)
108 {
109 wxString filename;
110
111 if ( !dir.IsOpened() )
112 return;
113
114 bool cont = dir.GetFirst(&filename, filespec, flags);
115 while ( cont )
116 {
117 printf("\t%s\n", filename.c_str());
118
119 cont = dir.GetNext(&filename);
120 }
121
122 puts("");
123 }
124
125 static void TestDirEnum()
126 {
127 wxDir dir(wxGetCwd());
128
129 puts("Enumerating everything in current directory:");
130 TestDirEnumHelper(dir);
131
132 puts("Enumerating really everything in current directory:");
133 TestDirEnumHelper(dir, wxDIR_DEFAULT | wxDIR_DOTDOT);
134
135 puts("Enumerating object files in current directory:");
136 TestDirEnumHelper(dir, wxDIR_DEFAULT, "*.o");
137
138 puts("Enumerating directories in current directory:");
139 TestDirEnumHelper(dir, wxDIR_DIRS);
140
141 puts("Enumerating files in current directory:");
142 TestDirEnumHelper(dir, wxDIR_FILES);
143
144 puts("Enumerating files including hidden in current directory:");
145 TestDirEnumHelper(dir, wxDIR_FILES | wxDIR_HIDDEN);
146
147 #ifdef __UNIX__
148 dir.Open("/");
149 #elif defined(__WXMSW__)
150 dir.Open("c:\\");
151 #else
152 #error "don't know where the root directory is"
153 #endif
154
155 puts("Enumerating everything in root directory:");
156 TestDirEnumHelper(dir, wxDIR_DEFAULT);
157
158 puts("Enumerating directories in root directory:");
159 TestDirEnumHelper(dir, wxDIR_DIRS);
160
161 puts("Enumerating files in root directory:");
162 TestDirEnumHelper(dir, wxDIR_FILES);
163
164 puts("Enumerating files including hidden in root directory:");
165 TestDirEnumHelper(dir, wxDIR_FILES | wxDIR_HIDDEN);
166
167 puts("Enumerating files in non existing directory:");
168 wxDir dirNo("nosuchdir");
169 TestDirEnumHelper(dirNo);
170 }
171
172 #endif // TEST_DIR
173
174 // ----------------------------------------------------------------------------
175 // wxExecute
176 // ----------------------------------------------------------------------------
177
178 #ifdef TEST_EXECUTE
179
180 #include <wx/utils.h>
181
182 static void TestExecute()
183 {
184 puts("*** testing wxExecute ***");
185
186 #ifdef __UNIX__
187 #define COMMAND "echo hi"
188 #define SHELL_COMMAND "echo hi from shell"
189 #define REDIRECT_COMMAND "date"
190 #elif defined(__WXMSW__)
191 #define COMMAND "command.com -c 'echo hi'"
192 #define SHELL_COMMAND "echo hi"
193 #define REDIRECT_COMMAND COMMAND
194 #else
195 #error "no command to exec"
196 #endif // OS
197
198 printf("Testing wxShell: ");
199 fflush(stdout);
200 if ( wxShell(SHELL_COMMAND) )
201 puts("Ok.");
202 else
203 puts("ERROR.");
204
205 printf("Testing wxExecute: ");
206 fflush(stdout);
207 if ( wxExecute(COMMAND, TRUE /* sync */) == 0 )
208 puts("Ok.");
209 else
210 puts("ERROR.");
211
212 #if 0 // no, it doesn't work (yet?)
213 printf("Testing async wxExecute: ");
214 fflush(stdout);
215 if ( wxExecute(COMMAND) != 0 )
216 puts("Ok (command launched).");
217 else
218 puts("ERROR.");
219 #endif // 0
220
221 printf("Testing wxExecute with redirection:\n");
222 wxArrayString output;
223 if ( wxExecute(REDIRECT_COMMAND, output) != 0 )
224 {
225 puts("ERROR.");
226 }
227 else
228 {
229 size_t count = output.GetCount();
230 for ( size_t n = 0; n < count; n++ )
231 {
232 printf("\t%s\n", output[n].c_str());
233 }
234
235 puts("Ok.");
236 }
237 }
238
239 #endif // TEST_EXECUTE
240
241 // ----------------------------------------------------------------------------
242 // wxFileConfig
243 // ----------------------------------------------------------------------------
244
245 #ifdef TEST_FILECONF
246
247 #include <wx/confbase.h>
248 #include <wx/fileconf.h>
249
250 static const struct FileConfTestData
251 {
252 const wxChar *name; // value name
253 const wxChar *value; // the value from the file
254 } fcTestData[] =
255 {
256 { _T("value1"), _T("one") },
257 { _T("value2"), _T("two") },
258 { _T("novalue"), _T("default") },
259 };
260
261 static void TestFileConfRead()
262 {
263 puts("*** testing wxFileConfig loading/reading ***");
264
265 wxFileConfig fileconf(_T("test"), wxEmptyString,
266 _T("testdata.fc"), wxEmptyString,
267 wxCONFIG_USE_RELATIVE_PATH);
268
269 // test simple reading
270 puts("\nReading config file:");
271 wxString defValue(_T("default")), value;
272 for ( size_t n = 0; n < WXSIZEOF(fcTestData); n++ )
273 {
274 const FileConfTestData& data = fcTestData[n];
275 value = fileconf.Read(data.name, defValue);
276 printf("\t%s = %s ", data.name, value.c_str());
277 if ( value == data.value )
278 {
279 puts("(ok)");
280 }
281 else
282 {
283 printf("(ERROR: should be %s)\n", data.value);
284 }
285 }
286
287 // test enumerating the entries
288 puts("\nEnumerating all root entries:");
289 long dummy;
290 wxString name;
291 bool cont = fileconf.GetFirstEntry(name, dummy);
292 while ( cont )
293 {
294 printf("\t%s = %s\n",
295 name.c_str(),
296 fileconf.Read(name.c_str(), _T("ERROR")).c_str());
297
298 cont = fileconf.GetNextEntry(name, dummy);
299 }
300 }
301
302 #endif // TEST_FILECONF
303
304 // ----------------------------------------------------------------------------
305 // wxHashTable
306 // ----------------------------------------------------------------------------
307
308 #ifdef TEST_HASH
309
310 #include <wx/hash.h>
311
312 struct Foo
313 {
314 Foo(int n_) { n = n_; count++; }
315 ~Foo() { count--; }
316
317 int n;
318
319 static size_t count;
320 };
321
322 size_t Foo::count = 0;
323
324 WX_DECLARE_LIST(Foo, wxListFoos);
325 WX_DECLARE_HASH(Foo, wxListFoos, wxHashFoos);
326
327 #include <wx/listimpl.cpp>
328
329 WX_DEFINE_LIST(wxListFoos);
330
331 static void TestHash()
332 {
333 puts("*** Testing wxHashTable ***\n");
334
335 {
336 wxHashFoos hash;
337 hash.DeleteContents(TRUE);
338
339 printf("Hash created: %u foos in hash, %u foos totally\n",
340 hash.GetCount(), Foo::count);
341
342 static const int hashTestData[] =
343 {
344 0, 1, 17, -2, 2, 4, -4, 345, 3, 3, 2, 1,
345 };
346
347 size_t n;
348 for ( n = 0; n < WXSIZEOF(hashTestData); n++ )
349 {
350 hash.Put(hashTestData[n], n, new Foo(n));
351 }
352
353 printf("Hash filled: %u foos in hash, %u foos totally\n",
354 hash.GetCount(), Foo::count);
355
356 puts("Hash access test:");
357 for ( n = 0; n < WXSIZEOF(hashTestData); n++ )
358 {
359 printf("\tGetting element with key %d, value %d: ",
360 hashTestData[n], n);
361 Foo *foo = hash.Get(hashTestData[n], n);
362 if ( !foo )
363 {
364 printf("ERROR, not found.\n");
365 }
366 else
367 {
368 printf("%d (%s)\n", foo->n,
369 (size_t)foo->n == n ? "ok" : "ERROR");
370 }
371 }
372
373 printf("\nTrying to get an element not in hash: ");
374
375 if ( hash.Get(1234) || hash.Get(1, 0) )
376 {
377 puts("ERROR: found!");
378 }
379 else
380 {
381 puts("ok (not found)");
382 }
383 }
384
385 printf("Hash destroyed: %u foos left\n", Foo::count);
386 }
387
388 #endif // TEST_HASH
389
390 // ----------------------------------------------------------------------------
391 // MIME types
392 // ----------------------------------------------------------------------------
393
394 #ifdef TEST_MIME
395
396 #include <wx/mimetype.h>
397
398 static void TestMimeEnum()
399 {
400 wxMimeTypesManager mimeTM;
401 wxArrayString mimetypes;
402
403 size_t count = mimeTM.EnumAllFileTypes(mimetypes);
404
405 printf("*** All %u known filetypes: ***\n", count);
406
407 wxArrayString exts;
408 wxString desc;
409
410 for ( size_t n = 0; n < count; n++ )
411 {
412 wxFileType *filetype = mimeTM.GetFileTypeFromMimeType(mimetypes[n]);
413 if ( !filetype )
414 {
415 printf("nothing known about the filetype '%s'!\n",
416 mimetypes[n].c_str());
417 continue;
418 }
419
420 filetype->GetDescription(&desc);
421 filetype->GetExtensions(exts);
422
423 filetype->GetIcon(NULL);
424
425 wxString extsAll;
426 for ( size_t e = 0; e < exts.GetCount(); e++ )
427 {
428 if ( e > 0 )
429 extsAll << _T(", ");
430 extsAll += exts[e];
431 }
432
433 printf("\t%s: %s (%s)\n",
434 mimetypes[n].c_str(), desc.c_str(), extsAll.c_str());
435 }
436 }
437
438 #endif // TEST_MIME
439
440 // ----------------------------------------------------------------------------
441 // long long
442 // ----------------------------------------------------------------------------
443
444 #ifdef TEST_LONGLONG
445
446 #include <wx/longlong.h>
447 #include <wx/timer.h>
448
449 // make a 64 bit number from 4 16 bit ones
450 #define MAKE_LL(x1, x2, x3, x4) wxLongLong((x1 << 16) | x2, (x3 << 16) | x3)
451
452 // get a random 64 bit number
453 #define RAND_LL() MAKE_LL(rand(), rand(), rand(), rand())
454
455 #if wxUSE_LONGLONG_WX
456 inline bool operator==(const wxLongLongWx& a, const wxLongLongNative& b)
457 { return a.GetHi() == b.GetHi() && a.GetLo() == b.GetLo(); }
458 inline bool operator==(const wxLongLongNative& a, const wxLongLongWx& b)
459 { return a.GetHi() == b.GetHi() && a.GetLo() == b.GetLo(); }
460 #endif // wxUSE_LONGLONG_WX
461
462 static void TestSpeed()
463 {
464 static const long max = 100000000;
465 long n;
466
467 {
468 wxStopWatch sw;
469
470 long l = 0;
471 for ( n = 0; n < max; n++ )
472 {
473 l += n;
474 }
475
476 printf("Summing longs took %ld milliseconds.\n", sw.Time());
477 }
478
479 #if wxUSE_LONGLONG_NATIVE
480 {
481 wxStopWatch sw;
482
483 wxLongLong_t l = 0;
484 for ( n = 0; n < max; n++ )
485 {
486 l += n;
487 }
488
489 printf("Summing wxLongLong_t took %ld milliseconds.\n", sw.Time());
490 }
491 #endif // wxUSE_LONGLONG_NATIVE
492
493 {
494 wxStopWatch sw;
495
496 wxLongLong l;
497 for ( n = 0; n < max; n++ )
498 {
499 l += n;
500 }
501
502 printf("Summing wxLongLongs took %ld milliseconds.\n", sw.Time());
503 }
504 }
505
506 static void TestLongLongConversion()
507 {
508 puts("*** Testing wxLongLong conversions ***\n");
509
510 wxLongLong a;
511 size_t nTested = 0;
512 for ( size_t n = 0; n < 100000; n++ )
513 {
514 a = RAND_LL();
515
516 #if wxUSE_LONGLONG_NATIVE
517 wxLongLongNative b(a.GetHi(), a.GetLo());
518
519 wxASSERT_MSG( a == b, "conversions failure" );
520 #else
521 puts("Can't do it without native long long type, test skipped.");
522
523 return;
524 #endif // wxUSE_LONGLONG_NATIVE
525
526 if ( !(nTested % 1000) )
527 {
528 putchar('.');
529 fflush(stdout);
530 }
531
532 nTested++;
533 }
534
535 puts(" done!");
536 }
537
538 static void TestMultiplication()
539 {
540 puts("*** Testing wxLongLong multiplication ***\n");
541
542 wxLongLong a, b;
543 size_t nTested = 0;
544 for ( size_t n = 0; n < 100000; n++ )
545 {
546 a = RAND_LL();
547 b = RAND_LL();
548
549 #if wxUSE_LONGLONG_NATIVE
550 wxLongLongNative aa(a.GetHi(), a.GetLo());
551 wxLongLongNative bb(b.GetHi(), b.GetLo());
552
553 wxASSERT_MSG( a*b == aa*bb, "multiplication failure" );
554 #else // !wxUSE_LONGLONG_NATIVE
555 puts("Can't do it without native long long type, test skipped.");
556
557 return;
558 #endif // wxUSE_LONGLONG_NATIVE
559
560 if ( !(nTested % 1000) )
561 {
562 putchar('.');
563 fflush(stdout);
564 }
565
566 nTested++;
567 }
568
569 puts(" done!");
570 }
571
572 static void TestDivision()
573 {
574 puts("*** Testing wxLongLong division ***\n");
575
576 wxLongLong q, r;
577 size_t nTested = 0;
578 for ( size_t n = 0; n < 100000; n++ )
579 {
580 // get a random wxLongLong (shifting by 12 the MSB ensures that the
581 // multiplication will not overflow)
582 wxLongLong ll = MAKE_LL((rand() >> 12), rand(), rand(), rand());
583
584 // get a random long (not wxLongLong for now) to divide it with
585 long l = rand();
586 q = ll / l;
587 r = ll % l;
588
589 #if wxUSE_LONGLONG_NATIVE
590 wxLongLongNative m(ll.GetHi(), ll.GetLo());
591
592 wxLongLongNative p = m / l, s = m % l;
593 wxASSERT_MSG( q == p && r == s, "division failure" );
594 #else // !wxUSE_LONGLONG_NATIVE
595 // verify the result
596 wxASSERT_MSG( ll == q*l + r, "division failure" );
597 #endif // wxUSE_LONGLONG_NATIVE
598
599 if ( !(nTested % 1000) )
600 {
601 putchar('.');
602 fflush(stdout);
603 }
604
605 nTested++;
606 }
607
608 puts(" done!");
609 }
610
611 static void TestAddition()
612 {
613 puts("*** Testing wxLongLong addition ***\n");
614
615 wxLongLong a, b, c;
616 size_t nTested = 0;
617 for ( size_t n = 0; n < 100000; n++ )
618 {
619 a = RAND_LL();
620 b = RAND_LL();
621 c = a + b;
622
623 #if wxUSE_LONGLONG_NATIVE
624 wxASSERT_MSG( c == wxLongLongNative(a.GetHi(), a.GetLo()) +
625 wxLongLongNative(b.GetHi(), b.GetLo()),
626 "addition failure" );
627 #else // !wxUSE_LONGLONG_NATIVE
628 wxASSERT_MSG( c - b == a, "addition failure" );
629 #endif // wxUSE_LONGLONG_NATIVE
630
631 if ( !(nTested % 1000) )
632 {
633 putchar('.');
634 fflush(stdout);
635 }
636
637 nTested++;
638 }
639
640 puts(" done!");
641 }
642
643 static void TestBitOperations()
644 {
645 puts("*** Testing wxLongLong bit operation ***\n");
646
647 wxLongLong a, c;
648 size_t nTested = 0;
649 for ( size_t n = 0; n < 100000; n++ )
650 {
651 a = RAND_LL();
652
653 #if wxUSE_LONGLONG_NATIVE
654 for ( size_t n = 0; n < 33; n++ )
655 {
656 wxLongLongNative b(a.GetHi(), a.GetLo());
657
658 b >>= n;
659 c = a >> n;
660
661 wxASSERT_MSG( b == c, "bit shift failure" );
662
663 b = wxLongLongNative(a.GetHi(), a.GetLo()) << n;
664 c = a << n;
665
666 wxASSERT_MSG( b == c, "bit shift failure" );
667 }
668
669 #else // !wxUSE_LONGLONG_NATIVE
670 puts("Can't do it without native long long type, test skipped.");
671
672 return;
673 #endif // wxUSE_LONGLONG_NATIVE
674
675 if ( !(nTested % 1000) )
676 {
677 putchar('.');
678 fflush(stdout);
679 }
680
681 nTested++;
682 }
683
684 puts(" done!");
685 }
686
687 #undef MAKE_LL
688 #undef RAND_LL
689
690 #endif // TEST_LONGLONG
691
692 // ----------------------------------------------------------------------------
693 // sockets
694 // ----------------------------------------------------------------------------
695
696 #ifdef TEST_SOCKETS
697
698 #include <wx/socket.h>
699
700 static void TestSocketClient()
701 {
702 puts("*** Testing wxSocketClient ***\n");
703
704 wxIPV4address addrDst;
705 addrDst.Hostname("www.wxwindows.org");
706 addrDst.Service(80);
707
708 wxSocketClient client;
709 if ( !client.Connect(addrDst) )
710 {
711 printf("ERROR: failed to connect to %s\n", addrDst.Hostname().c_str());
712 }
713 else
714 {
715 char buf[8192];
716
717 client.Write("get /front.htm\n", 17);
718 client.Read(buf, WXSIZEOF(buf));
719 printf("Server replied:\n%s", buf);
720 }
721 }
722
723 #endif // TEST_SOCKETS
724
725 // ----------------------------------------------------------------------------
726 // timers
727 // ----------------------------------------------------------------------------
728
729 #ifdef TEST_TIMER
730
731 #include <wx/timer.h>
732 #include <wx/utils.h>
733
734 static void TestStopWatch()
735 {
736 puts("*** Testing wxStopWatch ***\n");
737
738 wxStopWatch sw;
739 printf("Sleeping 3 seconds...");
740 wxSleep(3);
741 printf("\telapsed time: %ldms\n", sw.Time());
742
743 sw.Pause();
744 printf("Sleeping 2 more seconds...");
745 wxSleep(2);
746 printf("\telapsed time: %ldms\n", sw.Time());
747
748 sw.Resume();
749 printf("And 3 more seconds...");
750 wxSleep(3);
751 printf("\telapsed time: %ldms\n", sw.Time());
752
753 wxStopWatch sw2;
754 puts("\nChecking for 'backwards clock' bug...");
755 for ( size_t n = 0; n < 70; n++ )
756 {
757 sw2.Start();
758
759 for ( size_t m = 0; m < 100000; m++ )
760 {
761 if ( sw.Time() < 0 || sw2.Time() < 0 )
762 {
763 puts("\ntime is negative - ERROR!");
764 }
765 }
766
767 putchar('.');
768 }
769
770 puts(", ok.");
771 }
772
773 #endif // TEST_TIMER
774
775 // ----------------------------------------------------------------------------
776 // date time
777 // ----------------------------------------------------------------------------
778
779 #ifdef TEST_DATETIME
780
781 #include <wx/date.h>
782
783 #include <wx/datetime.h>
784
785 // the test data
786 struct Date
787 {
788 wxDateTime::wxDateTime_t day;
789 wxDateTime::Month month;
790 int year;
791 wxDateTime::wxDateTime_t hour, min, sec;
792 double jdn;
793 wxDateTime::WeekDay wday;
794 time_t gmticks, ticks;
795
796 void Init(const wxDateTime::Tm& tm)
797 {
798 day = tm.mday;
799 month = tm.mon;
800 year = tm.year;
801 hour = tm.hour;
802 min = tm.min;
803 sec = tm.sec;
804 jdn = 0.0;
805 gmticks = ticks = -1;
806 }
807
808 wxDateTime DT() const
809 { return wxDateTime(day, month, year, hour, min, sec); }
810
811 bool SameDay(const wxDateTime::Tm& tm) const
812 {
813 return day == tm.mday && month == tm.mon && year == tm.year;
814 }
815
816 wxString Format() const
817 {
818 wxString s;
819 s.Printf("%02d:%02d:%02d %10s %02d, %4d%s",
820 hour, min, sec,
821 wxDateTime::GetMonthName(month).c_str(),
822 day,
823 abs(wxDateTime::ConvertYearToBC(year)),
824 year > 0 ? "AD" : "BC");
825 return s;
826 }
827
828 wxString FormatDate() const
829 {
830 wxString s;
831 s.Printf("%02d-%s-%4d%s",
832 day,
833 wxDateTime::GetMonthName(month, wxDateTime::Name_Abbr).c_str(),
834 abs(wxDateTime::ConvertYearToBC(year)),
835 year > 0 ? "AD" : "BC");
836 return s;
837 }
838 };
839
840 static const Date testDates[] =
841 {
842 { 1, wxDateTime::Jan, 1970, 00, 00, 00, 2440587.5, wxDateTime::Thu, 0, -3600 },
843 { 21, wxDateTime::Jan, 2222, 00, 00, 00, 2532648.5, wxDateTime::Mon, -1, -1 },
844 { 29, wxDateTime::May, 1976, 12, 00, 00, 2442928.0, wxDateTime::Sat, 202219200, 202212000 },
845 { 29, wxDateTime::Feb, 1976, 00, 00, 00, 2442837.5, wxDateTime::Sun, 194400000, 194396400 },
846 { 1, wxDateTime::Jan, 1900, 12, 00, 00, 2415021.0, wxDateTime::Mon, -1, -1 },
847 { 1, wxDateTime::Jan, 1900, 00, 00, 00, 2415020.5, wxDateTime::Mon, -1, -1 },
848 { 15, wxDateTime::Oct, 1582, 00, 00, 00, 2299160.5, wxDateTime::Fri, -1, -1 },
849 { 4, wxDateTime::Oct, 1582, 00, 00, 00, 2299149.5, wxDateTime::Mon, -1, -1 },
850 { 1, wxDateTime::Mar, 1, 00, 00, 00, 1721484.5, wxDateTime::Thu, -1, -1 },
851 { 1, wxDateTime::Jan, 1, 00, 00, 00, 1721425.5, wxDateTime::Mon, -1, -1 },
852 { 31, wxDateTime::Dec, 0, 00, 00, 00, 1721424.5, wxDateTime::Sun, -1, -1 },
853 { 1, wxDateTime::Jan, 0, 00, 00, 00, 1721059.5, wxDateTime::Sat, -1, -1 },
854 { 12, wxDateTime::Aug, -1234, 00, 00, 00, 1270573.5, wxDateTime::Fri, -1, -1 },
855 { 12, wxDateTime::Aug, -4000, 00, 00, 00, 260313.5, wxDateTime::Sat, -1, -1 },
856 { 24, wxDateTime::Nov, -4713, 00, 00, 00, -0.5, wxDateTime::Mon, -1, -1 },
857 };
858
859 // this test miscellaneous static wxDateTime functions
860 static void TestTimeStatic()
861 {
862 puts("\n*** wxDateTime static methods test ***");
863
864 // some info about the current date
865 int year = wxDateTime::GetCurrentYear();
866 printf("Current year %d is %sa leap one and has %d days.\n",
867 year,
868 wxDateTime::IsLeapYear(year) ? "" : "not ",
869 wxDateTime::GetNumberOfDays(year));
870
871 wxDateTime::Month month = wxDateTime::GetCurrentMonth();
872 printf("Current month is '%s' ('%s') and it has %d days\n",
873 wxDateTime::GetMonthName(month, wxDateTime::Name_Abbr).c_str(),
874 wxDateTime::GetMonthName(month).c_str(),
875 wxDateTime::GetNumberOfDays(month));
876
877 // leap year logic
878 static const size_t nYears = 5;
879 static const size_t years[2][nYears] =
880 {
881 // first line: the years to test
882 { 1990, 1976, 2000, 2030, 1984, },
883
884 // second line: TRUE if leap, FALSE otherwise
885 { FALSE, TRUE, TRUE, FALSE, TRUE }
886 };
887
888 for ( size_t n = 0; n < nYears; n++ )
889 {
890 int year = years[0][n];
891 bool should = years[1][n] != 0,
892 is = wxDateTime::IsLeapYear(year);
893
894 printf("Year %d is %sa leap year (%s)\n",
895 year,
896 is ? "" : "not ",
897 should == is ? "ok" : "ERROR");
898
899 wxASSERT( should == wxDateTime::IsLeapYear(year) );
900 }
901 }
902
903 // test constructing wxDateTime objects
904 static void TestTimeSet()
905 {
906 puts("\n*** wxDateTime construction test ***");
907
908 for ( size_t n = 0; n < WXSIZEOF(testDates); n++ )
909 {
910 const Date& d1 = testDates[n];
911 wxDateTime dt = d1.DT();
912
913 Date d2;
914 d2.Init(dt.GetTm());
915
916 wxString s1 = d1.Format(),
917 s2 = d2.Format();
918
919 printf("Date: %s == %s (%s)\n",
920 s1.c_str(), s2.c_str(),
921 s1 == s2 ? "ok" : "ERROR");
922 }
923 }
924
925 // test time zones stuff
926 static void TestTimeZones()
927 {
928 puts("\n*** wxDateTime timezone test ***");
929
930 wxDateTime now = wxDateTime::Now();
931
932 printf("Current GMT time:\t%s\n", now.Format("%c", wxDateTime::GMT0).c_str());
933 printf("Unix epoch (GMT):\t%s\n", wxDateTime((time_t)0).Format("%c", wxDateTime::GMT0).c_str());
934 printf("Unix epoch (EST):\t%s\n", wxDateTime((time_t)0).Format("%c", wxDateTime::EST).c_str());
935 printf("Current time in Paris:\t%s\n", now.Format("%c", wxDateTime::CET).c_str());
936 printf(" Moscow:\t%s\n", now.Format("%c", wxDateTime::MSK).c_str());
937 printf(" New York:\t%s\n", now.Format("%c", wxDateTime::EST).c_str());
938
939 wxDateTime::Tm tm = now.GetTm();
940 if ( wxDateTime(tm) != now )
941 {
942 printf("ERROR: got %s instead of %s\n",
943 wxDateTime(tm).Format().c_str(), now.Format().c_str());
944 }
945 }
946
947 // test some minimal support for the dates outside the standard range
948 static void TestTimeRange()
949 {
950 puts("\n*** wxDateTime out-of-standard-range dates test ***");
951
952 static const char *fmt = "%d-%b-%Y %H:%M:%S";
953
954 printf("Unix epoch:\t%s\n",
955 wxDateTime(2440587.5).Format(fmt).c_str());
956 printf("Feb 29, 0: \t%s\n",
957 wxDateTime(29, wxDateTime::Feb, 0).Format(fmt).c_str());
958 printf("JDN 0: \t%s\n",
959 wxDateTime(0.0).Format(fmt).c_str());
960 printf("Jan 1, 1AD:\t%s\n",
961 wxDateTime(1, wxDateTime::Jan, 1).Format(fmt).c_str());
962 printf("May 29, 2099:\t%s\n",
963 wxDateTime(29, wxDateTime::May, 2099).Format(fmt).c_str());
964 }
965
966 static void TestTimeTicks()
967 {
968 puts("\n*** wxDateTime ticks test ***");
969
970 for ( size_t n = 0; n < WXSIZEOF(testDates); n++ )
971 {
972 const Date& d = testDates[n];
973 if ( d.ticks == -1 )
974 continue;
975
976 wxDateTime dt = d.DT();
977 long ticks = (dt.GetValue() / 1000).ToLong();
978 printf("Ticks of %s:\t% 10ld", d.Format().c_str(), ticks);
979 if ( ticks == d.ticks )
980 {
981 puts(" (ok)");
982 }
983 else
984 {
985 printf(" (ERROR: should be %ld, delta = %ld)\n",
986 d.ticks, ticks - d.ticks);
987 }
988
989 dt = d.DT().ToTimezone(wxDateTime::GMT0);
990 ticks = (dt.GetValue() / 1000).ToLong();
991 printf("GMtks of %s:\t% 10ld", d.Format().c_str(), ticks);
992 if ( ticks == d.gmticks )
993 {
994 puts(" (ok)");
995 }
996 else
997 {
998 printf(" (ERROR: should be %ld, delta = %ld)\n",
999 d.gmticks, ticks - d.gmticks);
1000 }
1001 }
1002
1003 puts("");
1004 }
1005
1006 // test conversions to JDN &c
1007 static void TestTimeJDN()
1008 {
1009 puts("\n*** wxDateTime to JDN test ***");
1010
1011 for ( size_t n = 0; n < WXSIZEOF(testDates); n++ )
1012 {
1013 const Date& d = testDates[n];
1014 wxDateTime dt(d.day, d.month, d.year, d.hour, d.min, d.sec);
1015 double jdn = dt.GetJulianDayNumber();
1016
1017 printf("JDN of %s is:\t% 15.6f", d.Format().c_str(), jdn);
1018 if ( jdn == d.jdn )
1019 {
1020 puts(" (ok)");
1021 }
1022 else
1023 {
1024 printf(" (ERROR: should be %f, delta = %f)\n",
1025 d.jdn, jdn - d.jdn);
1026 }
1027 }
1028 }
1029
1030 // test week days computation
1031 static void TestTimeWDays()
1032 {
1033 puts("\n*** wxDateTime weekday test ***");
1034
1035 // test GetWeekDay()
1036 size_t n;
1037 for ( n = 0; n < WXSIZEOF(testDates); n++ )
1038 {
1039 const Date& d = testDates[n];
1040 wxDateTime dt(d.day, d.month, d.year, d.hour, d.min, d.sec);
1041
1042 wxDateTime::WeekDay wday = dt.GetWeekDay();
1043 printf("%s is: %s",
1044 d.Format().c_str(),
1045 wxDateTime::GetWeekDayName(wday).c_str());
1046 if ( wday == d.wday )
1047 {
1048 puts(" (ok)");
1049 }
1050 else
1051 {
1052 printf(" (ERROR: should be %s)\n",
1053 wxDateTime::GetWeekDayName(d.wday).c_str());
1054 }
1055 }
1056
1057 puts("");
1058
1059 // test SetToWeekDay()
1060 struct WeekDateTestData
1061 {
1062 Date date; // the real date (precomputed)
1063 int nWeek; // its week index in the month
1064 wxDateTime::WeekDay wday; // the weekday
1065 wxDateTime::Month month; // the month
1066 int year; // and the year
1067
1068 wxString Format() const
1069 {
1070 wxString s, which;
1071 switch ( nWeek < -1 ? -nWeek : nWeek )
1072 {
1073 case 1: which = "first"; break;
1074 case 2: which = "second"; break;
1075 case 3: which = "third"; break;
1076 case 4: which = "fourth"; break;
1077 case 5: which = "fifth"; break;
1078
1079 case -1: which = "last"; break;
1080 }
1081
1082 if ( nWeek < -1 )
1083 {
1084 which += " from end";
1085 }
1086
1087 s.Printf("The %s %s of %s in %d",
1088 which.c_str(),
1089 wxDateTime::GetWeekDayName(wday).c_str(),
1090 wxDateTime::GetMonthName(month).c_str(),
1091 year);
1092
1093 return s;
1094 }
1095 };
1096
1097 // the array data was generated by the following python program
1098 /*
1099 from DateTime import *
1100 from whrandom import *
1101 from string import *
1102
1103 monthNames = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
1104 wdayNames = [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' ]
1105
1106 week = DateTimeDelta(7)
1107
1108 for n in range(20):
1109 year = randint(1900, 2100)
1110 month = randint(1, 12)
1111 day = randint(1, 28)
1112 dt = DateTime(year, month, day)
1113 wday = dt.day_of_week
1114
1115 countFromEnd = choice([-1, 1])
1116 weekNum = 0;
1117
1118 while dt.month is month:
1119 dt = dt - countFromEnd * week
1120 weekNum = weekNum + countFromEnd
1121
1122 data = { 'day': rjust(`day`, 2), 'month': monthNames[month - 1], 'year': year, 'weekNum': rjust(`weekNum`, 2), 'wday': wdayNames[wday] }
1123
1124 print "{ { %(day)s, wxDateTime::%(month)s, %(year)d }, %(weekNum)d, "\
1125 "wxDateTime::%(wday)s, wxDateTime::%(month)s, %(year)d }," % data
1126 */
1127
1128 static const WeekDateTestData weekDatesTestData[] =
1129 {
1130 { { 20, wxDateTime::Mar, 2045 }, 3, wxDateTime::Mon, wxDateTime::Mar, 2045 },
1131 { { 5, wxDateTime::Jun, 1985 }, -4, wxDateTime::Wed, wxDateTime::Jun, 1985 },
1132 { { 12, wxDateTime::Nov, 1961 }, -3, wxDateTime::Sun, wxDateTime::Nov, 1961 },
1133 { { 27, wxDateTime::Feb, 2093 }, -1, wxDateTime::Fri, wxDateTime::Feb, 2093 },
1134 { { 4, wxDateTime::Jul, 2070 }, -4, wxDateTime::Fri, wxDateTime::Jul, 2070 },
1135 { { 2, wxDateTime::Apr, 1906 }, -5, wxDateTime::Mon, wxDateTime::Apr, 1906 },
1136 { { 19, wxDateTime::Jul, 2023 }, -2, wxDateTime::Wed, wxDateTime::Jul, 2023 },
1137 { { 5, wxDateTime::May, 1958 }, -4, wxDateTime::Mon, wxDateTime::May, 1958 },
1138 { { 11, wxDateTime::Aug, 1900 }, 2, wxDateTime::Sat, wxDateTime::Aug, 1900 },
1139 { { 14, wxDateTime::Feb, 1945 }, 2, wxDateTime::Wed, wxDateTime::Feb, 1945 },
1140 { { 25, wxDateTime::Jul, 1967 }, -1, wxDateTime::Tue, wxDateTime::Jul, 1967 },
1141 { { 9, wxDateTime::May, 1916 }, -4, wxDateTime::Tue, wxDateTime::May, 1916 },
1142 { { 20, wxDateTime::Jun, 1927 }, 3, wxDateTime::Mon, wxDateTime::Jun, 1927 },
1143 { { 2, wxDateTime::Aug, 2000 }, 1, wxDateTime::Wed, wxDateTime::Aug, 2000 },
1144 { { 20, wxDateTime::Apr, 2044 }, 3, wxDateTime::Wed, wxDateTime::Apr, 2044 },
1145 { { 20, wxDateTime::Feb, 1932 }, -2, wxDateTime::Sat, wxDateTime::Feb, 1932 },
1146 { { 25, wxDateTime::Jul, 2069 }, 4, wxDateTime::Thu, wxDateTime::Jul, 2069 },
1147 { { 3, wxDateTime::Apr, 1925 }, 1, wxDateTime::Fri, wxDateTime::Apr, 1925 },
1148 { { 21, wxDateTime::Mar, 2093 }, 3, wxDateTime::Sat, wxDateTime::Mar, 2093 },
1149 { { 3, wxDateTime::Dec, 2074 }, -5, wxDateTime::Mon, wxDateTime::Dec, 2074 },
1150 };
1151
1152 static const char *fmt = "%d-%b-%Y";
1153
1154 wxDateTime dt;
1155 for ( n = 0; n < WXSIZEOF(weekDatesTestData); n++ )
1156 {
1157 const WeekDateTestData& wd = weekDatesTestData[n];
1158
1159 dt.SetToWeekDay(wd.wday, wd.nWeek, wd.month, wd.year);
1160
1161 printf("%s is %s", wd.Format().c_str(), dt.Format(fmt).c_str());
1162
1163 const Date& d = wd.date;
1164 if ( d.SameDay(dt.GetTm()) )
1165 {
1166 puts(" (ok)");
1167 }
1168 else
1169 {
1170 dt.Set(d.day, d.month, d.year);
1171
1172 printf(" (ERROR: should be %s)\n", dt.Format(fmt).c_str());
1173 }
1174 }
1175 }
1176
1177 // test the computation of (ISO) week numbers
1178 static void TestTimeWNumber()
1179 {
1180 puts("\n*** wxDateTime week number test ***");
1181
1182 struct WeekNumberTestData
1183 {
1184 Date date; // the date
1185 wxDateTime::wxDateTime_t week; // the week number in the year
1186 wxDateTime::wxDateTime_t wmon; // the week number in the month
1187 wxDateTime::wxDateTime_t wmon2; // same but week starts with Sun
1188 wxDateTime::wxDateTime_t dnum; // day number in the year
1189 };
1190
1191 // data generated with the following python script:
1192 /*
1193 from DateTime import *
1194 from whrandom import *
1195 from string import *
1196
1197 monthNames = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
1198 wdayNames = [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' ]
1199
1200 def GetMonthWeek(dt):
1201 weekNumMonth = dt.iso_week[1] - DateTime(dt.year, dt.month, 1).iso_week[1] + 1
1202 if weekNumMonth < 0:
1203 weekNumMonth = weekNumMonth + 53
1204 return weekNumMonth
1205
1206 def GetLastSundayBefore(dt):
1207 if dt.iso_week[2] == 7:
1208 return dt
1209 else:
1210 return dt - DateTimeDelta(dt.iso_week[2])
1211
1212 for n in range(20):
1213 year = randint(1900, 2100)
1214 month = randint(1, 12)
1215 day = randint(1, 28)
1216 dt = DateTime(year, month, day)
1217 dayNum = dt.day_of_year
1218 weekNum = dt.iso_week[1]
1219 weekNumMonth = GetMonthWeek(dt)
1220
1221 weekNumMonth2 = 0
1222 dtSunday = GetLastSundayBefore(dt)
1223
1224 while dtSunday >= GetLastSundayBefore(DateTime(dt.year, dt.month, 1)):
1225 weekNumMonth2 = weekNumMonth2 + 1
1226 dtSunday = dtSunday - DateTimeDelta(7)
1227
1228 data = { 'day': rjust(`day`, 2), \
1229 'month': monthNames[month - 1], \
1230 'year': year, \
1231 'weekNum': rjust(`weekNum`, 2), \
1232 'weekNumMonth': weekNumMonth, \
1233 'weekNumMonth2': weekNumMonth2, \
1234 'dayNum': rjust(`dayNum`, 3) }
1235
1236 print " { { %(day)s, "\
1237 "wxDateTime::%(month)s, "\
1238 "%(year)d }, "\
1239 "%(weekNum)s, "\
1240 "%(weekNumMonth)s, "\
1241 "%(weekNumMonth2)s, "\
1242 "%(dayNum)s }," % data
1243
1244 */
1245 static const WeekNumberTestData weekNumberTestDates[] =
1246 {
1247 { { 27, wxDateTime::Dec, 1966 }, 52, 5, 5, 361 },
1248 { { 22, wxDateTime::Jul, 1926 }, 29, 4, 4, 203 },
1249 { { 22, wxDateTime::Oct, 2076 }, 43, 4, 4, 296 },
1250 { { 1, wxDateTime::Jul, 1967 }, 26, 1, 1, 182 },
1251 { { 8, wxDateTime::Nov, 2004 }, 46, 2, 2, 313 },
1252 { { 21, wxDateTime::Mar, 1920 }, 12, 3, 4, 81 },
1253 { { 7, wxDateTime::Jan, 1965 }, 1, 2, 2, 7 },
1254 { { 19, wxDateTime::Oct, 1999 }, 42, 4, 4, 292 },
1255 { { 13, wxDateTime::Aug, 1955 }, 32, 2, 2, 225 },
1256 { { 18, wxDateTime::Jul, 2087 }, 29, 3, 3, 199 },
1257 { { 2, wxDateTime::Sep, 2028 }, 35, 1, 1, 246 },
1258 { { 28, wxDateTime::Jul, 1945 }, 30, 5, 4, 209 },
1259 { { 15, wxDateTime::Jun, 1901 }, 24, 3, 3, 166 },
1260 { { 10, wxDateTime::Oct, 1939 }, 41, 3, 2, 283 },
1261 { { 3, wxDateTime::Dec, 1965 }, 48, 1, 1, 337 },
1262 { { 23, wxDateTime::Feb, 1940 }, 8, 4, 4, 54 },
1263 { { 2, wxDateTime::Jan, 1987 }, 1, 1, 1, 2 },
1264 { { 11, wxDateTime::Aug, 2079 }, 32, 2, 2, 223 },
1265 { { 2, wxDateTime::Feb, 2063 }, 5, 1, 1, 33 },
1266 { { 16, wxDateTime::Oct, 1942 }, 42, 3, 3, 289 },
1267 };
1268
1269 for ( size_t n = 0; n < WXSIZEOF(weekNumberTestDates); n++ )
1270 {
1271 const WeekNumberTestData& wn = weekNumberTestDates[n];
1272 const Date& d = wn.date;
1273
1274 wxDateTime dt = d.DT();
1275
1276 wxDateTime::wxDateTime_t
1277 week = dt.GetWeekOfYear(wxDateTime::Monday_First),
1278 wmon = dt.GetWeekOfMonth(wxDateTime::Monday_First),
1279 wmon2 = dt.GetWeekOfMonth(wxDateTime::Sunday_First),
1280 dnum = dt.GetDayOfYear();
1281
1282 printf("%s: the day number is %d",
1283 d.FormatDate().c_str(), dnum);
1284 if ( dnum == wn.dnum )
1285 {
1286 printf(" (ok)");
1287 }
1288 else
1289 {
1290 printf(" (ERROR: should be %d)", wn.dnum);
1291 }
1292
1293 printf(", week in month is %d", wmon);
1294 if ( wmon == wn.wmon )
1295 {
1296 printf(" (ok)");
1297 }
1298 else
1299 {
1300 printf(" (ERROR: should be %d)", wn.wmon);
1301 }
1302
1303 printf(" or %d", wmon2);
1304 if ( wmon2 == wn.wmon2 )
1305 {
1306 printf(" (ok)");
1307 }
1308 else
1309 {
1310 printf(" (ERROR: should be %d)", wn.wmon2);
1311 }
1312
1313 printf(", week in year is %d", week);
1314 if ( week == wn.week )
1315 {
1316 puts(" (ok)");
1317 }
1318 else
1319 {
1320 printf(" (ERROR: should be %d)\n", wn.week);
1321 }
1322 }
1323 }
1324
1325 // test DST calculations
1326 static void TestTimeDST()
1327 {
1328 puts("\n*** wxDateTime DST test ***");
1329
1330 printf("DST is%s in effect now.\n\n",
1331 wxDateTime::Now().IsDST() ? "" : " not");
1332
1333 // taken from http://www.energy.ca.gov/daylightsaving.html
1334 static const Date datesDST[2][2004 - 1900 + 1] =
1335 {
1336 {
1337 { 1, wxDateTime::Apr, 1990 },
1338 { 7, wxDateTime::Apr, 1991 },
1339 { 5, wxDateTime::Apr, 1992 },
1340 { 4, wxDateTime::Apr, 1993 },
1341 { 3, wxDateTime::Apr, 1994 },
1342 { 2, wxDateTime::Apr, 1995 },
1343 { 7, wxDateTime::Apr, 1996 },
1344 { 6, wxDateTime::Apr, 1997 },
1345 { 5, wxDateTime::Apr, 1998 },
1346 { 4, wxDateTime::Apr, 1999 },
1347 { 2, wxDateTime::Apr, 2000 },
1348 { 1, wxDateTime::Apr, 2001 },
1349 { 7, wxDateTime::Apr, 2002 },
1350 { 6, wxDateTime::Apr, 2003 },
1351 { 4, wxDateTime::Apr, 2004 },
1352 },
1353 {
1354 { 28, wxDateTime::Oct, 1990 },
1355 { 27, wxDateTime::Oct, 1991 },
1356 { 25, wxDateTime::Oct, 1992 },
1357 { 31, wxDateTime::Oct, 1993 },
1358 { 30, wxDateTime::Oct, 1994 },
1359 { 29, wxDateTime::Oct, 1995 },
1360 { 27, wxDateTime::Oct, 1996 },
1361 { 26, wxDateTime::Oct, 1997 },
1362 { 25, wxDateTime::Oct, 1998 },
1363 { 31, wxDateTime::Oct, 1999 },
1364 { 29, wxDateTime::Oct, 2000 },
1365 { 28, wxDateTime::Oct, 2001 },
1366 { 27, wxDateTime::Oct, 2002 },
1367 { 26, wxDateTime::Oct, 2003 },
1368 { 31, wxDateTime::Oct, 2004 },
1369 }
1370 };
1371
1372 int year;
1373 for ( year = 1990; year < 2005; year++ )
1374 {
1375 wxDateTime dtBegin = wxDateTime::GetBeginDST(year, wxDateTime::USA),
1376 dtEnd = wxDateTime::GetEndDST(year, wxDateTime::USA);
1377
1378 printf("DST period in the US for year %d: from %s to %s",
1379 year, dtBegin.Format().c_str(), dtEnd.Format().c_str());
1380
1381 size_t n = year - 1990;
1382 const Date& dBegin = datesDST[0][n];
1383 const Date& dEnd = datesDST[1][n];
1384
1385 if ( dBegin.SameDay(dtBegin.GetTm()) && dEnd.SameDay(dtEnd.GetTm()) )
1386 {
1387 puts(" (ok)");
1388 }
1389 else
1390 {
1391 printf(" (ERROR: should be %s %d to %s %d)\n",
1392 wxDateTime::GetMonthName(dBegin.month).c_str(), dBegin.day,
1393 wxDateTime::GetMonthName(dEnd.month).c_str(), dEnd.day);
1394 }
1395 }
1396
1397 puts("");
1398
1399 for ( year = 1990; year < 2005; year++ )
1400 {
1401 printf("DST period in Europe for year %d: from %s to %s\n",
1402 year,
1403 wxDateTime::GetBeginDST(year, wxDateTime::Country_EEC).Format().c_str(),
1404 wxDateTime::GetEndDST(year, wxDateTime::Country_EEC).Format().c_str());
1405 }
1406 }
1407
1408 // test wxDateTime -> text conversion
1409 static void TestTimeFormat()
1410 {
1411 puts("\n*** wxDateTime formatting test ***");
1412
1413 // some information may be lost during conversion, so store what kind
1414 // of info should we recover after a round trip
1415 enum CompareKind
1416 {
1417 CompareNone, // don't try comparing
1418 CompareBoth, // dates and times should be identical
1419 CompareDate, // dates only
1420 CompareTime // time only
1421 };
1422
1423 static const struct
1424 {
1425 CompareKind compareKind;
1426 const char *format;
1427 } formatTestFormats[] =
1428 {
1429 { CompareBoth, "---> %c" },
1430 { CompareDate, "Date is %A, %d of %B, in year %Y" },
1431 { CompareBoth, "Date is %x, time is %X" },
1432 { CompareTime, "Time is %H:%M:%S or %I:%M:%S %p" },
1433 { CompareNone, "The day of year: %j, the week of year: %W" },
1434 };
1435
1436 static const Date formatTestDates[] =
1437 {
1438 { 29, wxDateTime::May, 1976, 18, 30, 00 },
1439 { 31, wxDateTime::Dec, 1999, 23, 30, 00 },
1440 #if 0
1441 // this test can't work for other centuries because it uses two digit
1442 // years in formats, so don't even try it
1443 { 29, wxDateTime::May, 2076, 18, 30, 00 },
1444 { 29, wxDateTime::Feb, 2400, 02, 15, 25 },
1445 { 01, wxDateTime::Jan, -52, 03, 16, 47 },
1446 #endif
1447 };
1448
1449 // an extra test (as it doesn't depend on date, don't do it in the loop)
1450 printf("%s\n", wxDateTime::Now().Format("Our timezone is %Z").c_str());
1451
1452 for ( size_t d = 0; d < WXSIZEOF(formatTestDates) + 1; d++ )
1453 {
1454 puts("");
1455
1456 wxDateTime dt = d == 0 ? wxDateTime::Now() : formatTestDates[d - 1].DT();
1457 for ( size_t n = 0; n < WXSIZEOF(formatTestFormats); n++ )
1458 {
1459 wxString s = dt.Format(formatTestFormats[n].format);
1460 printf("%s", s.c_str());
1461
1462 // what can we recover?
1463 int kind = formatTestFormats[n].compareKind;
1464
1465 // convert back
1466 wxDateTime dt2;
1467 const wxChar *result = dt2.ParseFormat(s, formatTestFormats[n].format);
1468 if ( !result )
1469 {
1470 // converion failed - should it have?
1471 if ( kind == CompareNone )
1472 puts(" (ok)");
1473 else
1474 puts(" (ERROR: conversion back failed)");
1475 }
1476 else if ( *result )
1477 {
1478 // should have parsed the entire string
1479 puts(" (ERROR: conversion back stopped too soon)");
1480 }
1481 else
1482 {
1483 bool equal = FALSE; // suppress compilaer warning
1484 switch ( kind )
1485 {
1486 case CompareBoth:
1487 equal = dt2 == dt;
1488 break;
1489
1490 case CompareDate:
1491 equal = dt.IsSameDate(dt2);
1492 break;
1493
1494 case CompareTime:
1495 equal = dt.IsSameTime(dt2);
1496 break;
1497 }
1498
1499 if ( !equal )
1500 {
1501 printf(" (ERROR: got back '%s' instead of '%s')\n",
1502 dt2.Format().c_str(), dt.Format().c_str());
1503 }
1504 else
1505 {
1506 puts(" (ok)");
1507 }
1508 }
1509 }
1510 }
1511 }
1512
1513 // test text -> wxDateTime conversion
1514 static void TestTimeParse()
1515 {
1516 puts("\n*** wxDateTime parse test ***");
1517
1518 struct ParseTestData
1519 {
1520 const char *format;
1521 Date date;
1522 bool good;
1523 };
1524
1525 static const ParseTestData parseTestDates[] =
1526 {
1527 { "Sat, 18 Dec 1999 00:46:40 +0100", { 18, wxDateTime::Dec, 1999, 00, 46, 40 }, TRUE },
1528 { "Wed, 1 Dec 1999 05:17:20 +0300", { 1, wxDateTime::Dec, 1999, 03, 17, 20 }, TRUE },
1529 };
1530
1531 for ( size_t n = 0; n < WXSIZEOF(parseTestDates); n++ )
1532 {
1533 const char *format = parseTestDates[n].format;
1534
1535 printf("%s => ", format);
1536
1537 wxDateTime dt;
1538 if ( dt.ParseRfc822Date(format) )
1539 {
1540 printf("%s ", dt.Format().c_str());
1541
1542 if ( parseTestDates[n].good )
1543 {
1544 wxDateTime dtReal = parseTestDates[n].date.DT();
1545 if ( dt == dtReal )
1546 {
1547 puts("(ok)");
1548 }
1549 else
1550 {
1551 printf("(ERROR: should be %s)\n", dtReal.Format().c_str());
1552 }
1553 }
1554 else
1555 {
1556 puts("(ERROR: bad format)");
1557 }
1558 }
1559 else
1560 {
1561 printf("bad format (%s)\n",
1562 parseTestDates[n].good ? "ERROR" : "ok");
1563 }
1564 }
1565 }
1566
1567 static void TestInteractive()
1568 {
1569 puts("\n*** interactive wxDateTime tests ***");
1570
1571 char buf[128];
1572
1573 for ( ;; )
1574 {
1575 printf("Enter a date: ");
1576 if ( !fgets(buf, WXSIZEOF(buf), stdin) )
1577 break;
1578
1579 wxDateTime dt;
1580 if ( !dt.ParseDate(buf) )
1581 {
1582 puts("failed to parse the date");
1583
1584 continue;
1585 }
1586
1587 printf("%s: day %u, week of month %u/%u, week of year %u\n",
1588 dt.FormatISODate().c_str(),
1589 dt.GetDayOfYear(),
1590 dt.GetWeekOfMonth(wxDateTime::Monday_First),
1591 dt.GetWeekOfMonth(wxDateTime::Sunday_First),
1592 dt.GetWeekOfYear(wxDateTime::Monday_First));
1593 }
1594
1595 puts("\n*** done ***");
1596 }
1597
1598 static void TestTimeArithmetics()
1599 {
1600 puts("\n*** testing arithmetic operations on wxDateTime ***");
1601
1602 static const struct
1603 {
1604 wxDateSpan span;
1605 const char *name;
1606 } testArithmData[] =
1607 {
1608 { wxDateSpan::Day(), "day" },
1609 { wxDateSpan::Week(), "week" },
1610 { wxDateSpan::Month(), "month" },
1611 { wxDateSpan::Year(), "year" },
1612 { wxDateSpan(1, 2, 3, 4), "year, 2 months, 3 weeks, 4 days" },
1613 };
1614
1615 wxDateTime dt(29, wxDateTime::Dec, 1999), dt1, dt2;
1616
1617 for ( size_t n = 0; n < WXSIZEOF(testArithmData); n++ )
1618 {
1619 wxDateSpan span = testArithmData[n].span;
1620 dt1 = dt + span;
1621 dt2 = dt - span;
1622
1623 const char *name = testArithmData[n].name;
1624 printf("%s + %s = %s, %s - %s = %s\n",
1625 dt.FormatISODate().c_str(), name, dt1.FormatISODate().c_str(),
1626 dt.FormatISODate().c_str(), name, dt2.FormatISODate().c_str());
1627
1628 printf("Going back: %s", (dt1 - span).FormatISODate().c_str());
1629 if ( dt1 - span == dt )
1630 {
1631 puts(" (ok)");
1632 }
1633 else
1634 {
1635 printf(" (ERROR: should be %s)\n", dt.FormatISODate().c_str());
1636 }
1637
1638 printf("Going forward: %s", (dt2 + span).FormatISODate().c_str());
1639 if ( dt2 + span == dt )
1640 {
1641 puts(" (ok)");
1642 }
1643 else
1644 {
1645 printf(" (ERROR: should be %s)\n", dt.FormatISODate().c_str());
1646 }
1647
1648 printf("Double increment: %s", (dt2 + 2*span).FormatISODate().c_str());
1649 if ( dt2 + 2*span == dt1 )
1650 {
1651 puts(" (ok)");
1652 }
1653 else
1654 {
1655 printf(" (ERROR: should be %s)\n", dt2.FormatISODate().c_str());
1656 }
1657
1658 puts("");
1659 }
1660 }
1661
1662 static void TestTimeHolidays()
1663 {
1664 puts("\n*** testing wxDateTimeHolidayAuthority ***\n");
1665
1666 wxDateTime::Tm tm = wxDateTime(29, wxDateTime::May, 2000).GetTm();
1667 wxDateTime dtStart(1, tm.mon, tm.year),
1668 dtEnd = dtStart.GetLastMonthDay();
1669
1670 wxDateTimeArray hol;
1671 wxDateTimeHolidayAuthority::GetHolidaysInRange(dtStart, dtEnd, hol);
1672
1673 const wxChar *format = "%d-%b-%Y (%a)";
1674
1675 printf("All holidays between %s and %s:\n",
1676 dtStart.Format(format).c_str(), dtEnd.Format(format).c_str());
1677
1678 size_t count = hol.GetCount();
1679 for ( size_t n = 0; n < count; n++ )
1680 {
1681 printf("\t%s\n", hol[n].Format(format).c_str());
1682 }
1683
1684 puts("");
1685 }
1686
1687 #if 0
1688
1689 // test compatibility with the old wxDate/wxTime classes
1690 static void TestTimeCompatibility()
1691 {
1692 puts("\n*** wxDateTime compatibility test ***");
1693
1694 printf("wxDate for JDN 0: %s\n", wxDate(0l).FormatDate().c_str());
1695 printf("wxDate for MJD 0: %s\n", wxDate(2400000).FormatDate().c_str());
1696
1697 double jdnNow = wxDateTime::Now().GetJDN();
1698 long jdnMidnight = (long)(jdnNow - 0.5);
1699 printf("wxDate for today: %s\n", wxDate(jdnMidnight).FormatDate().c_str());
1700
1701 jdnMidnight = wxDate().Set().GetJulianDate();
1702 printf("wxDateTime for today: %s\n",
1703 wxDateTime((double)(jdnMidnight + 0.5)).Format("%c", wxDateTime::GMT0).c_str());
1704
1705 int flags = wxEUROPEAN;//wxFULL;
1706 wxDate date;
1707 date.Set();
1708 printf("Today is %s\n", date.FormatDate(flags).c_str());
1709 for ( int n = 0; n < 7; n++ )
1710 {
1711 printf("Previous %s is %s\n",
1712 wxDateTime::GetWeekDayName((wxDateTime::WeekDay)n),
1713 date.Previous(n + 1).FormatDate(flags).c_str());
1714 }
1715 }
1716
1717 #endif // 0
1718
1719 #endif // TEST_DATETIME
1720
1721 // ----------------------------------------------------------------------------
1722 // threads
1723 // ----------------------------------------------------------------------------
1724
1725 #ifdef TEST_THREADS
1726
1727 #include <wx/thread.h>
1728
1729 static size_t gs_counter = (size_t)-1;
1730 static wxCriticalSection gs_critsect;
1731 static wxCondition gs_cond;
1732
1733 class MyJoinableThread : public wxThread
1734 {
1735 public:
1736 MyJoinableThread(size_t n) : wxThread(wxTHREAD_JOINABLE)
1737 { m_n = n; Create(); }
1738
1739 // thread execution starts here
1740 virtual ExitCode Entry();
1741
1742 private:
1743 size_t m_n;
1744 };
1745
1746 wxThread::ExitCode MyJoinableThread::Entry()
1747 {
1748 unsigned long res = 1;
1749 for ( size_t n = 1; n < m_n; n++ )
1750 {
1751 res *= n;
1752
1753 // it's a loooong calculation :-)
1754 Sleep(100);
1755 }
1756
1757 return (ExitCode)res;
1758 }
1759
1760 class MyDetachedThread : public wxThread
1761 {
1762 public:
1763 MyDetachedThread(size_t n, char ch)
1764 {
1765 m_n = n;
1766 m_ch = ch;
1767 m_cancelled = FALSE;
1768
1769 Create();
1770 }
1771
1772 // thread execution starts here
1773 virtual ExitCode Entry();
1774
1775 // and stops here
1776 virtual void OnExit();
1777
1778 private:
1779 size_t m_n; // number of characters to write
1780 char m_ch; // character to write
1781
1782 bool m_cancelled; // FALSE if we exit normally
1783 };
1784
1785 wxThread::ExitCode MyDetachedThread::Entry()
1786 {
1787 {
1788 wxCriticalSectionLocker lock(gs_critsect);
1789 if ( gs_counter == (size_t)-1 )
1790 gs_counter = 1;
1791 else
1792 gs_counter++;
1793 }
1794
1795 for ( size_t n = 0; n < m_n; n++ )
1796 {
1797 if ( TestDestroy() )
1798 {
1799 m_cancelled = TRUE;
1800
1801 break;
1802 }
1803
1804 putchar(m_ch);
1805 fflush(stdout);
1806
1807 wxThread::Sleep(100);
1808 }
1809
1810 return 0;
1811 }
1812
1813 void MyDetachedThread::OnExit()
1814 {
1815 wxLogTrace("thread", "Thread %ld is in OnExit", GetId());
1816
1817 wxCriticalSectionLocker lock(gs_critsect);
1818 if ( !--gs_counter && !m_cancelled )
1819 gs_cond.Signal();
1820 }
1821
1822 void TestDetachedThreads()
1823 {
1824 puts("\n*** Testing detached threads ***");
1825
1826 static const size_t nThreads = 3;
1827 MyDetachedThread *threads[nThreads];
1828 size_t n;
1829 for ( n = 0; n < nThreads; n++ )
1830 {
1831 threads[n] = new MyDetachedThread(10, 'A' + n);
1832 }
1833
1834 threads[0]->SetPriority(WXTHREAD_MIN_PRIORITY);
1835 threads[1]->SetPriority(WXTHREAD_MAX_PRIORITY);
1836
1837 for ( n = 0; n < nThreads; n++ )
1838 {
1839 threads[n]->Run();
1840 }
1841
1842 // wait until all threads terminate
1843 gs_cond.Wait();
1844
1845 puts("");
1846 }
1847
1848 void TestJoinableThreads()
1849 {
1850 puts("\n*** Testing a joinable thread (a loooong calculation...) ***");
1851
1852 // calc 10! in the background
1853 MyJoinableThread thread(10);
1854 thread.Run();
1855
1856 printf("\nThread terminated with exit code %lu.\n",
1857 (unsigned long)thread.Wait());
1858 }
1859
1860 void TestThreadSuspend()
1861 {
1862 puts("\n*** Testing thread suspend/resume functions ***");
1863
1864 MyDetachedThread *thread = new MyDetachedThread(15, 'X');
1865
1866 thread->Run();
1867
1868 // this is for this demo only, in a real life program we'd use another
1869 // condition variable which would be signaled from wxThread::Entry() to
1870 // tell us that the thread really started running - but here just wait a
1871 // bit and hope that it will be enough (the problem is, of course, that
1872 // the thread might still not run when we call Pause() which will result
1873 // in an error)
1874 wxThread::Sleep(300);
1875
1876 for ( size_t n = 0; n < 3; n++ )
1877 {
1878 thread->Pause();
1879
1880 puts("\nThread suspended");
1881 if ( n > 0 )
1882 {
1883 // don't sleep but resume immediately the first time
1884 wxThread::Sleep(300);
1885 }
1886 puts("Going to resume the thread");
1887
1888 thread->Resume();
1889 }
1890
1891 puts("Waiting until it terminates now");
1892
1893 // wait until the thread terminates
1894 gs_cond.Wait();
1895
1896 puts("");
1897 }
1898
1899 void TestThreadDelete()
1900 {
1901 // As above, using Sleep() is only for testing here - we must use some
1902 // synchronisation object instead to ensure that the thread is still
1903 // running when we delete it - deleting a detached thread which already
1904 // terminated will lead to a crash!
1905
1906 puts("\n*** Testing thread delete function ***");
1907
1908 MyDetachedThread *thread0 = new MyDetachedThread(30, 'W');
1909
1910 thread0->Delete();
1911
1912 puts("\nDeleted a thread which didn't start to run yet.");
1913
1914 MyDetachedThread *thread1 = new MyDetachedThread(30, 'Y');
1915
1916 thread1->Run();
1917
1918 wxThread::Sleep(300);
1919
1920 thread1->Delete();
1921
1922 puts("\nDeleted a running thread.");
1923
1924 MyDetachedThread *thread2 = new MyDetachedThread(30, 'Z');
1925
1926 thread2->Run();
1927
1928 wxThread::Sleep(300);
1929
1930 thread2->Pause();
1931
1932 thread2->Delete();
1933
1934 puts("\nDeleted a sleeping thread.");
1935
1936 MyJoinableThread thread3(20);
1937 thread3.Run();
1938
1939 thread3.Delete();
1940
1941 puts("\nDeleted a joinable thread.");
1942
1943 MyJoinableThread thread4(2);
1944 thread4.Run();
1945
1946 wxThread::Sleep(300);
1947
1948 thread4.Delete();
1949
1950 puts("\nDeleted a joinable thread which already terminated.");
1951
1952 puts("");
1953 }
1954
1955 #endif // TEST_THREADS
1956
1957 // ----------------------------------------------------------------------------
1958 // arrays
1959 // ----------------------------------------------------------------------------
1960
1961 #ifdef TEST_ARRAYS
1962
1963 void PrintArray(const char* name, const wxArrayString& array)
1964 {
1965 printf("Dump of the array '%s'\n", name);
1966
1967 size_t nCount = array.GetCount();
1968 for ( size_t n = 0; n < nCount; n++ )
1969 {
1970 printf("\t%s[%u] = '%s'\n", name, n, array[n].c_str());
1971 }
1972 }
1973
1974 #endif // TEST_ARRAYS
1975
1976 // ----------------------------------------------------------------------------
1977 // strings
1978 // ----------------------------------------------------------------------------
1979
1980 #ifdef TEST_STRINGS
1981
1982 #include "wx/timer.h"
1983 #include "wx/tokenzr.h"
1984
1985 static void TestStringConstruction()
1986 {
1987 puts("*** Testing wxString constructores ***");
1988
1989 #define TEST_CTOR(args, res) \
1990 { \
1991 wxString s args ; \
1992 printf("wxString%s = %s ", #args, s.c_str()); \
1993 if ( s == res ) \
1994 { \
1995 puts("(ok)"); \
1996 } \
1997 else \
1998 { \
1999 printf("(ERROR: should be %s)\n", res); \
2000 } \
2001 }
2002
2003 TEST_CTOR((_T('Z'), 4), _T("ZZZZ"));
2004 TEST_CTOR((_T("Hello"), 4), _T("Hell"));
2005 TEST_CTOR((_T("Hello"), 5), _T("Hello"));
2006 // TEST_CTOR((_T("Hello"), 6), _T("Hello")); -- should give assert failure
2007
2008 static const wxChar *s = _T("?really!");
2009 const wxChar *start = wxStrchr(s, _T('r'));
2010 const wxChar *end = wxStrchr(s, _T('!'));
2011 TEST_CTOR((start, end), _T("really"));
2012
2013 puts("");
2014 }
2015
2016 static void TestString()
2017 {
2018 wxStopWatch sw;
2019
2020 wxString a, b, c;
2021
2022 a.reserve (128);
2023 b.reserve (128);
2024 c.reserve (128);
2025
2026 for (int i = 0; i < 1000000; ++i)
2027 {
2028 a = "Hello";
2029 b = " world";
2030 c = "! How'ya doin'?";
2031 a += b;
2032 a += c;
2033 c = "Hello world! What's up?";
2034 if (c != a)
2035 c = "Doh!";
2036 }
2037
2038 printf ("TestString elapsed time: %ld\n", sw.Time());
2039 }
2040
2041 static void TestPChar()
2042 {
2043 wxStopWatch sw;
2044
2045 char a [128];
2046 char b [128];
2047 char c [128];
2048
2049 for (int i = 0; i < 1000000; ++i)
2050 {
2051 strcpy (a, "Hello");
2052 strcpy (b, " world");
2053 strcpy (c, "! How'ya doin'?");
2054 strcat (a, b);
2055 strcat (a, c);
2056 strcpy (c, "Hello world! What's up?");
2057 if (strcmp (c, a) == 0)
2058 strcpy (c, "Doh!");
2059 }
2060
2061 printf ("TestPChar elapsed time: %ld\n", sw.Time());
2062 }
2063
2064 static void TestStringSub()
2065 {
2066 wxString s("Hello, world!");
2067
2068 puts("*** Testing wxString substring extraction ***");
2069
2070 printf("String = '%s'\n", s.c_str());
2071 printf("Left(5) = '%s'\n", s.Left(5).c_str());
2072 printf("Right(6) = '%s'\n", s.Right(6).c_str());
2073 printf("Mid(3, 5) = '%s'\n", s(3, 5).c_str());
2074 printf("Mid(3) = '%s'\n", s.Mid(3).c_str());
2075 printf("substr(3, 5) = '%s'\n", s.substr(3, 5).c_str());
2076 printf("substr(3) = '%s'\n", s.substr(3).c_str());
2077
2078 puts("");
2079 }
2080
2081 static void TestStringFormat()
2082 {
2083 puts("*** Testing wxString formatting ***");
2084
2085 wxString s;
2086 s.Printf("%03d", 18);
2087
2088 printf("Number 18: %s\n", wxString::Format("%03d", 18).c_str());
2089 printf("Number 18: %s\n", s.c_str());
2090
2091 puts("");
2092 }
2093
2094 // returns "not found" for npos, value for all others
2095 static wxString PosToString(size_t res)
2096 {
2097 wxString s = res == wxString::npos ? wxString(_T("not found"))
2098 : wxString::Format(_T("%u"), res);
2099 return s;
2100 }
2101
2102 static void TestStringFind()
2103 {
2104 puts("*** Testing wxString find() functions ***");
2105
2106 static const wxChar *strToFind = _T("ell");
2107 static const struct StringFindTest
2108 {
2109 const wxChar *str;
2110 size_t start,
2111 result; // of searching "ell" in str
2112 } findTestData[] =
2113 {
2114 { _T("Well, hello world"), 0, 1 },
2115 { _T("Well, hello world"), 6, 7 },
2116 { _T("Well, hello world"), 9, wxString::npos },
2117 };
2118
2119 for ( size_t n = 0; n < WXSIZEOF(findTestData); n++ )
2120 {
2121 const StringFindTest& ft = findTestData[n];
2122 size_t res = wxString(ft.str).find(strToFind, ft.start);
2123
2124 printf(_T("Index of '%s' in '%s' starting from %u is %s "),
2125 strToFind, ft.str, ft.start, PosToString(res).c_str());
2126
2127 size_t resTrue = ft.result;
2128 if ( res == resTrue )
2129 {
2130 puts(_T("(ok)"));
2131 }
2132 else
2133 {
2134 printf(_T("(ERROR: should be %s)\n"),
2135 PosToString(resTrue).c_str());
2136 }
2137 }
2138
2139 puts("");
2140 }
2141
2142 // replace TABs with \t and CRs with \n
2143 static wxString MakePrintable(const wxChar *s)
2144 {
2145 wxString str(s);
2146 (void)str.Replace(_T("\t"), _T("\\t"));
2147 (void)str.Replace(_T("\n"), _T("\\n"));
2148 (void)str.Replace(_T("\r"), _T("\\r"));
2149
2150 return str;
2151 }
2152
2153 static void TestStringTokenizer()
2154 {
2155 puts("*** Testing wxStringTokenizer ***");
2156
2157 static const wxChar *modeNames[] =
2158 {
2159 _T("default"),
2160 _T("return empty"),
2161 _T("return all empty"),
2162 _T("with delims"),
2163 _T("like strtok"),
2164 };
2165
2166 static const struct StringTokenizerTest
2167 {
2168 const wxChar *str; // string to tokenize
2169 const wxChar *delims; // delimiters to use
2170 size_t count; // count of token
2171 wxStringTokenizerMode mode; // how should we tokenize it
2172 } tokenizerTestData[] =
2173 {
2174 { _T(""), _T(" "), 0 },
2175 { _T("Hello, world"), _T(" "), 2 },
2176 { _T("Hello, world "), _T(" "), 2 },
2177 { _T("Hello, world"), _T(","), 2 },
2178 { _T("Hello, world!"), _T(",!"), 2 },
2179 { _T("Hello,, world!"), _T(",!"), 3 },
2180 { _T("Hello, world!"), _T(",!"), 3, wxTOKEN_RET_EMPTY_ALL },
2181 { _T("username:password:uid:gid:gecos:home:shell"), _T(":"), 7 },
2182 { _T("1 \t3\t4 6 "), wxDEFAULT_DELIMITERS, 4 },
2183 { _T("1 \t3\t4 6 "), wxDEFAULT_DELIMITERS, 6, wxTOKEN_RET_EMPTY },
2184 { _T("1 \t3\t4 6 "), wxDEFAULT_DELIMITERS, 9, wxTOKEN_RET_EMPTY_ALL },
2185 { _T("01/02/99"), _T("/-"), 3 },
2186 { _T("01-02/99"), _T("/-"), 3, wxTOKEN_RET_DELIMS },
2187 };
2188
2189 for ( size_t n = 0; n < WXSIZEOF(tokenizerTestData); n++ )
2190 {
2191 const StringTokenizerTest& tt = tokenizerTestData[n];
2192 wxStringTokenizer tkz(tt.str, tt.delims, tt.mode);
2193
2194 size_t count = tkz.CountTokens();
2195 printf(_T("String '%s' has %u tokens delimited by '%s' (mode = %s) "),
2196 MakePrintable(tt.str).c_str(),
2197 count,
2198 MakePrintable(tt.delims).c_str(),
2199 modeNames[tkz.GetMode()]);
2200 if ( count == tt.count )
2201 {
2202 puts(_T("(ok)"));
2203 }
2204 else
2205 {
2206 printf(_T("(ERROR: should be %u)\n"), tt.count);
2207
2208 continue;
2209 }
2210
2211 // if we emulate strtok(), check that we do it correctly
2212 wxChar *buf, *s, *last;
2213
2214 if ( tkz.GetMode() == wxTOKEN_STRTOK )
2215 {
2216 buf = new wxChar[wxStrlen(tt.str) + 1];
2217 wxStrcpy(buf, tt.str);
2218
2219 s = wxStrtok(buf, tt.delims, &last);
2220 }
2221 else
2222 {
2223 buf = NULL;
2224 }
2225
2226 // now show the tokens themselves
2227 size_t count2 = 0;
2228 while ( tkz.HasMoreTokens() )
2229 {
2230 wxString token = tkz.GetNextToken();
2231
2232 printf(_T("\ttoken %u: '%s'"),
2233 ++count2,
2234 MakePrintable(token).c_str());
2235
2236 if ( buf )
2237 {
2238 if ( token == s )
2239 {
2240 puts(" (ok)");
2241 }
2242 else
2243 {
2244 printf(" (ERROR: should be %s)\n", s);
2245 }
2246
2247 s = wxStrtok(NULL, tt.delims, &last);
2248 }
2249 else
2250 {
2251 // nothing to compare with
2252 puts("");
2253 }
2254 }
2255
2256 if ( count2 != count )
2257 {
2258 puts(_T("\tERROR: token count mismatch"));
2259 }
2260
2261 delete [] buf;
2262 }
2263
2264 puts("");
2265 }
2266
2267 #endif // TEST_STRINGS
2268
2269 // ----------------------------------------------------------------------------
2270 // entry point
2271 // ----------------------------------------------------------------------------
2272
2273 int main(int argc, char **argv)
2274 {
2275 if ( !wxInitialize() )
2276 {
2277 fprintf(stderr, "Failed to initialize the wxWindows library, aborting.");
2278 }
2279
2280 #ifdef TEST_USLEEP
2281 puts("Sleeping for 3 seconds... z-z-z-z-z...");
2282 wxUsleep(3000);
2283 #endif // TEST_USLEEP
2284
2285 #ifdef TEST_CMDLINE
2286 static const wxCmdLineEntryDesc cmdLineDesc[] =
2287 {
2288 { wxCMD_LINE_SWITCH, "v", "verbose", "be verbose" },
2289 { wxCMD_LINE_SWITCH, "q", "quiet", "be quiet" },
2290
2291 { wxCMD_LINE_OPTION, "o", "output", "output file" },
2292 { wxCMD_LINE_OPTION, "i", "input", "input dir" },
2293 { wxCMD_LINE_OPTION, "s", "size", "output block size", wxCMD_LINE_VAL_NUMBER },
2294 { wxCMD_LINE_OPTION, "d", "date", "output file date", wxCMD_LINE_VAL_DATE },
2295
2296 { wxCMD_LINE_PARAM, NULL, NULL, "input file",
2297 wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE },
2298
2299 { wxCMD_LINE_NONE }
2300 };
2301
2302 wxCmdLineParser parser(cmdLineDesc, argc, argv);
2303
2304 switch ( parser.Parse() )
2305 {
2306 case -1:
2307 wxLogMessage("Help was given, terminating.");
2308 break;
2309
2310 case 0:
2311 ShowCmdLine(parser);
2312 break;
2313
2314 default:
2315 wxLogMessage("Syntax error detected, aborting.");
2316 break;
2317 }
2318 #endif // TEST_CMDLINE
2319
2320 #ifdef TEST_STRINGS
2321 if ( 0 )
2322 {
2323 TestPChar();
2324 TestString();
2325 }
2326 if ( 0 )
2327 {
2328 TestStringConstruction();
2329 TestStringSub();
2330 TestStringFormat();
2331 TestStringFind();
2332 TestStringTokenizer();
2333 }
2334 #endif // TEST_STRINGS
2335
2336 #ifdef TEST_ARRAYS
2337 wxArrayString a1;
2338 a1.Add("tiger");
2339 a1.Add("cat");
2340 a1.Add("lion");
2341 a1.Add("dog");
2342 a1.Add("human");
2343 a1.Add("ape");
2344
2345 puts("*** Initially:");
2346
2347 PrintArray("a1", a1);
2348
2349 wxArrayString a2(a1);
2350 PrintArray("a2", a2);
2351
2352 wxSortedArrayString a3(a1);
2353 PrintArray("a3", a3);
2354
2355 puts("*** After deleting a string from a1");
2356 a1.Remove(2);
2357
2358 PrintArray("a1", a1);
2359 PrintArray("a2", a2);
2360 PrintArray("a3", a3);
2361
2362 puts("*** After reassigning a1 to a2 and a3");
2363 a3 = a2 = a1;
2364 PrintArray("a2", a2);
2365 PrintArray("a3", a3);
2366 #endif // TEST_ARRAYS
2367
2368 #ifdef TEST_DIR
2369 TestDirEnum();
2370 #endif // TEST_DIR
2371
2372 #ifdef TEST_EXECUTE
2373 TestExecute();
2374 #endif // TEST_EXECUTE
2375
2376 #ifdef TEST_FILECONF
2377 TestFileConfRead();
2378 #endif // TEST_FILECONF
2379
2380 #ifdef TEST_LOG
2381 wxString s;
2382 for ( size_t n = 0; n < 8000; n++ )
2383 {
2384 s << (char)('A' + (n % 26));
2385 }
2386
2387 wxString msg;
2388 msg.Printf("A very very long message: '%s', the end!\n", s.c_str());
2389
2390 // this one shouldn't be truncated
2391 printf(msg);
2392
2393 // but this one will because log functions use fixed size buffer
2394 // (note that it doesn't need '\n' at the end neither - will be added
2395 // by wxLog anyhow)
2396 wxLogMessage("A very very long message 2: '%s', the end!", s.c_str());
2397 #endif // TEST_LOG
2398
2399 #ifdef TEST_THREADS
2400 int nCPUs = wxThread::GetCPUCount();
2401 printf("This system has %d CPUs\n", nCPUs);
2402 if ( nCPUs != -1 )
2403 wxThread::SetConcurrency(nCPUs);
2404
2405 if ( argc > 1 && argv[1][0] == 't' )
2406 wxLog::AddTraceMask("thread");
2407
2408 if ( 1 )
2409 TestDetachedThreads();
2410 if ( 1 )
2411 TestJoinableThreads();
2412 if ( 1 )
2413 TestThreadSuspend();
2414 if ( 1 )
2415 TestThreadDelete();
2416
2417 #endif // TEST_THREADS
2418
2419 #ifdef TEST_LONGLONG
2420 // seed pseudo random generator
2421 srand((unsigned)time(NULL));
2422
2423 if ( 0 )
2424 {
2425 TestSpeed();
2426 }
2427 TestMultiplication();
2428 if ( 0 )
2429 {
2430 TestDivision();
2431 TestAddition();
2432 TestLongLongConversion();
2433 TestBitOperations();
2434 }
2435 #endif // TEST_LONGLONG
2436
2437 #ifdef TEST_HASH
2438 TestHash();
2439 #endif // TEST_HASH
2440
2441 #ifdef TEST_MIME
2442 TestMimeEnum();
2443 #endif // TEST_MIME
2444
2445 #ifdef TEST_SOCKETS
2446 TestSocketClient();
2447 #endif // TEST_SOCKETS
2448
2449 #ifdef TEST_TIMER
2450 TestStopWatch();
2451 #endif // TEST_TIMER
2452
2453 #ifdef TEST_DATETIME
2454 if ( 0 )
2455 {
2456 TestTimeSet();
2457 TestTimeStatic();
2458 TestTimeRange();
2459 TestTimeZones();
2460 TestTimeTicks();
2461 TestTimeJDN();
2462 TestTimeDST();
2463 TestTimeWDays();
2464 TestTimeWNumber();
2465 TestTimeParse();
2466 TestTimeFormat();
2467 TestTimeArithmetics();
2468 }
2469 TestTimeHolidays();
2470 if ( 0 )
2471 TestInteractive();
2472 #endif // TEST_DATETIME
2473
2474 wxUninitialize();
2475
2476 return 0;
2477 }