1 /*
2
3 *************************************************************************
4
5 ArmageTron -- Just another Tron Lightcycle Game in 3D.
6 Copyright (C) 2000 Manuel Moos (manuel@moosnet.de)
7
8 **************************************************************************
9
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 ***************************************************************************
25
26 */
27
28 #ifndef TRECORDER_H_INCLUDED
29 #define TRECORDER_H_INCLUDED
30
31 #ifdef DEBUG
32 #ifndef DEBUG_DIFFERENCE
33 #define DEBUG_DIFFERENCE
34 #endif
35 #endif
36
37 // self include
38 #ifndef TRECORDER_H_INCLUDED
39 #include "tRecorder.h"
40 #endif
41
42 #include "tString.h"
43
44 // #include "tRecorderInternal.h"
45
46 // *****************************************************************************
47 // Helpers required to work around VisualC's iability to handle out-of-line
48 // template members. Just ignore them.
49 // *****************************************************************************
50
51 //! recording funtions that take one piece of data
52 template< class BLOCK >
53 class tRecorderTemplate1
54 {
55 public:
56 static bool Archive( bool strict, char const * section ); //!< Archives an empty section
57 };
58
59 //! recording funtions that take two pieces of data
60 template< class BLOCK, typename DATA >
61 class tRecorderTemplate2
62 {
63 public:
64 static bool Archive( bool strict, char const * section, DATA data ); //!< Archives a section with one piece of data
65 };
66
67 //! recording funtions that take two pieces of data and a block
68 template< class BLOCK, typename DATA1, typename DATA2 >
69 class tRecorderTemplate3
70 {
71 public:
72 static bool Archive( bool strict, char const * section, DATA1 data1, DATA2 data2 ); //!< Archives a section with two pieces of data
73 };
74
75 // *****************************************************************************
76 // tRecorder: simple recording interface. Most users will only need this.
77 // *****************************************************************************
78
79 class tRecordingBlock;
80 class tPlaybackBlock;
81
82 //! non-templated base class of recorder
83 class tRecorderBase
84 {
85 public:
86 static bool IsRecording(); //!< returns whether there is a recording running
87 static bool IsPlayingBack(); //!< returns whether there is a playback running
88 static bool IsRunning(); //!< returns whether recording or playback are running
89 };
90
91 //! simple interface to recording functionality
92 class tRecorder: public tRecorderBase
93 {
94 public:
95 static bool Record( char const * section ); //!< Records an empty section
96 static bool Playback( char const * section ); //!< Plays back an empty section
97 static bool PlaybackStrict( char const * section ); //!< Plays back an empty section, making sure it exists in the recording
98
99 //! Records a section with one piece of data
100 template< class DATA >
Record(char const * section,DATA const & data)101 static bool Record ( char const * section, DATA const & data )
102 { return tRecorderTemplate2< tRecordingBlock, DATA const & >::Archive( false, section, data ); }
103
104 //! Plays back a section with one piece of data
105 template< class DATA >
Playback(char const * section,DATA & data)106 static bool Playback( char const * section, DATA & data )
107 { return tRecorderTemplate2< tPlaybackBlock, DATA & >::Archive( false, section, data ); }
108
109 //! Plays back a section with one piece of data, making sure it exists in the recording
110 template< class DATA >
PlaybackStrict(char const * section,DATA & data)111 static bool PlaybackStrict( char const * section, DATA & data )
112 { return tRecorderTemplate2< tPlaybackBlock, DATA & >::Archive( true, section, data ); }
113
114 //! Records a section with two pieces of data
115 template< class DATA1, class DATA2 >
Record(char const * section,DATA1 const & data1,DATA2 const & data2)116 static bool Record( char const * section, DATA1 const & data1, DATA2 const & data2 )
117 { return tRecorderTemplate3< tRecordingBlock, DATA1 const & , DATA2 const & >::Archive( false, section, data1, data2 ); }
118
119 //!< Plays back a section with two pieces of data
120 template< class DATA1, class DATA2 >
Playback(char const * section,DATA1 & data1,DATA2 & data2)121 static bool Playback( char const * section, DATA1 & data1, DATA2 & data2 )
122 { return tRecorderTemplate3< tPlaybackBlock, DATA1 &, DATA2 & >::Archive( false, section, data1, data2 ); }
123
124 //! Plays back a section with two pieces of data, making sure it exists in the recording
125 template< class DATA1, class DATA2 >
PlaybackStrict(char const * section,DATA1 & data1,DATA2 & data2)126 static bool PlaybackStrict( char const * section, DATA1 & data1, DATA2 & data2 )
127 { return tRecorderTemplate3< tPlaybackBlock, DATA1 &, DATA2 & >::Archive( true, section, data1, data2 ); }
128 };
129
130 class tPath;
131
132 //! text file loading recorder
133 class tTextFileRecorder: public tRecorderBase
134 {
135 public:
136 tTextFileRecorder();
137 ~tTextFileRecorder();
138
139 //! opens a text file for reading
140 bool Open( tPath const & searchPath, char const * fileName );
141
142 //! constructor, opening a file directly (status can be queried later with EndOfFile)
143 tTextFileRecorder( tPath const & searchPath, char const * fileName );
144
145 //! end of file query
146 bool EndOfFile() const;
147
148 //! read one line, give it back as a stream
149 std::string GetLine();
150 private:
151 // disable copying
152 tTextFileRecorder(tTextFileRecorder const &);
153 tTextFileRecorder & operator = (tTextFileRecorder const &);
154
155 std::ifstream * stream_; //! the real stream to read from
156 bool eof_; //! flag indicating end of file
157 };
158
159 //! typedef for easier handling
160 // typedef tRecorderTemplate<int> tRecorder;
161
162 // *****************************************************************************
163 // helper classes for converting data before it gets archived
164 // *****************************************************************************
165
166 //! type modifying class mapping types in memory to types to stream
167 template< class T > struct tTypeToStream
168 {
169 typedef T TOSTREAM; //!< type to put into the stream
170 typedef int DUMMYREQUIRED; //!< change this type to "int *" to indicate the conversion is required
171 };
172
173 //! macro declaring that type TYPE should be converted to type STREAM before
174 // recording (and back after playback) by specializing the tTypeToStream class template
175 #define tRECORD_AS( TYPE, STREAM ) \
176 template<> struct tTypeToStream< TYPE > \
177 { \
178 typedef STREAM TOSTREAM; \
179 typedef int * DUMMYREQUIRED; \
180 } \
181
182 //! macro for recording enums: convert them to int.
183 #define tRECORDING_ENUM( TYPE ) tRECORD_AS( TYPE, int )
184
185 // record chars as ints for human readability
186 tRECORD_AS( char, int );
187 tRECORD_AS( unsigned char, int );
188
189 //! persistable string class
190 class tLineString: public tString
191 {
192 public:
193 tLineString( tString const & ); //! copy constructor
194 tLineString(); //! default constructor
195 ~tLineString(); //! destructor
196 };
197
198 //! persistent string writing operator
199 std::ostream & operator << ( std::ostream & s, tLineString const & line );
200
201 //! persistent string reading operator
202 std::istream & operator >> ( std::istream & s, tLineString & line );
203
204 //! record strings as line strings
205 tRECORD_AS( tString, tLineString );
206
207 // *****************************************************************************
208 // support for debugging only recording (for intermediate data)
209 // *****************************************************************************
210
211 //! debug recording synchronization test class
212 class tRecorderSyncBase
213 {
214 public:
215 //! returns the current debug level of the playback
216 static int GetDebugLevelPlayback();
217
218 //! returns the current debug level of the recording
219 static int GetDebugLevelRecording();
220 };
221
222 //! debug recording synchronization test class
223 template< class DATA >
224 class tRecorderSync: public tRecorderSyncBase
225 {
226 public:
227 //! Archives a bit of data for reference
228 static void Archive( char const * section, int debugLevel, DATA & data );
229
230 private:
231 //! Calculates a suitable difference between two bits of data
232 static float GetDifference( DATA const & a, DATA const & b );
233 };
234
235 // *****************************************************************************
236 // another helper class
237 // *****************************************************************************
238
239 //! class taking the ugly implementation part of tRecordingBlock and tPlaybackBlock
240 template < class DATA > class tRecorderBlockHelper
241 {
242 public:
243 static void Write ( std::ostream & stream, DATA const & data, int nodummyrequired ); //!< writes a piece of data using a dummy
244 static void Write ( std::ostream & stream, DATA const & data, int * dummyrequired ); //!< writes a piece of data using a dummy
245
246 static void Read ( std::istream & stream, DATA & data, int nodummyrequired ); //!< reads a piece of data using a dummy
247 static void Read ( std::istream & stream, DATA & data, int * dummyrequired ); //!< reads a piece of data using a dummy
248 };
249
250 // *****************************************************************************
251 // recording blocks for stuffing more data inside a section than two elements
252 // *****************************************************************************
253
254 class tRecording;
255
256 //! a block of data to record (for more advanced data storage ), base class
257 class tRecordingBlockBase
258 {
259 public:
260 bool Initialize( char const * section, tRecording * recording ); //!< initializes this for recording
261 bool Initialize( char const * section ); //!< initializes this for recording
262
263 void Separator(); //!< separates two recorded elements (more than usual)
264 static tRecording * GetArchive(); //!< returns the active recording
265 protected:
266 tRecordingBlockBase(); //!< default constructor
267 ~tRecordingBlockBase(); //!< ends a recording block
268
269 std::ostream & GetRecordingStream() const; //!< returns the stream to record to
270
271 bool separate_; //!< flag indicating whether a separation is needed before the next data element
272 private:
273 tRecording * recording_; //!< the recording to record to
274 };
275
276 //! a block of data to record (for more advanced data storage ), implementation
277 class tRecordingBlock: public tRecordingBlockBase
278 {
279 public:
280 tRecordingBlock(); //!< default constructor
281 ~tRecordingBlock(); //!< ends a recording block
282
283 //! writes a piece of data
284 template< class T > tRecordingBlock & operator << ( T const & data ) { return Write( data ); }
285
286 //! writes a piece of data
Archive(T const & data)287 template< class T > tRecordingBlock & Archive ( T const & data ) { return Write( data ); }
288
289 //! writes a piece of data
Write(T const & data)290 template< class T > tRecordingBlock & Write ( T const & data )
291 {
292 // get stream
293 std::ostream & stream = GetRecordingStream();
294
295 // add separator
296 if ( separate_ )
297 stream << ' ';
298 separate_ = true;
299
300 // delegate to dummy using or dummyless function
301 typename tTypeToStream< T >::DUMMYREQUIRED dummyRequired = 0;
302 tRecorderBlockHelper< T >::Write( stream, data, dummyRequired );
303
304 return *this;
305 }
306 };
307
308 // *****************************************************************************
309
310 class tPlayback;
311
312 //! a block of data to play back.
313 class tPlaybackBlockBase
314 {
315 public:
316 bool Initialize( char const * section, tPlayback * playback ); //!< initializes this for recording
317 bool Initialize( char const * section ); //!< initializes this for recording
318
319 void Separator() const; //!< separate output (Nothing done here while playing back)
320 static tPlayback * GetArchive(); //!< returns the active playback
321 protected:
322 tPlaybackBlockBase(); //!< default constructor
323 ~tPlaybackBlockBase(); //!< ends a playback block
324
325 std::istream & GetPlaybackStream() const; //!< returns the stream to playback from
326
327 private:
328 tPlayback * playback_; //!< the playback to read from
329 };
330
331 //! a block of data to play back.
332 class tPlaybackBlock: public tPlaybackBlockBase
333 {
334 public:
335 tPlaybackBlock(); //!< default constructor
336 ~tPlaybackBlock(); //!< ends a playback block
337
338 //!< reads a piece of data
339 template< class T > tPlaybackBlock & operator >> ( T & data ){ return Read( data ); }
340
341 //!< reads a piece aof data
Archive(T & data)342 template< class T > tPlaybackBlock & Archive ( T & data ){ return Read( data ); }
343
344 //!< reads a piece of data
Read(T & data)345 template< class T > tPlaybackBlock & Read ( T & data )
346 {
347 // delegate to dummy using or dummyless function
348 typename tTypeToStream< T >::DUMMYREQUIRED dummyrequired = 0;
349 tRecorderBlockHelper< T >::Read( GetPlaybackStream(), data, dummyrequired );
350
351 return *this;
352 }
353 };
354
355 //! typedefs for easier handling
356 // typedef tRecordingBlockTemplate< int > tRecordingBlock;
357 // typedef tPlaybackBlockTemplate< int > tPlaybackBlock;
358
359 // Note: both tRecordingBlock and tPlaybackBlock share common mebe fuctions. See uInputQueue.cpp
360 // (or the tRecorderTemplate::Archive implementation) how to
361 // exploit this with templates to make sure you read exaclty the same data as you write.
362
363 // *****************************************************************************
364 // * Implementation
365 // *****************************************************************************
366
367 /*
368
369 // *******************************************************************************************
370 // *
371 // * Record
372 // *
373 // *******************************************************************************************
374 //!
375 //! @param section the name of the section to record or play back
376 //! @param data the data to archive
377 //! @return true on success
378 //!
379 // *******************************************************************************************
380
381 template< class DUMMY >
382 template< class DATA >
383 bool tRecorderTemplate< DUMMY >::Record( char const * section, DATA const & data )
384 {
385 // delegate
386 return Archive< tRecordingBlock >( false, section, data );
387 }
388
389 // *******************************************************************************************
390 // *
391 // * Playback
392 // *
393 // *******************************************************************************************
394 //!
395 //! @param section the name of the section to record or play back
396 //! @param data the data to archive
397 //! @return true on success
398 //!
399 // *******************************************************************************************
400
401 template< class DUMMY >
402 template< class DATA >
403 bool tRecorderTemplate< DUMMY >::Playback( char const * section, DATA & data )
404 {
405 // delegate
406 return Archive< tPlaybackBlock >( false, section, data );
407 }
408
409 // *******************************************************************************************
410 // *
411 // * PlaybackStrict
412 // *
413 // *******************************************************************************************
414 //!
415 //! @param section the name of the section to record or play back
416 //! @param data the data to archive
417 //! @return true on success
418 //!
419 // *******************************************************************************************
420
421 template< class DUMMY >
422 template< class DATA >
423 bool tRecorderTemplate< DUMMY >::PlaybackStrict( char const * section, DATA & data )
424 {
425 // delegate
426 return Archive< tPlaybackBlock >( true, section, data );
427 }
428
429 // *******************************************************************************************
430 // *
431 // * Record
432 // *
433 // *******************************************************************************************
434 //!
435 //! @param section the name of the section to record or play back
436 //! @param data1 first bit of data to archive
437 //! @param data2 second bit of data to archive
438 //! @return true on success
439 //!
440 // *******************************************************************************************
441
442 template< class DUMMY >
443 template< class DATA1, class DATA2 >
444 bool tRecorderTemplate< DUMMY >::Record( char const * section, DATA1 const & data1, DATA2 const & data2 )
445 {
446 // delegate
447 return Archive< tRecordingBlock >( false, section, data1, data2 );
448 }
449
450 // *******************************************************************************************
451 // *
452 // * Playback
453 // *
454 // *******************************************************************************************
455 //!
456 //! @param section the name of the section to record or play back
457 //! @param data1 first bit of data to archive
458 //! @param data2 second bit of data to archive
459 //! @return true on success
460 //!
461 // *******************************************************************************************
462
463 template< class DUMMY >
464 template< class DATA1, class DATA2 >
465 bool tRecorderTemplate< DUMMY >::Playback( char const * section, DATA1 & data1, DATA2 & data2 )
466 {
467 // delegate
468 return Archive< tPlaybackBlock >( false, section, data1, data2 );
469 }
470
471 // *******************************************************************************************
472 // *
473 // * PlaybackStrict
474 // *
475 // *******************************************************************************************
476 //!
477 //! @param section the name of the section to record or play back
478 //! @param data1 first bit of data to archive
479 //! @param data2 second bit of data to archive
480 //! @return true on success
481 //!
482 // *******************************************************************************************
483
484 template< class DUMMY >
485 template< class DATA1, class DATA2 >
486 bool tRecorderTemplate< DUMMY >::PlaybackStrict( char const * section, DATA1 & data1, DATA2 & data2 )
487 {
488 // delegate
489 return Archive< tPlaybackBlock >( true, section, data1, data2 );
490 }
491
492 // *******************************************************************************************
493 // *
494 // * Archive
495 // *
496 // *******************************************************************************************
497 //!
498 //! @param strict
499 //! @param section the name of the section to record or play back
500 //! @return true on success
501 //!
502 // *******************************************************************************************
503
504 template< class DUMMY >
505 template< class BLOCK >
506 bool tRecorderTemplate< DUMMY >::Archive( bool strict, char const * section )
507 {
508 // create recording/playback block
509 BLOCK block;
510
511 // initialize
512 if ( block.Initialize( section ) )
513 {
514 // return success
515 return true;
516 }
517
518 // report failure
519 tASSERT( !strict || !BLOCK::GetArchive() );
520 return false;
521 }
522
523 // *******************************************************************************************
524 // *
525 // * Archive
526 // *
527 // *******************************************************************************************
528 //!
529 //! @param strict
530 //! @param section the name of the section to record or play back
531 //! @param data
532 //! @return true on success
533 //!
534 // *******************************************************************************************
535
536 template< class DUMMY >
537 template< class BLOCK, class DATA >
538 bool tRecorderTemplate< DUMMY >::Archive( bool strict, char const * section, DATA & data )
539 {
540 // create recording/playback block
541 BLOCK block;
542
543 // initialize
544 if ( block.Initialize( section ) )
545 {
546 // successfully initialized: archive data
547 block.Archive( data );
548
549 // return success
550 return true;
551 }
552
553 // report failure
554 tASSERT( !strict || !BLOCK::GetArchive() );
555 return false;
556 }
557
558 // *******************************************************************************************
559 // *
560 // * Archive
561 // *
562 // *******************************************************************************************
563 //!
564 //! @param strict
565 //! @param section the name of the section to record or play back
566 //! @param data1 first bit of data to archive
567 //! @param data2 second bit of data to archive
568 //! @return true on success
569 //!
570 // *******************************************************************************************
571
572 template< class DUMMY >
573 template< class BLOCK, class DATA1, class DATA2 >
574 bool tRecorderTemplate< DUMMY >::Archive( bool strict, char const * section, DATA1 & data1, DATA2 & data2 )
575 {
576 // create recording/playback block
577 BLOCK block;
578
579 // initialize
580 if ( block.Initialize( section ) )
581 {
582 // successfully initialized: archive data
583 block.Archive( data1 ).Archive( data2 );
584
585 // return success
586 return true;
587 }
588
589 // report failure
590 tASSERT( !strict || !BLOCK::GetArchive() );
591 return false;
592 }
593
594 // *******************************************************************************************
595 // *******************************************************************************************
596 // *******************************************************************************************
597 // *******************************************************************************************
598
599 // *******************************************************************************************
600 // *
601 // * tRecordingBlockTemplate
602 // *
603 // *******************************************************************************************
604 //!
605 //!
606 // *******************************************************************************************
607
608 template< class DUMMY >
609 tRecordingBlockTemplate< DUMMY >::tRecordingBlockTemplate( void )
610 {
611 }
612
613 // *******************************************************************************************
614 // *
615 // * ~tRecordingBlockTemplate
616 // *
617 // *******************************************************************************************
618 //!
619 //!
620 // *******************************************************************************************
621
622 template< class DUMMY >
623 tRecordingBlockTemplate< DUMMY >::~tRecordingBlockTemplate( void )
624 {
625 }
626
627 // *******************************************************************************************
628 // *
629 // * operator <<
630 // *
631 // *******************************************************************************************
632 //!
633 //! @param data the data to archive
634 //! @return reference to this for chaining
635 //!
636 // *******************************************************************************************
637
638 template< class DUMMY >
639 template< class T >
640 tRecordingBlockTemplate< DUMMY > & tRecordingBlockTemplate< DUMMY >::operator <<( T const & data )
641 {
642 // delegate
643 return Write( data );
644 }
645
646 // *******************************************************************************************
647 // *
648 // * Archive
649 // *
650 // *******************************************************************************************
651 //!
652 //! @param data the data to archive
653 //! @return reference to this for chaining
654 //!
655 // *******************************************************************************************
656
657 template< class DUMMY >
658 template< class T >
659 tRecordingBlockTemplate< DUMMY > & tRecordingBlockTemplate< DUMMY >::Archive( T const & data )
660 {
661 // delegate
662 return Write( data );
663 }
664
665 // *******************************************************************************************
666 // *
667 // * Write
668 // *
669 // *******************************************************************************************
670 //!
671 //! @param data the data to archive
672 //! @return reference to this for chaining
673 //!
674 // *******************************************************************************************
675
676 template< class DUMMY >
677 template< class T >
678 tRecordingBlockTemplate< DUMMY > & tRecordingBlockTemplate< DUMMY >::Write( T const & data )
679 {
680 // get stream
681 std::ostream & stream = GetRecordingStream();
682
683 // add small separator
684 if (separate_)
685 stream << ' ';
686 separate_ = true;
687
688 // delegate to dummy using or dummyless function
689 typename tTypeToStream< T >::DUMMYREQUIRED dummyrequired = 0;
690 Write( data, dummyrequired );
691
692 return *this;
693 }
694
695 // *******************************************************************************************
696 // *
697 // * Write
698 // *
699 // *******************************************************************************************
700 //!
701 //! @param data the data to archive
702 //! @param nodummyrequired dummy parameter indicating by type that no conversion is required
703 //!
704 // *******************************************************************************************
705
706 template< class DUMMY >
707 template< class T >
708 void tRecordingBlockTemplate< DUMMY >::Write( T const & data, int nodummyrequired )
709 {
710 // get stream
711 std::ostream & stream = GetRecordingStream();
712
713 // add small separator
714 stream << ' ';
715
716 // write
717 stream << data;
718
719 }
720
721 // *******************************************************************************************
722 // *
723 // * Write
724 // *
725 // *******************************************************************************************
726 //!
727 //! @param data the data to archive
728 //! @param dummyrequired dummy parameter indicating by type that conversion is required
729 //!
730 // *******************************************************************************************
731
732 template< class DUMMY >
733 template< class T >
734 void tRecordingBlockTemplate< DUMMY >::Write( T const & data, int * dummyrequired )
735 {
736 // get stream
737 std::ostream & stream = GetRecordingStream();
738
739 // write ( converted )
740 typedef typename tTypeToStream< T >::TOSTREAM TOSTREAM;
741 TOSTREAM dummy = static_cast< TOSTREAM >( data );
742 stream << dummy;
743 }
744
745 // *******************************************************************************************
746 // *******************************************************************************************
747 // *******************************************************************************************
748 // *******************************************************************************************
749
750 // *******************************************************************************************
751 // *
752 // * tPlaybackBlockTemplate
753 // *
754 // *******************************************************************************************
755 //!
756 //!
757 // *******************************************************************************************
758
759 template< class DUMMY >
760 tPlaybackBlockTemplate< DUMMY >::tPlaybackBlockTemplate( void )
761 {
762 }
763
764 // *******************************************************************************************
765 // *
766 // * ~tPlaybackBlockTemplate
767 // *
768 // *******************************************************************************************
769 //!
770 //!
771 // *******************************************************************************************
772
773 template< class DUMMY >
774 tPlaybackBlockTemplate< DUMMY >::~tPlaybackBlockTemplate( void )
775 {
776 }
777
778 // *******************************************************************************************
779 // *
780 // * operator >>
781 // *
782 // *******************************************************************************************
783 //!
784 //! @param data the data to archive
785 //! @return reference to this for chaining
786 //!
787 // *******************************************************************************************
788
789 template< class DUMMY >
790 template< class T >
791 tPlaybackBlockTemplate< DUMMY > & tPlaybackBlockTemplate< DUMMY >::operator >>( T & data )
792 {
793 // delegate
794 return Read( data );
795 }
796
797 // *******************************************************************************************
798 // *
799 // * Archive
800 // *
801 // *******************************************************************************************
802 //!
803 //! @param data the data to archive
804 //! @return reference to this for chaining
805 //!
806 // *******************************************************************************************
807
808 template< class DUMMY >
809 template< class T >
810 tPlaybackBlockTemplate< DUMMY > & tPlaybackBlockTemplate< DUMMY >::Archive( T & data )
811 {
812 // delegate
813 return Read( data );
814 }
815
816 // *******************************************************************************************
817 // *
818 // * Read
819 // *
820 // *******************************************************************************************
821 //!
822 //! @param data the data to archive
823 //! @return reference to this for chaining
824 //!
825 // *******************************************************************************************
826
827 template< class DUMMY >
828 template< class T >
829 tPlaybackBlockTemplate< DUMMY > & tPlaybackBlockTemplate< DUMMY >::Read( T & data )
830 {
831 // delegate to dummy using or dummyless function
832 typename tTypeToStream< T >::DUMMYREQUIRED dummyrequired = 0;
833 Read( data, dummyrequired );
834
835 return *this;
836 }
837
838 // *******************************************************************************************
839 // *
840 // * Read
841 // *
842 // *******************************************************************************************
843 //!
844 //! @param data the data to archive
845 //! @param nodummyrequired dummy parameter indicating by type that no conversion is required
846 //!
847 // *******************************************************************************************
848
849 template< class DUMMY >
850 template< class T >
851 void tPlaybackBlockTemplate< DUMMY >::Read( T & data, int nodummyrequired )
852 {
853 // get stream
854 std::istream & stream = GetPlaybackStream();
855 tASSERT( stream.good() );
856
857 // read
858 stream >> data;
859 }
860
861 // *******************************************************************************************
862 // *
863 // * Read
864 // *
865 // *******************************************************************************************
866 //!
867 //! @param data the data to archive
868 //! @param dummyrequired dummy parameter indicating by type that conversion is required
869 //!
870 // *******************************************************************************************
871
872 template< class DUMMY >
873 template< class T >
874 void tPlaybackBlockTemplate< DUMMY >::Read( T & data, int * dummyrequired )
875 {
876 // get stream
877 std::istream & stream = GetPlaybackStream();
878 tASSERT( stream.good() );
879
880 // read ( with conversion )
881 typedef typename tTypeToStream< T >::TOSTREAM TOSTREAM;
882 TOSTREAM dummy ;
883 stream >> dummy;
884 data = static_cast< T >( dummy );
885 }
886
887 */
888
889 // ******************************************************************************************
890 // *
891 // * Archive
892 // *
893 // ******************************************************************************************
894 //!
895 //! @param section section to archive to
896 //! @param level debug level of the data (lower levels get archived sooner)
897 //! @param data data to archive
898 //!
899 // ******************************************************************************************
900
901 template< class DATA >
Archive(char const * section,int level,DATA & data)902 void tRecorderSync< DATA >::Archive( char const * section, int level, DATA & data )
903 {
904 // see if it is really a DEBUG only section
905 tASSERT( section && *section == '_' );
906
907 if ( level <= GetDebugLevelPlayback() )
908 {
909 DATA copy = data;
910
911 // read data from archive
912 if ( tRecorder::PlaybackStrict( section, copy ) )
913 {
914 #ifdef DEBUG_DIFFERENCE
915 // determine difference
916 REAL diff = GetDifference( data, copy );
917
918 static REAL alarmDiff = EPS;
919 if ( diff > alarmDiff )
920 {
921 alarmDiff = diff * 2;
922 REAL st_GetDifference( REAL a, REAL b);
923 REAL st_GetDifference( int a, int b);
924 REAL st_GetDifference( tString const & a, tString const & b );
925 std::cout << "Syncing difference found: " << data << "!=" << copy << " by " << diff << "\n";
926 st_Breakpoint();
927 }
928 #endif
929
930 // restore data, hoping that the playback can take the little bump
931 if ( level <= GetDebugLevelRecording() )
932 {
933 data = copy;
934 }
935 }
936 else if ( tRecorder::IsPlayingBack() )
937 {
938 std::cout << "Syncing difference found: expected " << section << ".\n";
939
940 st_Breakpoint();
941 }
942 }
943
944 // archive data
945 if ( level <= GetDebugLevelRecording() )
946 tRecorder::Record( section, data );
947 }
948
949 REAL st_GetDifference( REAL a, REAL b);
950 REAL st_GetDifference( int a, int b);
951 REAL st_GetDifference( unsigned int a, unsigned int b);
952 REAL st_GetDifference( long unsigned int a, long unsigned int b);
953 REAL st_GetDifference( tString const & a, tString const & b );
954
955 // ******************************************************************************************
956 // *
957 // * GetDifference
958 // *
959 // ******************************************************************************************
960 //!
961 //! @param a object a
962 //! @param b object b
963 //! @return |a-b|, interpreted as appropriate
964 //!
965 // ******************************************************************************************
966
967 template< class DATA >
GetDifference(DATA const & a,DATA const & b)968 float tRecorderSync< DATA >::GetDifference( DATA const & a, DATA const & b )
969 {
970 return st_GetDifference( a, b );
971 }
972
973 // ******************************************************************************************
974 // *
975 // * Archive
976 // *
977 // ******************************************************************************************
978 //!
979 //! @param strict true if the success should be asserted
980 //! @param section the name of the section to record or play back
981 //! @return true on success
982 //!
983 // ******************************************************************************************
984
985 template< class BLOCK >
Archive(bool strict,char const * section)986 bool tRecorderTemplate1< BLOCK >::Archive( bool strict, char const * section )
987 {
988 // create recording/playback block
989 BLOCK block;
990
991 // initialize
992 if ( block.Initialize( section ) )
993 {
994 // return success
995 return true;
996 }
997
998 // report failure
999 tASSERT( !strict || !BLOCK::GetArchive() );
1000 return false;
1001 }
1002
1003 // ******************************************************************************************
1004 // *
1005 // * Archive
1006 // *
1007 // ******************************************************************************************
1008 //!
1009 //! @param strict true if the success should be asserted
1010 //! @param section the name of the section to record or play back
1011 //! @param data bit of data to archive
1012 //! @return true on success
1013 //!
1014 // ******************************************************************************************
1015
1016 template< class BLOCK, typename DATA >
Archive(bool strict,char const * section,DATA data)1017 bool tRecorderTemplate2< BLOCK, DATA >::Archive( bool strict, char const * section, DATA data )
1018 {
1019 // create recording/playback block
1020 BLOCK block;
1021
1022 // initialize
1023 if ( block.Initialize( section ) )
1024 {
1025 // successfully initialized: archive data
1026 block.Archive( data );
1027
1028 // return success
1029 return true;
1030 }
1031
1032 // report failure
1033 tASSERT( !strict || !BLOCK::GetArchive() );
1034 return false;
1035 }
1036
1037 // ******************************************************************************************
1038 // *
1039 // * Archive
1040 // *
1041 // ******************************************************************************************
1042 //!
1043 //! @param strict true if the success should be asserted
1044 //! @param section the name of the section to record or play back
1045 //! @param data1 first bit of data to archive
1046 //! @param data2 second bit of data to archive
1047 //! @return true on success
1048 //!
1049 // ******************************************************************************************
1050
1051 template< class BLOCK, typename DATA1, typename DATA2 >
Archive(bool strict,char const * section,DATA1 data1,DATA2 data2)1052 bool tRecorderTemplate3< BLOCK, DATA1, DATA2 >::Archive( bool strict, char const * section, DATA1 data1, DATA2 data2 )
1053 {
1054 // create recording/playback block
1055 BLOCK block;
1056
1057 // initialize
1058 if ( block.Initialize( section ) )
1059 {
1060 // successfully initialized: archive data
1061 block.Archive( data1 ).Archive( data2 );
1062
1063 // return success
1064 return true;
1065 }
1066
1067 // report failure
1068 tASSERT( !strict || !BLOCK::GetArchive() );
1069 return false;
1070 }
1071
1072 // ******************************************************************************************
1073 // *
1074 // * Write
1075 // *
1076 // ******************************************************************************************
1077 //!
1078 //! @param stream the stream to write to
1079 //! @param data the data to archive
1080 //! @param nodummyrequired dummy parameter indicating by type that no conversion is required
1081 //!
1082 // ******************************************************************************************
1083
1084 template< class DATA >
Write(std::ostream & stream,DATA const & data,int nodummyrequired)1085 void tRecorderBlockHelper< DATA >::Write( std::ostream & stream, DATA const & data, int nodummyrequired )
1086 {
1087 // write
1088 stream << data;
1089 }
1090
1091 // ******************************************************************************************
1092 // *
1093 // * Write
1094 // *
1095 // ******************************************************************************************
1096 //!
1097 //! @param stream the stream to write to
1098 //! @param data the data to archive
1099 //! @param dummyrequired dummy parameter indicating by type that conversion is required
1100 //!
1101 // ******************************************************************************************
1102
1103 template< class DATA >
Write(std::ostream & stream,DATA const & data,int * dummyrequired)1104 void tRecorderBlockHelper< DATA >::Write( std::ostream & stream, DATA const & data, int * dummyrequired )
1105 {
1106 // write ( converted )
1107 typedef typename tTypeToStream< DATA >::TOSTREAM TOSTREAM;
1108 TOSTREAM dummy = static_cast< TOSTREAM >( data );
1109 stream << dummy;
1110 }
1111
1112 // ******************************************************************************************
1113 // *
1114 // * Read
1115 // *
1116 // ******************************************************************************************
1117 //!
1118 //! @param stream the stream to read from
1119 //! @param data the data to archive
1120 //! @param nodummyrequired dummy parameter indicating by type that no conversion is required
1121 //!
1122 // ******************************************************************************************
1123
1124 template< class DATA >
Read(std::istream & stream,DATA & data,int nodummyrequired)1125 void tRecorderBlockHelper< DATA >::Read( std::istream & stream, DATA & data, int nodummyrequired )
1126 {
1127 tASSERT( stream.good() );
1128
1129 // read
1130 stream >> data;
1131 }
1132
1133 // ******************************************************************************************
1134 // *
1135 // * Read
1136 // *
1137 // ******************************************************************************************
1138 //!
1139 //! @param stream the stream to read from
1140 //! @param data the data to archive
1141 //! @param dummyrequired dummy parameter indicating by type that conversion is required
1142 //!
1143 // ******************************************************************************************
1144
1145 template< class DATA >
Read(std::istream & stream,DATA & data,int * dummyrequired)1146 void tRecorderBlockHelper< DATA >::Read( std::istream & stream, DATA & data, int * dummyrequired )
1147 {
1148 tASSERT( stream.good() );
1149
1150 // read ( with conversion )
1151 typedef typename tTypeToStream< DATA >::TOSTREAM TOSTREAM;
1152 TOSTREAM dummy ;
1153 stream >> dummy;
1154 data = static_cast< DATA >( dummy );
1155 }
1156
1157 #endif // TRECORDING_H_INCLUDED
1158