]> git.saurik.com Git - wxWidgets.git/blob - samples/console/console.cpp
ecbaeeda4f704ac91f0ebc25c7a6dc45760d4b27
[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_DIR
34 //#define TEST_LOG
35 //#define TEST_MIME
36 //#define TEST_STRINGS
37 //#define TEST_THREADS
38 //#define TEST_TIME
39 //#define TEST_LONGLONG
40
41 // ============================================================================
42 // implementation
43 // ============================================================================
44
45 // ----------------------------------------------------------------------------
46 // wxDir
47 // ----------------------------------------------------------------------------
48
49 #ifdef TEST_DIR
50
51 #include <wx/dir.h>
52
53 static void TestDirEnumHelper(wxDir& dir,
54 int flags = wxDIR_DEFAULT,
55 const wxString& filespec = wxEmptyString)
56 {
57 wxString filename;
58
59 if ( !dir.IsOpened() )
60 return;
61
62 bool cont = dir.GetFirst(&filename, filespec, flags);
63 while ( cont )
64 {
65 printf("\t%s\n", filename.c_str());
66
67 cont = dir.GetNext(&filename);
68 }
69
70 puts("");
71 }
72
73 static void TestDirEnum()
74 {
75 wxDir dir(wxGetCwd());
76
77 puts("Enumerating everything in current directory:");
78 TestDirEnumHelper(dir);
79
80 puts("Enumerating really everything in current directory:");
81 TestDirEnumHelper(dir, wxDIR_DEFAULT | wxDIR_DOTDOT);
82
83 puts("Enumerating object files in current directory:");
84 TestDirEnumHelper(dir, wxDIR_DEFAULT, "*.o");
85
86 puts("Enumerating directories in current directory:");
87 TestDirEnumHelper(dir, wxDIR_DIRS);
88
89 puts("Enumerating files in current directory:");
90 TestDirEnumHelper(dir, wxDIR_FILES);
91
92 puts("Enumerating files including hidden in current directory:");
93 TestDirEnumHelper(dir, wxDIR_FILES | wxDIR_HIDDEN);
94
95 #ifdef __UNIX__
96 dir.Open("/");
97 #elif defined(__WXMSW__)
98 dir.Open("c:\\");
99 #else
100 #error "don't know where the root directory is"
101 #endif
102
103 puts("Enumerating everything in root directory:");
104 TestDirEnumHelper(dir, wxDIR_DEFAULT);
105
106 puts("Enumerating directories in root directory:");
107 TestDirEnumHelper(dir, wxDIR_DIRS);
108
109 puts("Enumerating files in root directory:");
110 TestDirEnumHelper(dir, wxDIR_FILES);
111
112 puts("Enumerating files including hidden in root directory:");
113 TestDirEnumHelper(dir, wxDIR_FILES | wxDIR_HIDDEN);
114
115 puts("Enumerating files in non existing directory:");
116 wxDir dirNo("nosuchdir");
117 TestDirEnumHelper(dirNo);
118 }
119
120 #endif // TEST_DIR
121
122 // ----------------------------------------------------------------------------
123 // MIME types
124 // ----------------------------------------------------------------------------
125
126 #ifdef TEST_MIME
127
128 #include <wx/mimetype.h>
129
130 static void TestMimeEnum()
131 {
132 wxMimeTypesManager mimeTM;
133 wxArrayString mimetypes;
134
135 size_t count = mimeTM.EnumAllFileTypes(mimetypes);
136
137 printf("*** All %u known filetypes: ***\n", count);
138
139 wxArrayString exts;
140 wxString desc;
141
142 for ( size_t n = 0; n < count; n++ )
143 {
144 wxFileType *filetype = mimeTM.GetFileTypeFromMimeType(mimetypes[n]);
145 if ( !filetype )
146 {
147 printf("nothing known about the filetype '%s'!\n",
148 mimetypes[n].c_str());
149 continue;
150 }
151
152 filetype->GetDescription(&desc);
153 filetype->GetExtensions(exts);
154
155 wxString extsAll;
156 for ( size_t e = 0; e < exts.GetCount(); e++ )
157 {
158 if ( e > 0 )
159 extsAll << _T(", ");
160 extsAll += exts[e];
161 }
162
163 printf("\t%s: %s (%s)\n",
164 mimetypes[n].c_str(), desc.c_str(), extsAll.c_str());
165 }
166 }
167
168 #endif // TEST_MIME
169
170 // ----------------------------------------------------------------------------
171 // long long
172 // ----------------------------------------------------------------------------
173
174 #ifdef TEST_LONGLONG
175
176 #include <wx/longlong.h>
177 #include <wx/timer.h>
178
179 static void TestSpeed()
180 {
181 static const long max = 100000000;
182 long n;
183
184 {
185 wxStopWatch sw;
186
187 long l = 0;
188 for ( n = 0; n < max; n++ )
189 {
190 l += n;
191 }
192
193 printf("Summing longs took %ld milliseconds.\n", sw.Time());
194 }
195
196 {
197 wxStopWatch sw;
198
199 __int64 l = 0;
200 for ( n = 0; n < max; n++ )
201 {
202 l += n;
203 }
204
205 printf("Summing __int64s took %ld milliseconds.\n", sw.Time());
206 }
207
208 {
209 wxStopWatch sw;
210
211 wxLongLong l;
212 for ( n = 0; n < max; n++ )
213 {
214 l += n;
215 }
216
217 printf("Summing wxLongLongs took %ld milliseconds.\n", sw.Time());
218 }
219 }
220
221 static void TestDivision()
222 {
223 #define MAKE_LL(x1, x2, x3, x4) wxLongLong((x1 << 16) | x2, (x3 << 16) | x3)
224
225 // seed pseudo random generator
226 //srand((unsigned)time(NULL));
227
228 size_t nTested = 0;
229 for ( size_t n = 0; n < 10000; n++ )
230 {
231 // get a random wxLongLong (shifting by 12 the MSB ensures that the
232 // multiplication will not overflow)
233 wxLongLong ll = MAKE_LL((rand() >> 12), rand(), rand(), rand());
234
235 wxASSERT( (ll * 1000l)/1000l == ll );
236
237 nTested++;
238 }
239
240 printf("\n*** Tested %u divisions/multiplications: ok\n", nTested);
241
242 #undef MAKE_LL
243 }
244
245 #endif // TEST_LONGLONG
246
247 // ----------------------------------------------------------------------------
248 // date time
249 // ----------------------------------------------------------------------------
250
251 #ifdef TEST_TIME
252
253 #include <wx/datetime.h>
254
255 // this test miscellaneous static wxDateTime functions
256 static void TestTimeStatic()
257 {
258 puts("\n*** wxDateTime static methods test ***");
259
260 // some info about the current date
261 int year = wxDateTime::GetCurrentYear();
262 printf("Current year %d is %sa leap one and has %d days.\n",
263 year,
264 wxDateTime::IsLeapYear(year) ? "" : "not ",
265 wxDateTime::GetNumberOfDays(year));
266
267 wxDateTime::Month month = wxDateTime::GetCurrentMonth();
268 printf("Current month is '%s' ('%s') and it has %d days\n",
269 wxDateTime::GetMonthName(month, TRUE).c_str(),
270 wxDateTime::GetMonthName(month).c_str(),
271 wxDateTime::GetNumberOfDays(month));
272
273 // leap year logic
274 static const size_t nYears = 5;
275 static const size_t years[2][nYears] =
276 {
277 // first line: the years to test
278 { 1990, 1976, 2000, 2030, 1984, },
279
280 // second line: TRUE if leap, FALSE otherwise
281 { FALSE, TRUE, TRUE, FALSE, TRUE }
282 };
283
284 for ( size_t n = 0; n < nYears; n++ )
285 {
286 int year = years[0][n];
287 bool should = years[1][n] != 0;
288
289 printf("Year %d is %sa leap year (should be: %s)\n",
290 year,
291 wxDateTime::IsLeapYear(year) ? "" : "not ",
292 should ? "yes" : "no");
293
294 wxASSERT( should == wxDateTime::IsLeapYear(year) );
295 }
296 }
297
298 // test constructing wxDateTime objects
299 static void TestTimeSet()
300 {
301 puts("\n*** wxDateTime construction test ***");
302
303 printf("Current time:\t%s\n", wxDateTime::Now().Format().c_str());
304 printf("Unix epoch:\t%s\n", wxDateTime((time_t)0).Format().c_str());
305 printf("Today noon:\t%s\n", wxDateTime(12, 0).Format().c_str());
306 printf("May 29, 1976:\t%s\n", wxDateTime(29, wxDateTime::May, 1976).Format().c_str());
307 }
308
309 // test time zones stuff
310 static void TestTimeZones()
311 {
312 puts("\n*** wxDateTime timezone test ***");
313
314 wxDateTime now = wxDateTime::Now();
315
316 printf("Current GMT time:\t%s\n", now.ToGMT().Format().c_str());
317 printf("Unix epoch (GMT):\t%s\n", wxDateTime((time_t)0).MakeGMT().Format().c_str());
318 printf("Current time in Paris:\t%s\n", now.ToTimezone(wxDateTime::CET).Format().c_str());
319 printf(" Moscow:\t%s\n", now.ToTimezone(wxDateTime::MSK).Format().c_str());
320 printf(" New York:\t%s\n", now.ToTimezone(wxDateTime::EST).Format().c_str());
321 }
322
323 // test some minimal support for the dates outside the standard range
324 static void TestTimeRange()
325 {
326 puts("\n*** wxDateTime out-of-standard-range dates test ***");
327
328 printf("Unix epoch:\t%s\n",
329 wxDateTime(2440587.5).Format().c_str());
330 printf("Feb 29, 0: \t%s\n",
331 wxDateTime(29, wxDateTime::Feb, 0).Format().c_str());
332 printf("JDN 0: \t%s\n",
333 wxDateTime(0.0).Format().c_str());
334 printf("Jan 1, 1AD:\t%s\n",
335 wxDateTime(1, wxDateTime::Jan, 1).Format().c_str());
336 printf("May 29, 2099:\t%s\n",
337 wxDateTime(29, wxDateTime::May, 2099).Format().c_str());
338 }
339
340 // test conversions to JDN &c
341 static void TestTimeJDN()
342 {
343 puts("\n*** wxDateTime to JDN test ***");
344
345 struct Date
346 {
347 wxDateTime::wxDateTime_t day;
348 wxDateTime::Month month;
349 int year;
350 double jdn;
351 };
352
353 static const Date testDates[] =
354 {
355 { 21, wxDateTime::Jan, 2222, 2532648.5 },
356 { 29, wxDateTime::May, 1976, 2442927.5 },
357 { 1, wxDateTime::Jan, 1970, 2440587.5 },
358 { 1, wxDateTime::Jan, 1900, 2415020.5 },
359 { 15, wxDateTime::Oct, 1582, 2299160.5 },
360 { 4, wxDateTime::Oct, 1582, 2299149.5 },
361 { 1, wxDateTime::Mar, 1, 1721484.5 },
362 { 1, wxDateTime::Jan, 1, 1721425.5 },
363 { 31, wxDateTime::Dec, 0, 1721424.5 },
364 { 1, wxDateTime::Jan, 0, 1721059.5 },
365 { 12, wxDateTime::Aug, -1234, 1270573.5 },
366 { 12, wxDateTime::Aug, -4000, 260313.5 },
367 { 24, wxDateTime::Nov, -4713, -0.5 },
368 };
369
370 for ( size_t n = 0; n < WXSIZEOF(testDates); n++ )
371 {
372 const Date& d = testDates[n];
373 wxDateTime dt(d.day, d.month, d.year);
374 double jdn = dt.GetJulianDayNumber();
375
376 printf("JDN of %s %02d, %4d%s is:\t%f",
377 wxDateTime::GetMonthName(d.month).c_str(),
378 d.day,
379 wxDateTime::ConvertYearToBC(d.year),
380 d.year > 0 ? "AD" : "BC",
381 jdn);
382 if ( jdn == d.jdn )
383 {
384 puts(" (ok)");
385 }
386 else
387 {
388 printf(" (ERROR: should be %f, delta = %f)\n",
389 d.jdn, jdn - d.jdn);
390 }
391 }
392 }
393
394 #endif // TEST_TIME
395
396 // ----------------------------------------------------------------------------
397 // threads
398 // ----------------------------------------------------------------------------
399
400 #ifdef TEST_THREADS
401
402 #include <wx/thread.h>
403
404 static size_t gs_counter = (size_t)-1;
405 static wxCriticalSection gs_critsect;
406 static wxCondition gs_cond;
407
408 class MyJoinableThread : public wxThread
409 {
410 public:
411 MyJoinableThread(size_t n) : wxThread(wxTHREAD_JOINABLE)
412 { m_n = n; Create(); }
413
414 // thread execution starts here
415 virtual ExitCode Entry();
416
417 private:
418 size_t m_n;
419 };
420
421 wxThread::ExitCode MyJoinableThread::Entry()
422 {
423 unsigned long res = 1;
424 for ( size_t n = 1; n < m_n; n++ )
425 {
426 res *= n;
427
428 // it's a loooong calculation :-)
429 Sleep(100);
430 }
431
432 return (ExitCode)res;
433 }
434
435 class MyDetachedThread : public wxThread
436 {
437 public:
438 MyDetachedThread(size_t n, char ch)
439 {
440 m_n = n;
441 m_ch = ch;
442 m_cancelled = FALSE;
443
444 Create();
445 }
446
447 // thread execution starts here
448 virtual ExitCode Entry();
449
450 // and stops here
451 virtual void OnExit();
452
453 private:
454 size_t m_n; // number of characters to write
455 char m_ch; // character to write
456
457 bool m_cancelled; // FALSE if we exit normally
458 };
459
460 wxThread::ExitCode MyDetachedThread::Entry()
461 {
462 {
463 wxCriticalSectionLocker lock(gs_critsect);
464 if ( gs_counter == (size_t)-1 )
465 gs_counter = 1;
466 else
467 gs_counter++;
468 }
469
470 for ( size_t n = 0; n < m_n; n++ )
471 {
472 if ( TestDestroy() )
473 {
474 m_cancelled = TRUE;
475
476 break;
477 }
478
479 putchar(m_ch);
480 fflush(stdout);
481
482 wxThread::Sleep(100);
483 }
484
485 return 0;
486 }
487
488 void MyDetachedThread::OnExit()
489 {
490 wxLogTrace("thread", "Thread %ld is in OnExit", GetId());
491
492 wxCriticalSectionLocker lock(gs_critsect);
493 if ( !--gs_counter && !m_cancelled )
494 gs_cond.Signal();
495 }
496
497 void TestDetachedThreads()
498 {
499 puts("\n*** Testing detached threads ***");
500
501 static const size_t nThreads = 3;
502 MyDetachedThread *threads[nThreads];
503 size_t n;
504 for ( n = 0; n < nThreads; n++ )
505 {
506 threads[n] = new MyDetachedThread(10, 'A' + n);
507 }
508
509 threads[0]->SetPriority(WXTHREAD_MIN_PRIORITY);
510 threads[1]->SetPriority(WXTHREAD_MAX_PRIORITY);
511
512 for ( n = 0; n < nThreads; n++ )
513 {
514 threads[n]->Run();
515 }
516
517 // wait until all threads terminate
518 gs_cond.Wait();
519
520 puts("");
521 }
522
523 void TestJoinableThreads()
524 {
525 puts("\n*** Testing a joinable thread (a loooong calculation...) ***");
526
527 // calc 10! in the background
528 MyJoinableThread thread(10);
529 thread.Run();
530
531 printf("\nThread terminated with exit code %lu.\n",
532 (unsigned long)thread.Wait());
533 }
534
535 void TestThreadSuspend()
536 {
537 puts("\n*** Testing thread suspend/resume functions ***");
538
539 MyDetachedThread *thread = new MyDetachedThread(15, 'X');
540
541 thread->Run();
542
543 // this is for this demo only, in a real life program we'd use another
544 // condition variable which would be signaled from wxThread::Entry() to
545 // tell us that the thread really started running - but here just wait a
546 // bit and hope that it will be enough (the problem is, of course, that
547 // the thread might still not run when we call Pause() which will result
548 // in an error)
549 wxThread::Sleep(300);
550
551 for ( size_t n = 0; n < 3; n++ )
552 {
553 thread->Pause();
554
555 puts("\nThread suspended");
556 if ( n > 0 )
557 {
558 // don't sleep but resume immediately the first time
559 wxThread::Sleep(300);
560 }
561 puts("Going to resume the thread");
562
563 thread->Resume();
564 }
565
566 puts("Waiting until it terminates now");
567
568 // wait until the thread terminates
569 gs_cond.Wait();
570
571 puts("");
572 }
573
574 void TestThreadDelete()
575 {
576 // As above, using Sleep() is only for testing here - we must use some
577 // synchronisation object instead to ensure that the thread is still
578 // running when we delete it - deleting a detached thread which already
579 // terminated will lead to a crash!
580
581 puts("\n*** Testing thread delete function ***");
582
583 MyDetachedThread *thread0 = new MyDetachedThread(30, 'W');
584
585 thread0->Delete();
586
587 puts("\nDeleted a thread which didn't start to run yet.");
588
589 MyDetachedThread *thread1 = new MyDetachedThread(30, 'Y');
590
591 thread1->Run();
592
593 wxThread::Sleep(300);
594
595 thread1->Delete();
596
597 puts("\nDeleted a running thread.");
598
599 MyDetachedThread *thread2 = new MyDetachedThread(30, 'Z');
600
601 thread2->Run();
602
603 wxThread::Sleep(300);
604
605 thread2->Pause();
606
607 thread2->Delete();
608
609 puts("\nDeleted a sleeping thread.");
610
611 MyJoinableThread thread3(20);
612 thread3.Run();
613
614 thread3.Delete();
615
616 puts("\nDeleted a joinable thread.");
617
618 MyJoinableThread thread4(2);
619 thread4.Run();
620
621 wxThread::Sleep(300);
622
623 thread4.Delete();
624
625 puts("\nDeleted a joinable thread which already terminated.");
626
627 puts("");
628 }
629
630 #endif // TEST_THREADS
631
632 // ----------------------------------------------------------------------------
633 // arrays
634 // ----------------------------------------------------------------------------
635
636 #ifdef TEST_ARRAYS
637
638 void PrintArray(const char* name, const wxArrayString& array)
639 {
640 printf("Dump of the array '%s'\n", name);
641
642 size_t nCount = array.GetCount();
643 for ( size_t n = 0; n < nCount; n++ )
644 {
645 printf("\t%s[%u] = '%s'\n", name, n, array[n].c_str());
646 }
647 }
648
649 #endif // TEST_ARRAYS
650
651 // ----------------------------------------------------------------------------
652 // strings
653 // ----------------------------------------------------------------------------
654
655 #ifdef TEST_STRINGS
656
657 #include "wx/timer.h"
658
659 void TestString()
660 {
661 wxStopWatch sw;
662
663 wxString a, b, c;
664
665 a.reserve (128);
666 b.reserve (128);
667 c.reserve (128);
668
669 for (int i = 0; i < 1000000; ++i)
670 {
671 a = "Hello";
672 b = " world";
673 c = "! How'ya doin'?";
674 a += b;
675 a += c;
676 c = "Hello world! What's up?";
677 if (c != a)
678 c = "Doh!";
679 }
680
681 printf ("TestString elapsed time: %ld\n", sw.Time());
682 }
683
684 void TestPChar()
685 {
686 wxStopWatch sw;
687
688 char a [128];
689 char b [128];
690 char c [128];
691
692 for (int i = 0; i < 1000000; ++i)
693 {
694 strcpy (a, "Hello");
695 strcpy (b, " world");
696 strcpy (c, "! How'ya doin'?");
697 strcat (a, b);
698 strcat (a, c);
699 strcpy (c, "Hello world! What's up?");
700 if (strcmp (c, a) == 0)
701 strcpy (c, "Doh!");
702 }
703
704 printf ("TestPChar elapsed time: %ld\n", sw.Time());
705 }
706
707 #endif // TEST_STRINGS
708
709 // ----------------------------------------------------------------------------
710 // entry point
711 // ----------------------------------------------------------------------------
712
713 int main(int argc, char **argv)
714 {
715 if ( !wxInitialize() )
716 {
717 fprintf(stderr, "Failed to initialize the wxWindows library, aborting.");
718 }
719
720 #ifdef TEST_STRINGS
721 TestPChar();
722 TestString();
723 #endif // TEST_STRINGS
724
725 #ifdef TEST_ARRAYS
726 wxArrayString a1;
727 a1.Add("tiger");
728 a1.Add("cat");
729 a1.Add("lion");
730 a1.Add("dog");
731 a1.Add("human");
732 a1.Add("ape");
733
734 puts("*** Initially:");
735
736 PrintArray("a1", a1);
737
738 wxArrayString a2(a1);
739 PrintArray("a2", a2);
740
741 wxSortedArrayString a3(a1);
742 PrintArray("a3", a3);
743
744 puts("*** After deleting a string from a1");
745 a1.Remove(2);
746
747 PrintArray("a1", a1);
748 PrintArray("a2", a2);
749 PrintArray("a3", a3);
750
751 puts("*** After reassigning a1 to a2 and a3");
752 a3 = a2 = a1;
753 PrintArray("a2", a2);
754 PrintArray("a3", a3);
755 #endif // TEST_ARRAYS
756
757 #ifdef TEST_DIR
758 TestDirEnum();
759 #endif // TEST_DIR
760
761 #ifdef TEST_LOG
762 wxString s;
763 for ( size_t n = 0; n < 8000; n++ )
764 {
765 s << (char)('A' + (n % 26));
766 }
767
768 wxString msg;
769 msg.Printf("A very very long message: '%s', the end!\n", s.c_str());
770
771 // this one shouldn't be truncated
772 printf(msg);
773
774 // but this one will because log functions use fixed size buffer
775 // (note that it doesn't need '\n' at the end neither - will be added
776 // by wxLog anyhow)
777 wxLogMessage("A very very long message 2: '%s', the end!", s.c_str());
778 #endif // TEST_LOG
779
780 #ifdef TEST_THREADS
781 int nCPUs = wxThread::GetCPUCount();
782 printf("This system has %d CPUs\n", nCPUs);
783 if ( nCPUs != -1 )
784 wxThread::SetConcurrency(nCPUs);
785
786 if ( argc > 1 && argv[1][0] == 't' )
787 wxLog::AddTraceMask("thread");
788
789 if ( 1 )
790 TestDetachedThreads();
791 if ( 1 )
792 TestJoinableThreads();
793 if ( 1 )
794 TestThreadSuspend();
795 if ( 1 )
796 TestThreadDelete();
797
798 #endif // TEST_THREADS
799
800 #ifdef TEST_LONGLONG
801 if ( 0 )
802 TestSpeed();
803 if ( 1 )
804 TestDivision();
805 #endif // TEST_LONGLONG
806
807 #ifdef TEST_MIME
808 TestMimeEnum();
809 #endif // TEST_MIME
810
811 #ifdef TEST_TIME
812 TestTimeStatic();
813 TestTimeSet();
814 TestTimeZones();
815 TestTimeRange();
816 TestTimeJDN();
817 #endif // TEST_TIME
818
819 wxUninitialize();
820
821 return 0;
822 }