]> git.saurik.com Git - wxWidgets.git/blame_incremental - samples/console/console.cpp
compilation for Win32 using configure works again
[wxWidgets.git] / samples / console / console.cpp
... / ...
CommitLineData
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
56static 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
95static 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
115static 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
172static 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
200static 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
258inline bool operator==(const wxLongLongWx& a, const wxLongLongNative& b)
259 { return a.GetHi() == b.GetHi() && a.GetLo() == b.GetLo(); }
260inline bool operator==(const wxLongLongNative& a, const wxLongLongWx& b)
261 { return a.GetHi() == b.GetHi() && a.GetLo() == b.GetLo(); }
262#endif // wxUSE_LONGLONG_WX
263
264static 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
308static 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
340static 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
374static 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
413static 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
445static 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
505struct 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
559static 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
579static 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
623static 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
645static 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
667static 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
685static 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
726static 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
750static 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 /*
818from DateTime import *
819from whrandom import *
820from string import *
821
822monthNames = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
823wdayNames = [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' ]
824
825week = DateTimeDelta(7)
826
827for 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
897static 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 /*
912from DateTime import *
913from whrandom import *
914from string import *
915
916monthNames = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
917wdayNames = [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' ]
918
919def 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
925def GetLastSundayBefore(dt):
926 if dt.iso_week[2] == 7:
927 return dt
928 else:
929 return dt - DateTimeDelta(dt.iso_week[2])
930
931for 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
1045static 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
1128static 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
1233static 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
1286static 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
1317static 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
1381static 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
1409static 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
1448static size_t gs_counter = (size_t)-1;
1449static wxCriticalSection gs_critsect;
1450static wxCondition gs_cond;
1451
1452class MyJoinableThread : public wxThread
1453{
1454public:
1455 MyJoinableThread(size_t n) : wxThread(wxTHREAD_JOINABLE)
1456 { m_n = n; Create(); }
1457
1458 // thread execution starts here
1459 virtual ExitCode Entry();
1460
1461private:
1462 size_t m_n;
1463};
1464
1465wxThread::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
1479class MyDetachedThread : public wxThread
1480{
1481public:
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
1497private:
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
1504wxThread::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
1532void 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
1541void 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
1567void 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
1579void 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
1618void 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
1682void 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
1703static void TestString()
1704{
1705 wxStopWatch sw;
1706
1707 wxString a, b, c;
1708
1709 a.reserve (128);
1710 b.reserve (128);
1711 c.reserve (128);
1712
1713 for (int i = 0; i < 1000000; ++i)
1714 {
1715 a = "Hello";
1716 b = " world";
1717 c = "! How'ya doin'?";
1718 a += b;
1719 a += c;
1720 c = "Hello world! What's up?";
1721 if (c != a)
1722 c = "Doh!";
1723 }
1724
1725 printf ("TestString elapsed time: %ld\n", sw.Time());
1726}
1727
1728static void TestPChar()
1729{
1730 wxStopWatch sw;
1731
1732 char a [128];
1733 char b [128];
1734 char c [128];
1735
1736 for (int i = 0; i < 1000000; ++i)
1737 {
1738 strcpy (a, "Hello");
1739 strcpy (b, " world");
1740 strcpy (c, "! How'ya doin'?");
1741 strcat (a, b);
1742 strcat (a, c);
1743 strcpy (c, "Hello world! What's up?");
1744 if (strcmp (c, a) == 0)
1745 strcpy (c, "Doh!");
1746 }
1747
1748 printf ("TestPChar elapsed time: %ld\n", sw.Time());
1749}
1750
1751static void TestStringSub()
1752{
1753 wxString s("Hello, world!");
1754
1755 puts("*** Testing wxString substring extraction ***");
1756
1757 printf("String = '%s'\n", s.c_str());
1758 printf("Left(5) = '%s'\n", s.Left(5).c_str());
1759 printf("Right(6) = '%s'\n", s.Right(6).c_str());
1760 printf("Mid(3, 5) = '%s'\n", s(3, 5).c_str());
1761 printf("Mid(3) = '%s'\n", s.Mid(3).c_str());
1762 printf("substr(3, 5) = '%s'\n", s.substr(3, 5).c_str());
1763 printf("substr(3) = '%s'\n", s.substr(3).c_str());
1764
1765 puts("");
1766}
1767
1768static void TestStringFormat()
1769{
1770 puts("*** Testing wxString formatting ***");
1771
1772 wxString s;
1773 s.Printf("%03d", 18);
1774
1775 printf("Number 18: %s\n", wxString::Format("%03d", 18).c_str());
1776 printf("Number 18: %s\n", s.c_str());
1777
1778 puts("");
1779}
1780
1781// returns "not found" for npos, value for all others
1782static wxString PosToString(size_t res)
1783{
1784 wxString s = res == wxString::npos ? wxString(_T("not found"))
1785 : wxString::Format(_T("%u"), res);
1786 return s;
1787}
1788
1789static void TestStringFind()
1790{
1791 puts("*** Testing wxString find() functions ***");
1792
1793 static const wxChar *strToFind = _T("ell");
1794 static const struct StringFindTest
1795 {
1796 const wxChar *str;
1797 size_t start,
1798 result; // of searching "ell" in str
1799 } findTestData[] =
1800 {
1801 { _T("Well, hello world"), 0, 1 },
1802 { _T("Well, hello world"), 6, 7 },
1803 { _T("Well, hello world"), 9, wxString::npos },
1804 };
1805
1806 for ( size_t n = 0; n < WXSIZEOF(findTestData); n++ )
1807 {
1808 const StringFindTest& ft = findTestData[n];
1809 size_t res = wxString(ft.str).find(strToFind, ft.start);
1810
1811 printf(_T("Index of '%s' in '%s' starting from %u is %s "),
1812 strToFind, ft.str, ft.start, PosToString(res).c_str());
1813
1814 size_t resTrue = ft.result;
1815 if ( res == resTrue )
1816 {
1817 puts(_T("(ok)"));
1818 }
1819 else
1820 {
1821 printf(_T("(ERROR: should be %s)\n"),
1822 PosToString(resTrue).c_str());
1823 }
1824 }
1825
1826 puts("");
1827}
1828
1829#endif // TEST_STRINGS
1830
1831// ----------------------------------------------------------------------------
1832// entry point
1833// ----------------------------------------------------------------------------
1834
1835int main(int argc, char **argv)
1836{
1837 if ( !wxInitialize() )
1838 {
1839 fprintf(stderr, "Failed to initialize the wxWindows library, aborting.");
1840 }
1841
1842#ifdef TEST_USLEEP
1843 puts("Sleeping for 3 seconds... z-z-z-z-z...");
1844 wxUsleep(3000);
1845#endif // TEST_USLEEP
1846
1847#ifdef TEST_CMDLINE
1848 static const wxCmdLineEntryDesc cmdLineDesc[] =
1849 {
1850 { wxCMD_LINE_SWITCH, "v", "verbose", "be verbose" },
1851 { wxCMD_LINE_SWITCH, "q", "quiet", "be quiet" },
1852
1853 { wxCMD_LINE_OPTION, "o", "output", "output file" },
1854 { wxCMD_LINE_OPTION, "i", "input", "input dir" },
1855 { wxCMD_LINE_OPTION, "s", "size", "output block size", wxCMD_LINE_VAL_NUMBER },
1856 { wxCMD_LINE_OPTION, "d", "date", "output file date", wxCMD_LINE_VAL_DATE },
1857
1858 { wxCMD_LINE_PARAM, NULL, NULL, "input file",
1859 wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE },
1860
1861 { wxCMD_LINE_NONE }
1862 };
1863
1864 wxCmdLineParser parser(cmdLineDesc, argc, argv);
1865
1866 switch ( parser.Parse() )
1867 {
1868 case -1:
1869 wxLogMessage("Help was given, terminating.");
1870 break;
1871
1872 case 0:
1873 ShowCmdLine(parser);
1874 break;
1875
1876 default:
1877 wxLogMessage("Syntax error detected, aborting.");
1878 break;
1879 }
1880#endif // TEST_CMDLINE
1881
1882#ifdef TEST_STRINGS
1883 if ( 0 )
1884 {
1885 TestPChar();
1886 TestString();
1887 }
1888 if ( 0 )
1889 {
1890 TestStringSub();
1891 TestStringFormat();
1892 }
1893 TestStringFind();
1894#endif // TEST_STRINGS
1895
1896#ifdef TEST_ARRAYS
1897 wxArrayString a1;
1898 a1.Add("tiger");
1899 a1.Add("cat");
1900 a1.Add("lion");
1901 a1.Add("dog");
1902 a1.Add("human");
1903 a1.Add("ape");
1904
1905 puts("*** Initially:");
1906
1907 PrintArray("a1", a1);
1908
1909 wxArrayString a2(a1);
1910 PrintArray("a2", a2);
1911
1912 wxSortedArrayString a3(a1);
1913 PrintArray("a3", a3);
1914
1915 puts("*** After deleting a string from a1");
1916 a1.Remove(2);
1917
1918 PrintArray("a1", a1);
1919 PrintArray("a2", a2);
1920 PrintArray("a3", a3);
1921
1922 puts("*** After reassigning a1 to a2 and a3");
1923 a3 = a2 = a1;
1924 PrintArray("a2", a2);
1925 PrintArray("a3", a3);
1926#endif // TEST_ARRAYS
1927
1928#ifdef TEST_DIR
1929 TestDirEnum();
1930#endif // TEST_DIR
1931
1932#ifdef TEST_EXECUTE
1933 TestExecute();
1934#endif // TEST_EXECUTE
1935
1936#ifdef TEST_LOG
1937 wxString s;
1938 for ( size_t n = 0; n < 8000; n++ )
1939 {
1940 s << (char)('A' + (n % 26));
1941 }
1942
1943 wxString msg;
1944 msg.Printf("A very very long message: '%s', the end!\n", s.c_str());
1945
1946 // this one shouldn't be truncated
1947 printf(msg);
1948
1949 // but this one will because log functions use fixed size buffer
1950 // (note that it doesn't need '\n' at the end neither - will be added
1951 // by wxLog anyhow)
1952 wxLogMessage("A very very long message 2: '%s', the end!", s.c_str());
1953#endif // TEST_LOG
1954
1955#ifdef TEST_THREADS
1956 int nCPUs = wxThread::GetCPUCount();
1957 printf("This system has %d CPUs\n", nCPUs);
1958 if ( nCPUs != -1 )
1959 wxThread::SetConcurrency(nCPUs);
1960
1961 if ( argc > 1 && argv[1][0] == 't' )
1962 wxLog::AddTraceMask("thread");
1963
1964 if ( 1 )
1965 TestDetachedThreads();
1966 if ( 1 )
1967 TestJoinableThreads();
1968 if ( 1 )
1969 TestThreadSuspend();
1970 if ( 1 )
1971 TestThreadDelete();
1972
1973#endif // TEST_THREADS
1974
1975#ifdef TEST_LONGLONG
1976 // seed pseudo random generator
1977 srand((unsigned)time(NULL));
1978
1979 if ( 0 )
1980 {
1981 TestSpeed();
1982 }
1983 TestMultiplication();
1984 if ( 0 )
1985 {
1986 TestDivision();
1987 TestAddition();
1988 TestLongLongConversion();
1989 TestBitOperations();
1990 }
1991#endif // TEST_LONGLONG
1992
1993#ifdef TEST_MIME
1994 TestMimeEnum();
1995#endif // TEST_MIME
1996
1997#ifdef TEST_TIME
1998 if ( 0 )
1999 {
2000 TestTimeSet();
2001 TestTimeStatic();
2002 TestTimeRange();
2003 TestTimeZones();
2004 TestTimeTicks();
2005 TestTimeJDN();
2006 TestTimeDST();
2007 TestTimeWDays();
2008 TestTimeWNumber();
2009 TestTimeParse();
2010 TestTimeFormat();
2011 TestTimeArithmetics();
2012 }
2013 TestTimeHolidays();
2014 if ( 0 )
2015 TestInteractive();
2016#endif // TEST_TIME
2017
2018 wxUninitialize();
2019
2020 return 0;
2021}