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