00001 /* 00002 00003 ************************************************************************* 00004 00005 ArmageTron -- Just another Tron Lightcycle Game in 3D. 00006 Copyright (C) 2000 Manuel Moos (manuel@moosnet.de) 00007 00008 ************************************************************************** 00009 00010 This program is free software; you can redistribute it and/or 00011 modify it under the terms of the GNU General Public License 00012 as published by the Free Software Foundation; either version 2 00013 of the License, or (at your option) any later version. 00014 00015 This program is distributed in the hope that it will be useful, 00016 but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 GNU General Public License for more details. 00019 00020 You should have received a copy of the GNU General Public License 00021 along with this program; if not, write to the Free Software 00022 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00023 00024 *************************************************************************** 00025 00026 */ 00027 00028 // declaration 00029 #ifndef TRECORDER_H_INCLUDED 00030 #include "tRecorder.h" 00031 #endif 00032 00033 #include "tConfiguration.h" 00034 #include "tDirectories.h" 00035 #include "tRecorderInternal.h" 00036 00037 #undef INLINE_DEF 00038 #define INLINE_DEF 00039 00040 // ***************************************************************************************** 00041 // * 00042 // * IsRecording 00043 // * 00044 // ***************************************************************************************** 00048 // ***************************************************************************************** 00049 00050 bool tRecorderBase::IsRecording( void ) 00051 { 00052 return tRecordingBlock::GetArchive(); 00053 } 00054 00055 // ***************************************************************************************** 00056 // * 00057 // * IsPlayingBack 00058 // * 00059 // ***************************************************************************************** 00063 // ***************************************************************************************** 00064 00065 bool tRecorderBase::IsPlayingBack( void ) 00066 { 00067 return tPlaybackBlock::GetArchive(); 00068 } 00069 00070 // ***************************************************************************************** 00071 // * 00072 // * IsRunning 00073 // * 00074 // ***************************************************************************************** 00078 // ***************************************************************************************** 00079 00080 bool tRecorderBase::IsRunning( void ) 00081 { 00082 return IsRecording() || IsPlayingBack(); 00083 } 00084 00085 // ******************************************************************************************* 00086 // * 00087 // * Record 00088 // * 00089 // ******************************************************************************************* 00094 // ******************************************************************************************* 00095 00096 bool tRecorder::Record( char const * section ) 00097 { 00098 // delegate 00099 return tRecorderTemplate1< tRecordingBlock >::Archive( false, section ); 00100 } 00101 00102 // ******************************************************************************************* 00103 // * 00104 // * Playback 00105 // * 00106 // ******************************************************************************************* 00111 // ******************************************************************************************* 00112 00113 bool tRecorder::Playback( char const * section ) 00114 { 00115 // delegate 00116 return tRecorderTemplate1< tPlaybackBlock >::Archive( false, section ); 00117 } 00118 00119 // ******************************************************************************************* 00120 // * 00121 // * PlaybackStrict 00122 // * 00123 // ******************************************************************************************* 00128 // ******************************************************************************************* 00129 00130 bool tRecorder::PlaybackStrict( char const * section ) 00131 { 00132 // delegate 00133 return tRecorderTemplate1< tPlaybackBlock >::Archive( true, section ); 00134 } 00135 00136 // ***************************************************************************************** 00137 // ***************************************************************************************** 00138 // ***************************************************************************************** 00139 // ***************************************************************************************** 00140 00141 // ***************************************************************************************** 00142 // * 00143 // * tLineString 00144 // * 00145 // ***************************************************************************************** 00149 // ***************************************************************************************** 00150 00151 tLineString::tLineString( tString const & other ) 00152 :tString( other ) 00153 { 00154 } 00155 00156 // ***************************************************************************************** 00157 // * 00158 // * tLineString 00159 // * 00160 // ***************************************************************************************** 00163 // ***************************************************************************************** 00164 00165 tLineString::tLineString( void ) 00166 { 00167 } 00168 00169 // ***************************************************************************************** 00170 // * 00171 // * ~tLineString 00172 // * 00173 // ***************************************************************************************** 00176 // ***************************************************************************************** 00177 00178 tLineString::~tLineString( void ) 00179 { 00180 } 00181 00183 std::ostream & operator << ( std::ostream & s, tLineString const & line ) 00184 { 00185 // write magic character 00186 s << 'L'; 00187 00188 // print string, encode newlines 00189 for( int i=0; i<line.Len(); ++i) 00190 { 00191 char c = line[i]; 00192 if ( c == '\n' ) 00193 s << "\\n"; 00194 if ( c == '\\' ) 00195 s << "\\\\"; 00196 else if ( c != '\0' ) 00197 s << c; 00198 } 00199 00200 return s << '\n'; 00201 } 00202 00204 std::istream & operator >> ( std::istream & s, tLineString & line ) 00205 { 00206 // read magic character 00207 char c; 00208 s >> c; 00209 tASSERT( 'L' == c ); 00210 00211 tString read; 00212 00213 // read line 00214 read.ReadLine(s); 00215 00216 // std::cout << "Read: " << read << "\n"; 00217 00218 line.Clear(); 00219 00220 // copy line, replacing "\n" with real newline 00221 for(size_t i=0; i<read.Size(); ++i) 00222 { 00223 char c = read[i]; 00224 if ( c != '\\' || i+1 == read.Size() || ( read[i+1] != 'n' && read[i+1] != '\\' ) ) 00225 { 00226 line << c; 00227 } 00228 else if ( read[i+1] == '\\' ) 00229 { 00230 line << "\\"; 00231 i++; 00232 } 00233 else // if ( read[i+1] != 'n' ) 00234 { 00235 line << "\n"; 00236 i++; 00237 } 00238 } 00239 00240 return s; 00241 } 00242 00243 // ***************************************************************************************** 00244 // ***************************************************************************************** 00245 // ***************************************************************************************** 00246 // ***************************************************************************************** 00247 00248 // ***************************************************************************************** 00249 // * 00250 // * Initialize 00251 // * 00252 // ***************************************************************************************** 00258 // ***************************************************************************************** 00259 00260 bool tRecordingBlockBase::Initialize( char const * section, tRecording * recording ) 00261 { 00262 // initialize recording pointer 00263 recording_ = recording; 00264 if (!recording_) 00265 return false; 00266 00267 // start section 00268 recording_->BeginSection( section ); 00269 00270 // return success 00271 return true; 00272 } 00273 00274 // ***************************************************************************************** 00275 // * 00276 // * Initialize 00277 // * 00278 // ***************************************************************************************** 00283 // ***************************************************************************************** 00284 00285 bool tRecordingBlockBase::Initialize( char const * section ) 00286 { 00287 // delegate 00288 return Initialize( section, tRecording::currentRecording_ ); 00289 } 00290 00291 // ***************************************************************************************** 00292 // * 00293 // * Separator 00294 // * 00295 // ***************************************************************************************** 00298 // ***************************************************************************************** 00299 00300 void tRecordingBlockBase::Separator( void ) 00301 { 00302 GetRecordingStream() << "\n"; 00303 separate_ = false; 00304 } 00305 00306 // ****************************************************************************************** 00307 // * 00308 // * GetArchive 00309 // * 00310 // ****************************************************************************************** 00314 // ****************************************************************************************** 00315 00316 tRecording * tRecordingBlockBase::GetArchive( void ) 00317 { 00318 return tRecording::currentRecording_; 00319 } 00320 00321 // ***************************************************************************************** 00322 // * 00323 // * tRecordingBlockBase 00324 // * 00325 // ***************************************************************************************** 00328 // ***************************************************************************************** 00329 00330 tRecordingBlockBase::tRecordingBlockBase( void ) 00331 : separate_( true ), recording_( NULL ) 00332 { 00333 } 00334 00335 // ***************************************************************************************** 00336 // * 00337 // * ~tRecordingBlockBase 00338 // * 00339 // ***************************************************************************************** 00342 // ***************************************************************************************** 00343 00344 tRecordingBlockBase::~tRecordingBlockBase( void ) 00345 { 00346 // make sure everything is logged, even if program crashes 00347 if (recording_) 00348 GetRecordingStream().flush(); 00349 00350 recording_ = 0; 00351 } 00352 00353 // ***************************************************************************************** 00354 // * 00355 // * GetRecordingStream 00356 // * 00357 // ***************************************************************************************** 00361 // ***************************************************************************************** 00362 00363 std::ostream & tRecordingBlockBase::GetRecordingStream() const 00364 { 00365 tASSERT( recording_ ); 00366 00367 return recording_->DoGetStream(); 00368 } 00369 00370 // ******************************************************************************************* 00371 // * 00372 // * tRecordingBlock 00373 // * 00374 // ******************************************************************************************* 00377 // ******************************************************************************************* 00378 00379 tRecordingBlock::tRecordingBlock( void ) 00380 { 00381 } 00382 00383 // ******************************************************************************************* 00384 // * 00385 // * ~tRecordingBlock 00386 // * 00387 // ******************************************************************************************* 00390 // ******************************************************************************************* 00391 00392 tRecordingBlock::~tRecordingBlock( void ) 00393 { 00394 } 00395 00396 // ***************************************************************************************** 00397 // ***************************************************************************************** 00398 // ***************************************************************************************** 00399 // ***************************************************************************************** 00400 00401 // ***************************************************************************************** 00402 // * 00403 // * Initialize 00404 // * 00405 // ***************************************************************************************** 00411 // ***************************************************************************************** 00412 00413 bool tPlaybackBlockBase::Initialize( char const * section, tPlayback * playback ) 00414 { 00415 // initialize playback pointer 00416 playback_ = playback; 00417 if (!playback_) 00418 return false; 00419 00420 // read section 00421 if( playback_->GetNextSection() != section ) 00422 { 00423 playback_ = NULL; 00424 return false; 00425 } 00426 00427 // return success 00428 return true; 00429 } 00430 00431 // ***************************************************************************************** 00432 // * 00433 // * Initialize 00434 // * 00435 // ***************************************************************************************** 00440 // ***************************************************************************************** 00441 00442 bool tPlaybackBlockBase::Initialize( char const * section ) 00443 { 00444 return Initialize( section, tPlayback::currentPlayback_ ); 00445 } 00446 00447 // ***************************************************************************************** 00448 // * 00449 // * Separator 00450 // * 00451 // ***************************************************************************************** 00454 // ***************************************************************************************** 00455 00456 void tPlaybackBlockBase::Separator( void ) const 00457 { 00458 } 00459 // ****************************************************************************************** 00460 // * 00461 // * GetArchive 00462 // * 00463 // ****************************************************************************************** 00467 // ****************************************************************************************** 00468 00469 tPlayback * tPlaybackBlockBase::GetArchive( void ) 00470 { 00471 return tPlayback::currentPlayback_; 00472 } 00473 00474 // ***************************************************************************************** 00475 // * 00476 // * tPlaybackBlockBase 00477 // * 00478 // ***************************************************************************************** 00481 // ***************************************************************************************** 00482 00483 tPlaybackBlockBase::tPlaybackBlockBase( void ) 00484 : playback_( 0 ) 00485 { 00486 } 00487 00488 // ***************************************************************************************** 00489 // * 00490 // * ~tPlaybackBlockBase 00491 // * 00492 // ***************************************************************************************** 00495 // ***************************************************************************************** 00496 00497 tPlaybackBlockBase::~tPlaybackBlockBase( void ) 00498 { 00499 // end current block and read next 00500 if ( playback_ ) 00501 playback_->AdvanceSection(); 00502 00503 playback_ = 0; 00504 } 00505 00506 // ***************************************************************************************** 00507 // * 00508 // * GetPlaybackStream 00509 // * 00510 // ***************************************************************************************** 00514 // ***************************************************************************************** 00515 00516 std::istream & tPlaybackBlockBase::GetPlaybackStream() const 00517 { 00518 tASSERT( playback_ ); 00519 00520 return playback_->DoGetStream(); 00521 } 00522 00523 // ******************************************************************************************* 00524 // * 00525 // * tPlaybackBlock 00526 // * 00527 // ******************************************************************************************* 00530 // ******************************************************************************************* 00531 00532 tPlaybackBlock::tPlaybackBlock( void ) 00533 { 00534 } 00535 00536 // ******************************************************************************************* 00537 // * 00538 // * ~tPlaybackBlock 00539 // * 00540 // ******************************************************************************************* 00543 // ******************************************************************************************* 00544 00545 tPlaybackBlock::~tPlaybackBlock( void ) 00546 { 00547 } 00548 00549 // ***************************************************************************************** 00550 // ***************************************************************************************** 00551 // ***************************************************************************************** 00552 // ***************************************************************************************** 00553 00554 static int st_debugLevelRecording=0; 00555 static tSettingItem<int>rdb( "RECORDING_DEBUGLEVEL", 00556 st_debugLevelRecording ); 00557 00558 // returns the playback debug level, archiving the result 00559 static int st_GetDebugLevelPlayback() 00560 { 00561 // sync level with recording 00562 int level = st_debugLevelRecording; 00563 tRecorder::Playback( "DEBUGLEVEL", level ); 00564 tRecorder::Record( "DEBUGLEVEL", st_debugLevelRecording ); 00565 00566 return level; 00567 } 00568 00569 // ******************************************************************************************* 00570 // * 00571 // * GetDebugLevelPlayback 00572 // * 00573 // ******************************************************************************************* 00577 // ******************************************************************************************* 00578 00579 int tRecorderSyncBase::GetDebugLevelPlayback( void ) 00580 { 00581 // get the playback level only once 00582 static int level = st_GetDebugLevelPlayback(); 00583 00584 return level; 00585 } 00586 00587 // ******************************************************************************************* 00588 // * 00589 // * GetDebugLevelRecording 00590 // * 00591 // ******************************************************************************************* 00595 // ******************************************************************************************* 00596 00597 int tRecorderSyncBase::GetDebugLevelRecording( void ) 00598 { 00599 return st_debugLevelRecording; 00600 } 00601 00602 REAL st_GetDifference( REAL a, REAL b) 00603 { 00604 return fabs( a - b ); 00605 } 00606 00607 REAL st_GetDifference( int a, int b) 00608 { 00609 return fabs( REAL( a - b ) ); 00610 } 00611 00612 REAL st_GetDifference( unsigned int a, unsigned int b) 00613 { 00614 return fabs( REAL( a - b ) ); 00615 } 00616 00617 REAL st_GetDifference( unsigned long int a, unsigned long int b) 00618 { 00619 return fabs( REAL( a - b ) ); 00620 } 00621 00622 REAL st_GetDifference( tString const & a, tString const & b ) 00623 { 00624 return ( a == b ) ? 0 : 1; 00625 } 00626 00627 static char const * st_fileOpen = "FILE_OPEN"; 00628 static char const * st_fileRead = "FILE_READ"; 00629 00630 // ******************************************************************************* 00631 // * 00632 // * Open 00633 // * 00634 // ******************************************************************************* 00640 // ******************************************************************************* 00641 00642 bool tTextFileRecorder::Open( tPath const & searchPath, char const * fileName ) 00643 { 00644 tASSERT( !stream_ ); 00645 00646 bool result = false; 00647 00648 // try to read opening state from recording 00649 if ( !tRecorder::Playback( st_fileOpen, result, eof_ ) ) 00650 { 00651 // open the stream (if not in recording mode) 00652 stream_ = tNEW( std::ifstream ); 00653 result = searchPath.Open( *stream_, fileName ); 00654 eof_ = !result || !stream_->good() || stream_->eof(); 00655 } 00656 tRecorder::Record( st_fileOpen, result, eof_ ); 00657 00658 return result; 00659 } 00660 00661 // ******************************************************************************* 00662 // * 00663 // * tTextFileRecorder 00664 // * 00665 // ******************************************************************************* 00670 // ******************************************************************************* 00671 00672 tTextFileRecorder::tTextFileRecorder( tPath const & searchPath, char const * fileName ) 00673 : stream_(NULL), eof_(false) 00674 { 00675 Open( searchPath, fileName ); 00676 } 00677 00678 // ******************************************************************************* 00679 // * 00680 // * tTextFileRecorder 00681 // * 00682 // ******************************************************************************* 00685 // ******************************************************************************* 00686 00687 tTextFileRecorder::tTextFileRecorder( void ) 00688 : stream_(NULL), eof_(false) 00689 { 00690 stream_ = NULL; 00691 } 00692 00693 // ******************************************************************************* 00694 // * 00695 // * ~tTextFileRecorder 00696 // * 00697 // ******************************************************************************* 00700 // ******************************************************************************* 00701 00702 tTextFileRecorder::~tTextFileRecorder( void ) 00703 { 00704 delete stream_; 00705 stream_ = NULL; 00706 } 00707 00708 // ******************************************************************************* 00709 // * 00710 // * EndOfFile 00711 // * 00712 // ******************************************************************************* 00716 // ******************************************************************************* 00717 00718 bool tTextFileRecorder::EndOfFile( void ) const 00719 { 00720 return eof_; 00721 } 00722 00723 // ******************************************************************************* 00724 // * 00725 // * GetLine 00726 // * 00727 // ******************************************************************************* 00731 // ******************************************************************************* 00732 00733 std::string tTextFileRecorder::GetLine( void ) 00734 { 00735 // try to read opening state from recording 00736 tLineString line; 00737 if ( !tRecorder::Playback( st_fileRead, line, eof_ ) ) 00738 { 00739 // read a line 00740 tASSERT( stream_ ); 00741 line.ReadLine( *stream_ ); 00742 std::ws( *stream_ ); 00743 eof_ = !stream_->good() || stream_->eof(); 00744 } 00745 tRecorder::Record( st_fileRead, line, eof_ ); 00746 00747 // convert and return read line 00748 return std::string(line); 00749 } 00750 00751