cmtkTypedStream.cxx

Go to the documentation of this file.
00001 /*
00002 //
00003 //  Copyright 1997-2009 Torsten Rohlfing
00004 //
00005 //  Copyright 2004-2011 SRI International
00006 //
00007 //  This file is part of the Computational Morphometry Toolkit.
00008 //
00009 //  http://www.nitrc.org/projects/cmtk/
00010 //
00011 //  The Computational Morphometry Toolkit is free software: you can
00012 //  redistribute it and/or modify it under the terms of the GNU General Public
00013 //  License as published by the Free Software Foundation, either version 3 of
00014 //  the License, or (at your option) any later version.
00015 //
00016 //  The Computational Morphometry Toolkit is distributed in the hope that it
00017 //  will be useful, but WITHOUT ANY WARRANTY; without even the implied
00018 //  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 //  GNU General Public License for more details.
00020 //
00021 //  You should have received a copy of the GNU General Public License along
00022 //  with the Computational Morphometry Toolkit.  If not, see
00023 //  <http://www.gnu.org/licenses/>.
00024 //
00025 //  $Revision: 2752 $
00026 //
00027 //  $LastChangedDate: 2011-01-17 11:33:31 -0800 (Mon, 17 Jan 2011) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #include "cmtkTypedStream.h"
00034 
00035 #include <System/cmtkFileUtils.h>
00036 #include <System/cmtkConsole.h>
00037 
00038 #include <string.h>
00039 #include <stdlib.h>
00040 #include <cstdarg>
00041 #include <limits.h>
00042 
00043 #ifdef HAVE_MALLOC_H
00044 #  include <malloc.h>
00045 #endif
00046 
00047 #ifdef HAVE_SYS_TIME_H
00048 #  include <sys/time.h>
00049 #endif
00050 
00051 #ifdef HAVE_SYS_STAT_H
00052 #  include <sys/stat.h>
00053 #endif
00054 
00055 namespace
00056 cmtk
00057 {
00058 
00061 
00062 TypedStream
00063 ::TypedStream()
00064 {
00065   this->InitInternals();
00066 }
00067 
00068 TypedStream
00069 ::TypedStream
00070 ( const char *filename, const TypedStreamMode mode )
00071 {
00072   this->InitInternals();
00073   this->Open( filename, mode );
00074 }
00075 
00076 TypedStream
00077 ::TypedStream
00078 ( const char *dir, const char *archive, const TypedStreamMode mode )
00079 {
00080   this->InitInternals();
00081   this->Open( dir, archive, mode );
00082 }
00083 
00084 void
00085 TypedStream
00086 ::InitInternals()
00087 {
00088   File = NULL;
00089   GzFile = NULL;
00090 
00091   PrecisionFloat = 6;
00092   PrecisionDouble = 10;
00093 
00094   Status = TYPEDSTREAM_ERROR_NONE;
00095   DebugFlag = TYPEDSTREAM_DEBUG_OFF;
00096 
00097   SplitPosition = NULL;
00098 }
00099 
00100 TypedStream
00101 ::~TypedStream()
00102 {
00103   this->Close();
00104   this->InitInternals();
00105 }
00106 
00107 void 
00108 TypedStream
00109 ::Open
00110 ( const char *dir, const char *archive, const TypedStreamMode mode )
00111 {
00112   static char fname[PATH_MAX];
00113   
00114   // If "dir" parameter is NULL or empty, use current directory instead.
00115   if ( dir && *dir ) 
00116     {
00117     if ( static_cast<size_t>( snprintf( fname, sizeof( fname ), "%s/%s", dir, archive ) ) >= sizeof( fname ) )
00118       {
00119       StdErr << "WARNING: length of path exceeds system PATH_MAX in TypedStream::Open and will be truncated.\n";
00120       }
00121     } 
00122   else 
00123     {
00124     if ( static_cast<size_t>( snprintf( fname, sizeof( fname ), "%s", archive ) ) >= sizeof( fname ) )
00125       {
00126       StdErr << "WARNING: length of path exceeds system PATH_MAX in TypedStream::Open and will be truncated.\n";
00127       }
00128     }
00129   
00130   if ( mode == TYPEDSTREAM_WRITE || mode == TYPEDSTREAM_WRITE_ZLIB || mode == TYPEDSTREAM_APPEND ) 
00131     {
00132 #ifndef _MSC_VER
00133     // check if this is an existing directory; if it is, set access/modification time.
00134     // this is useful for dependency checking using file system timestamps.
00135     struct stat buf;
00136     if ( !stat( dir, &buf ) && S_ISDIR( buf.st_mode ) )
00137       {
00138       utimes( dir, NULL );
00139       }
00140 #endif
00141     }    
00142 
00143   this->Open( fname, mode );
00144 }
00145 
00146 void 
00147 TypedStream
00148 ::Open
00149 ( const char *filename, const TypedStreamMode mode )
00150 {
00151   Status = TYPEDSTREAM_ERROR_NONE;
00152 
00153   this->Close();
00154   
00155   if ( !filename) 
00156     {
00157     Status = TYPEDSTREAM_ERROR_ARG;
00158     return;
00159     }
00160   
00161   if ( mode != TYPEDSTREAM_READ && mode != TYPEDSTREAM_WRITE && mode != TYPEDSTREAM_WRITE_ZLIB && mode != TYPEDSTREAM_APPEND ) 
00162     {
00163     Status = TYPEDSTREAM_ERROR_ARG;
00164     return;
00165     }
00166   
00167   if ( mode == TYPEDSTREAM_WRITE || mode == TYPEDSTREAM_WRITE_ZLIB ) 
00168     {
00169     if ( FileUtils::RecursiveMkPrefixDir( filename ) ) 
00170       {
00171       Status = TYPEDSTREAM_ERROR_SYSTEM;
00172       return;
00173       }
00174     }
00175   
00176   const char *modestr = "";
00177   switch ( mode ) 
00178     {
00179 #ifdef _MSC_VER
00180     case TYPEDSTREAM_READ:      modestr = "rb"; break;
00181     case TYPEDSTREAM_WRITE:     modestr = "wb"; break;
00182     case TYPEDSTREAM_WRITE_ZLIB:        modestr = "wb"; break;
00183     case TYPEDSTREAM_APPEND:    modestr = "ab"; break;
00184 #else
00185     case TYPEDSTREAM_READ:      modestr = "r"; break;
00186     case TYPEDSTREAM_WRITE:     modestr = "w"; break;
00187     case TYPEDSTREAM_WRITE_ZLIB:        modestr = "w"; break;
00188     case TYPEDSTREAM_APPEND:    modestr = "a"; break;
00189 #endif
00190     }
00191   
00192   if ( ! ( File = fopen( filename, modestr ) ) ) 
00193     {
00194     char gzName[PATH_MAX];
00195     snprintf( gzName, sizeof( gzName ), "%s.gz", filename );
00196     GzFile = gzopen( gzName, modestr );
00197     if ( ! GzFile ) 
00198       {
00199       Status = TYPEDSTREAM_ERROR_SYSTEM;
00200       return;
00201       }
00202     }
00203   
00204   Mode = mode;
00205   switch ( Mode ) 
00206     {
00207     case TYPEDSTREAM_READ:
00208       if ( GzFile ) 
00209         {
00210         if (! gzgets( GzFile, Buffer, TYPEDSTREAM_LIMIT_BUFFER ) ) 
00211           {
00212           Status = TYPEDSTREAM_ERROR_FORMAT;
00213           gzclose( GzFile );
00214           return;
00215           }
00216         } 
00217       else
00218         if (! fgets( Buffer, TYPEDSTREAM_LIMIT_BUFFER, File ) ) 
00219           {
00220           Status = TYPEDSTREAM_ERROR_FORMAT;
00221           fclose( File );
00222           File = NULL;
00223           return;
00224           }
00225       
00226       if (Buffer[0] != '!' && Buffer[0] != '#') 
00227         {
00228         Status = TYPEDSTREAM_ERROR_FORMAT;
00229         if ( GzFile )
00230           {
00231           gzclose( GzFile );
00232           GzFile = NULL;
00233           }
00234 
00235         if ( File )
00236           {
00237           fclose( File );
00238           File = NULL;
00239           }
00240         return;
00241         }
00242       int releaseMinor, releaseMajor;
00243       if (2 != sscanf( Buffer+1, " TYPEDSTREAM %d.%d", &releaseMajor, &releaseMinor)) 
00244         {
00245         Status = TYPEDSTREAM_ERROR_FORMAT;
00246         if ( GzFile )
00247           {
00248           gzclose( GzFile );
00249           GzFile = NULL;
00250           }
00251 
00252         if ( File )
00253           {
00254           fclose( File );
00255           File = NULL;
00256           }
00257         return;
00258         }
00259       if ( releaseMajor == 1 && releaseMinor == 0) 
00260         {
00261         /* Release 1.0 */
00262         } 
00263       else
00264         if (releaseMajor == 1 && releaseMinor == 1) 
00265           {
00266           /* Release 1.1 */
00267           } 
00268         else 
00269           {
00270           /* Unknown Release */
00271           Status = TYPEDSTREAM_ERROR_FORMAT;
00272           if ( GzFile )
00273             {
00274             gzclose( GzFile );
00275             GzFile = NULL;
00276             }
00277           
00278           if ( File )
00279             {
00280             fclose( File );
00281             File = NULL;
00282             }
00283           return;
00284           }
00285       break;
00286       
00287     case TYPEDSTREAM_WRITE:
00288     case TYPEDSTREAM_WRITE_ZLIB:
00289       if ( GzFile )
00290         gzprintf( GzFile, "%s\n", GetTypedStreamIdent() );
00291       else
00292         fprintf( File, "%s\n", GetTypedStreamIdent() );
00293       break;
00294       
00295     case TYPEDSTREAM_APPEND:
00296       if ( GzFile ) 
00297         {
00298         if ( 0 == gztell( File) )
00299           gzprintf( GzFile, "%s\n", GetTypedStreamIdent() );
00300         } 
00301       else
00302         if ( 0 == ftell( File) )
00303           fprintf( File, "%s\n", GetTypedStreamIdent() );
00304       break;
00305     }
00306 }
00307 
00308 void
00309 TypedStream
00310 ::Close()
00311 {
00312   if ( File || GzFile )
00313     {
00314     if ( Mode == TYPEDSTREAM_WRITE || Mode == TYPEDSTREAM_APPEND ) 
00315       {
00316       while ( ! LevelStack.empty() ) 
00317         {
00318         LevelStack.pop();
00319         int streamLevel = LevelStack.size();
00320         if ( GzFile ) 
00321           {
00322           for ( int level = 0; level < streamLevel; level++)
00323             gzputs( GzFile, "\t" );
00324           gzputs( GzFile, "}\n" );
00325           } 
00326         else
00327           {
00328           for ( int level = 0; level < streamLevel; level++)
00329             fputs( "\t", File );
00330           fputs( "}\n", File );
00331           }
00332         }
00333       } 
00334     else 
00335       {
00336       while ( ! LevelStack.empty() ) 
00337         {
00338         LevelStack.pop();      
00339         }
00340       }
00341     
00342     if ( GzFile ) 
00343       {
00344       gzclose( GzFile );
00345       GzFile = NULL;
00346       }
00347     if ( File ) 
00348       {
00349       fclose( File );
00350       File = NULL;
00351       }
00352     }
00353   
00354   Status = TYPEDSTREAM_ERROR_NONE;
00355   SplitPosition = NULL;
00356 }
00357 
00358 TypedStreamCondition 
00359 TypedStream
00360 ::Begin
00361 ( const char* section )
00362 {
00363   if ( !File && !GzFile)
00364     {
00365     Status = TYPEDSTREAM_ERROR_INVALID;
00366     return TYPEDSTREAM_ERROR;
00367     }
00368 
00369   if ( (Mode != TYPEDSTREAM_READ) && !section) 
00370     {
00371     Status = TYPEDSTREAM_ERROR_ARG;
00372     return TYPEDSTREAM_ERROR;
00373     }
00374   
00375   if ( Mode == TYPEDSTREAM_READ ) 
00376     {
00377     if ( GzFile )
00378       gzseek( GzFile, LevelStack.top(), SEEK_SET );
00379     else
00380       fseek( File, LevelStack.top(), SEEK_SET );
00381     return TYPEDSTREAM_OK;
00382     } 
00383   else 
00384     {
00385     int streamLevel = LevelStack.size();
00386     if ( GzFile ) 
00387       {
00388       for ( int level = 0; level < streamLevel; level++)
00389         gzputs( GzFile, "\t" );
00390 
00391       gzprintf( GzFile, "%s {\n", section );
00392       }
00393     else
00394       {
00395       for ( int level = 0; level < streamLevel; level++)
00396         fputs( "\t", File );
00397       
00398       fprintf( File, "%s {\n", section );
00399       }
00400     
00401     if ( GzFile )
00402       LevelStack.push( gztell( GzFile ) );
00403     else
00404       LevelStack.push( ftell( File ) );
00405     }
00406   
00407   return TYPEDSTREAM_OK;
00408 }
00409 
00410 TypedStreamCondition
00411 TypedStream
00412 ::End
00413 ( const bool flush )
00414 {
00415   if ( ! File && ! GzFile )
00416     {
00417     Status = TYPEDSTREAM_ERROR_INVALID;
00418     return TYPEDSTREAM_ERROR;
00419     }
00420   
00421   if ( Mode == TYPEDSTREAM_READ ) 
00422     {
00423     if ( LevelStack.size() == 0 ) 
00424       {
00425       // end without begin
00426       Status = TYPEDSTREAM_ERROR_LEVEL;
00427       return TYPEDSTREAM_ERROR;
00428       }
00429 
00430     TypedStreamToken token;
00431     int currentLevel = 1;
00432     while ( currentLevel && (TYPEDSTREAM_EOF != ( token = this->ReadLineToken() ) ) ) 
00433       {
00434       if ( token == TYPEDSTREAM_BEGIN ) 
00435         {
00436         this->DebugOutput( "Skipping section %s at level %d.", BufferKey, currentLevel );
00437         ++currentLevel;
00438         }
00439       else
00440         if ( token == TYPEDSTREAM_END ) 
00441           {
00442           this->DebugOutput( "Leaving section %d.", currentLevel );
00443           --currentLevel;
00444           }
00445       }
00446     
00447     LevelStack.pop();
00448     } 
00449   else 
00450     {
00451     int streamLevel = LevelStack.size();
00452     if ( streamLevel == 0 ) 
00453       {
00454       // end without begin
00455       Status = TYPEDSTREAM_ERROR_LEVEL;
00456       return TYPEDSTREAM_ERROR;
00457       }
00458     
00459     LevelStack.pop();
00460     if ( GzFile ) 
00461       {
00462       for ( int level = 0; level < streamLevel-1; level++ )
00463         gzputs( GzFile, "\t" );
00464       gzputs( GzFile, "}\n" );
00465       }
00466     else 
00467       {
00468       for ( int level = 0; level < streamLevel-1; level++ )
00469         fputs( "\t", File );
00470       fputs( "}\n", File ); 
00471       }
00472     }
00473   
00474   if ( flush ) 
00475     {
00476     fflush( File );
00477     }
00478   
00479   return TYPEDSTREAM_OK;
00480 }
00481   
00482 TypedStreamCondition
00483 TypedStream
00484 ::Seek
00485 ( const char* section, const bool forward )
00486 {
00487   if ( ! File && ! GzFile )
00488     {
00489     Status = TYPEDSTREAM_ERROR_INVALID;
00490     return TYPEDSTREAM_ERROR;
00491     }
00492 
00493   if ( ! section ) 
00494     {
00495     Status = TYPEDSTREAM_ERROR_ARG;
00496     return TYPEDSTREAM_ERROR;
00497     }
00498   if ( Mode != TYPEDSTREAM_READ ) 
00499     {
00500     Status = TYPEDSTREAM_ERROR_MODE;
00501     return TYPEDSTREAM_ERROR;
00502     }
00503   
00504   unsigned initialLevel = LevelStack.size();
00505 
00506   if ( ! forward )
00507     {
00508     if ( GzFile ) 
00509       {
00510       if ( initialLevel ) 
00511         {
00512         gzseek( GzFile, LevelStack.top(), SEEK_SET );
00513         } 
00514       else 
00515         {
00516         gzseek( GzFile, 0, SEEK_SET);
00517         }
00518       } 
00519     else
00520       if ( initialLevel ) 
00521         {
00522         fseek( File, LevelStack.top(), SEEK_SET );
00523         } 
00524       else 
00525         {
00526         fseek( File, 0, SEEK_SET);
00527         }
00528     }
00529 
00530   unsigned currentLevel = initialLevel;
00531   
00532   this->DebugOutput( "Seeking section %s from level %d.", section, initialLevel );
00533   TypedStreamToken token;
00534   while ( TYPEDSTREAM_EOF != ( token = this->ReadLineToken() ) ) 
00535     {
00536     if ( token == TYPEDSTREAM_BEGIN ) 
00537       {
00538       this->DebugOutput( "Enter section %s at level %d.", BufferKey, currentLevel );
00539       if ( this->StringCmp( BufferKey, section ) == 0 ) 
00540         {
00541         if ( currentLevel == LevelStack.size() ) 
00542           {
00543           if ( GzFile )
00544             LevelStack.push( gztell( GzFile ) );
00545           else
00546             LevelStack.push( ftell( File ) );
00547           return TYPEDSTREAM_OK;
00548           }
00549         if ( currentLevel == LevelStack.size()-1 ) 
00550           {
00551           LevelStack.pop();
00552           if ( GzFile )
00553             LevelStack.push( gztell( GzFile ) );
00554           else
00555             LevelStack.push( ftell( File ) );
00556           return TYPEDSTREAM_OK;
00557           }
00558         }
00559       ++ currentLevel;
00560       }
00561     if ( token == TYPEDSTREAM_END ) 
00562       {
00563       this->DebugOutput( "Leaving section %d.", currentLevel );
00564       if ( ! currentLevel ) 
00565         {
00566         Status = TYPEDSTREAM_ERROR_LEVEL;
00567         return TYPEDSTREAM_ERROR;
00568         }
00569       if ( currentLevel < initialLevel ) 
00570         {
00571         Status = TYPEDSTREAM_ERROR_NONE;
00572         return TYPEDSTREAM_ERROR;
00573         }
00574       -- currentLevel;
00575       }
00576     }
00577   
00578   this->DebugOutput( "Section %s not found.", section );
00579   Status = TYPEDSTREAM_ERROR_NONE;
00580   return TYPEDSTREAM_ERROR;
00581 }
00582 
00583 TypedStreamCondition
00584 TypedStream
00585 ::Rewind()
00586 {
00587   if ( ! File && ! GzFile )
00588     {
00589     Status = TYPEDSTREAM_ERROR_INVALID;
00590     return TYPEDSTREAM_ERROR;
00591     }
00592   if ( Mode != TYPEDSTREAM_READ ) 
00593     {
00594     Status = TYPEDSTREAM_ERROR_MODE;
00595     return TYPEDSTREAM_ERROR;
00596     }
00597   
00598   if ( LevelStack.size() )
00599     LevelStack.pop();
00600   
00601   if ( LevelStack.size() == 0 ) 
00602     {
00603     if ( GzFile ) 
00604       {
00605       if ( -1 == gzseek( GzFile, 0, SEEK_SET ) ) 
00606         {
00607         Status = TYPEDSTREAM_ERROR_SYSTEM;
00608         return TYPEDSTREAM_ERROR;
00609         }
00610       } 
00611     else
00612       if ( -1 == fseek( File, 0, SEEK_SET ) )
00613         {
00614         Status = TYPEDSTREAM_ERROR_SYSTEM;
00615         return TYPEDSTREAM_ERROR;
00616         }
00617     } 
00618   else 
00619     {
00620     if ( GzFile ) 
00621       {
00622       if (-1 == gzseek( GzFile, LevelStack.top(), SEEK_SET)) 
00623         {
00624         Status = TYPEDSTREAM_ERROR_SYSTEM;
00625         return TYPEDSTREAM_ERROR;
00626         }
00627       }
00628     else
00629       if (-1 == fseek( File, LevelStack.top(), SEEK_SET)) 
00630         {
00631         Status = TYPEDSTREAM_ERROR_SYSTEM;
00632         return TYPEDSTREAM_ERROR;
00633         }
00634     }
00635   return TYPEDSTREAM_OK;
00636 }
00637 
00638 bool
00639 TypedStream
00640 ::ReadBool( const char* key, const bool defaultValue, const bool forward )
00641 {
00642   int value;
00643   
00644   if ( this->GenericReadArray( key, TYPEDSTREAM_TYPE_BOOL, &value, 1, forward ) != TYPEDSTREAM_OK )
00645     if ( this->GenericReadArray( key, TYPEDSTREAM_TYPE_INT, &value, 1, forward ) != TYPEDSTREAM_OK )
00646       return defaultValue;
00647   
00648   return (value != 0);
00649 }
00650 
00651 TypedStreamCondition 
00652 TypedStream
00653 ::ReadBoolArray( const char* key, byte *const array, const int size, const bool forward )
00654 {
00655   return this->GenericReadArray( key, TYPEDSTREAM_TYPE_BINARYBOOL, array, size, forward );
00656 }
00657 
00658 int 
00659 TypedStream
00660 ::ReadInt( const char* key, const int defaultValue, const bool forward )
00661 {
00662   int value = defaultValue;
00663   if ( this->GenericReadArray( key, TYPEDSTREAM_TYPE_INT, &value, 1, forward ) != TYPEDSTREAM_OK )
00664     return defaultValue;
00665   
00666   return value;
00667 }
00668 
00669 TypedStreamCondition 
00670 TypedStream
00671 ::ReadIntArray( const char* key, int *const array, const int size, const bool forward )
00672 {
00673   return this->GenericReadArray( key, TYPEDSTREAM_TYPE_INT, array, size, forward );
00674 }
00675 
00676 float
00677 TypedStream
00678 ::ReadFloat( const char* key, const float defaultValue, const bool forward )
00679 {
00680   float value = defaultValue;
00681   if ( this->GenericReadArray( key, TYPEDSTREAM_TYPE_FLOAT, &value, 1, forward ) != TYPEDSTREAM_OK )
00682     return defaultValue;
00683   
00684   return value;
00685 }
00686 
00687 TypedStreamCondition
00688 TypedStream
00689 ::ReadFloatArray( const char* key, float *const array, const int size, const bool forward )
00690 {
00691   return this->GenericReadArray( key, TYPEDSTREAM_TYPE_FLOAT, array, size, forward );
00692 }
00693 
00694 double
00695 TypedStream
00696 ::ReadDouble( const char* key, const double defaultValue, const bool forward )
00697 {
00698   double value = defaultValue;
00699   if ( this->GenericReadArray( key, TYPEDSTREAM_TYPE_DOUBLE, &value, 1, forward ) != TYPEDSTREAM_OK )
00700     return defaultValue;
00701   
00702   return value;
00703 }
00704 
00705 TypedStreamCondition
00706 TypedStream
00707 ::ReadDoubleArray( const char* key, double *const array, const int size, const bool forward )
00708 {
00709   return this->GenericReadArray( key, TYPEDSTREAM_TYPE_DOUBLE, array, size, forward );
00710 }
00711 
00712 char*
00713 TypedStream
00714 ::ReadString( const char* key, const char *defaultValue, const bool forward )
00715 {
00716   char *value;
00717   if ( this->GenericReadArray( key, TYPEDSTREAM_TYPE_STRING, &value, 1, forward ) != TYPEDSTREAM_OK )
00718     {
00719     if ( defaultValue )
00720       return strdup( defaultValue );
00721     else
00722       return NULL;
00723     }
00724   
00725   return value;
00726 }
00727 
00728 TypedStreamCondition 
00729 TypedStream
00730 ::WriteBool( const char* key, const bool value )
00731 {
00732   int currentLevel = LevelStack.size();
00733   if ( GzFile ) 
00734     {
00735     for ( int level = 0; level < currentLevel; level++ )
00736       gzputs( GzFile, "\t" );
00737     gzprintf( GzFile, "%s %s\n", key, (value) ? "yes" : "no");
00738     } 
00739   else
00740     { 
00741     for ( int level = 0; level < currentLevel; level++ )
00742       fputs( "\t", File );
00743     fprintf( File, "%s %s\n", key, (value) ? "yes" : "no");
00744     }
00745   return TYPEDSTREAM_OK;
00746 }
00747 
00748 TypedStreamCondition
00749 TypedStream
00750 ::WriteInt( const char* key, const int value )
00751 {
00752   int currentLevel = LevelStack.size();
00753   if ( GzFile ) 
00754     {
00755     for ( int level = 0; level < currentLevel; level++ )
00756       gzputs( GzFile, "\t" );
00757     gzprintf( GzFile, "%s %d\n", key, value );
00758     } 
00759   else
00760     { 
00761     for ( int level = 0; level < currentLevel; level++ )
00762       fputs( "\t", File );
00763     fprintf( File, "%s %d\n", key, value );
00764     }
00765   return TYPEDSTREAM_OK;
00766 }
00767 
00768 TypedStreamCondition
00769 TypedStream
00770 ::WriteFloat( const char* key, const float value )
00771 {
00772   int currentLevel = LevelStack.size();
00773   if ( GzFile ) 
00774     {
00775     for ( int level = 0; level < currentLevel; level++ )
00776       gzputs( GzFile, "\t" );
00777     gzprintf( GzFile, "%s %.*f\n", key, PrecisionFloat, value );
00778     } 
00779   else
00780     {
00781     for ( int level = 0; level < currentLevel; level++ )
00782       fputs( "\t", File );
00783     fprintf( File, "%s %.*f\n", key, PrecisionFloat, value );
00784     }
00785   return TYPEDSTREAM_OK;
00786 }
00787 
00788 TypedStreamCondition
00789 TypedStream
00790 ::WriteDouble( const char* key, const double value )
00791 {
00792   int currentLevel = LevelStack.size();
00793   if ( GzFile ) 
00794     {
00795     for ( int level = 0; level < currentLevel; level++ )
00796       gzputs( GzFile, "\t" );
00797     gzprintf( File, "%s %.*f\n", key, PrecisionDouble, value );
00798     } 
00799   else
00800     {
00801     for ( int level = 0; level < currentLevel; level++ )
00802       fputs( "\t", File );
00803     fprintf( File, "%s %.*f\n", key, PrecisionDouble, value );
00804     }
00805   return TYPEDSTREAM_OK;
00806 }
00807 
00808 TypedStreamCondition
00809 TypedStream
00810 ::WriteString( const char* key, const std::string& value )
00811 {
00812   return this->WriteString( key, value.c_str() );
00813 }
00814 
00815 TypedStreamCondition
00816 TypedStream
00817 ::WriteString( const char* key, const char* value )
00818 {
00819   char *buffer = Buffer;
00820   
00821   const char *strValue = (value) ? value : "";
00822   while (*strValue) 
00823     {
00824     if (*strValue == '\\') 
00825       {
00826       *buffer++ = '\\';
00827       *buffer++ = *strValue++;
00828       continue;
00829       }
00830     if (*strValue == '\"') 
00831       {
00832       *buffer++ = '\\';
00833       *buffer++ = *strValue++;
00834       continue;
00835       }
00836     if (*strValue == '\n') 
00837       {
00838       *buffer++ = '\\';
00839       *buffer++ = 'n';
00840       strValue++;
00841       continue;
00842       }
00843     *buffer++ = *strValue++;
00844     }
00845   
00846   *buffer++ = '\0';
00847   
00848   int currentLevel = LevelStack.size();
00849   if ( GzFile ) 
00850     {
00851     for ( int level = 0; level < currentLevel; level++)
00852       gzputs( GzFile, "\t" );
00853     gzprintf( GzFile, "%s \"%s\"\n", key, Buffer);
00854     } 
00855   else
00856     {
00857     for ( int level = 0; level < currentLevel; level++)
00858       fputs( "\t", File );
00859     fprintf( File, "%s \"%s\"\n", key, Buffer);
00860     }
00861   
00862   return TYPEDSTREAM_OK;
00863 }
00864 
00865 TypedStreamCondition 
00866 TypedStream
00867 ::WriteComment( const char* fmt, ... )
00868 {
00869   if ( this->Mode != TYPEDSTREAM_WRITE ) 
00870     {
00871     Status = TYPEDSTREAM_ERROR_MODE;
00872     return TYPEDSTREAM_ERROR;
00873     }
00874 
00875   static char buffer[1024];
00876 
00877   va_list args;
00878   va_start(args, fmt);
00879   vsnprintf( buffer, sizeof( buffer ), fmt, args );
00880   va_end(args);
00881 
00882   if ( this->GzFile )
00883     gzprintf( GzFile, "! %s\n", buffer );
00884   else
00885     fprintf( File, "! %s\n", buffer );
00886 
00887   return TYPEDSTREAM_OK;
00888 }
00889 
00890 TypedStreamCondition 
00891 TypedStream
00892 ::WriteComment( int argc, char* argv[] )
00893 {
00894   return this->WriteComment( argc, const_cast<const char**>( argv ) );
00895 }
00896 
00897 TypedStreamCondition 
00898 TypedStream
00899 ::WriteComment( const int argc, const char* argv[] )
00900 {
00901   if ( this->Mode != TYPEDSTREAM_WRITE ) 
00902     {
00903     Status = TYPEDSTREAM_ERROR_MODE;
00904     return TYPEDSTREAM_ERROR;
00905     }
00906 
00907   if ( this->GzFile )
00908     gzprintf( GzFile, "! " );
00909   else
00910     fprintf( File, "! " );
00911 
00912   for ( int i = 0; i < argc; ++i )
00913     {
00914   if ( this->GzFile )
00915     gzprintf( GzFile, "%s ", argv[i] );
00916   else
00917     fprintf( File, "%s ", argv[i] );
00918     }
00919 
00920   if ( this->GzFile )
00921     gzputs( GzFile, "\n" );
00922   else
00923     fputs( "\n", File );
00924 
00925   return TYPEDSTREAM_OK;
00926 }
00927 
00928 TypedStreamCondition
00929 TypedStream
00930 ::WriteIntArray( const char* key, const int* array, const int size, const int valuesPerLine )
00931 {
00932   if ( !array || size < 1) 
00933     {
00934     Status = TYPEDSTREAM_ERROR_ARG;
00935     return TYPEDSTREAM_ERROR;
00936     }
00937   
00938   int currentLevel = LevelStack.size();
00939   if ( GzFile ) 
00940     {
00941     for ( int level = 0; level < currentLevel; level++)
00942       gzputs( GzFile, "\t" );
00943     
00944     gzprintf( File, "%s ", key );
00945     
00946     for ( int i = 0; i < size; i++) 
00947       {
00948       if (i && (i % valuesPerLine) == 0) 
00949         {
00950         gzprintf( GzFile, "\n\t");
00951         for ( int level = 0; level < currentLevel; level++ )
00952           gzputs( GzFile, "\t" );
00953         }
00954       gzprintf( GzFile, "%d ", array[i] );
00955       }
00956     
00957     gzputs( GzFile, "\n" );
00958     } 
00959   else
00960     {
00961     for ( int level = 0; level < currentLevel; level++)
00962       fputs( "\t", File );
00963     
00964     fprintf( File, "%s ", key );
00965     
00966     for ( int i = 0; i < size; i++) 
00967       {
00968       if (i && (i % valuesPerLine) == 0) 
00969         {
00970         fprintf( File, "\n\t");
00971         for ( int level = 0; level < currentLevel; level++ )
00972           fputs( "\t", File );
00973         }
00974       fprintf( File, "%d ", array[i] );
00975       }
00976     
00977     fputs( "\n", File);
00978     }
00979   
00980   return TYPEDSTREAM_OK;
00981 }
00982 
00983 TypedStreamCondition
00984 TypedStream
00985 ::WriteBoolArray( const char* key, const byte* array, const int size, const int valuesPerLine )
00986 {
00987   if ( !array || size < 1) 
00988     {
00989     Status = TYPEDSTREAM_ERROR_ARG;
00990     return TYPEDSTREAM_ERROR;
00991     }
00992   
00993   int currentLevel = LevelStack.size();
00994   if ( GzFile ) 
00995     {
00996     for ( int level = 0; level < currentLevel; level++)
00997       gzputs( GzFile, "\t" );
00998     
00999     gzprintf( GzFile, "%s ", key );
01000     
01001     for ( int i = 0; i < size; i++) 
01002       {
01003       if (i && (i % valuesPerLine) == 0) 
01004         {
01005         gzprintf( GzFile, "\n\t");
01006         for ( int level = 0; level < currentLevel; level++ )
01007           gzputs( GzFile, "\t" );
01008         }
01009       gzprintf( GzFile, "%d", (array[i/8]>>(i%8))&1 );
01010       }
01011     
01012     gzputs( GzFile, "\n" );
01013     }
01014   else
01015     {
01016     for ( int level = 0; level < currentLevel; level++)
01017       fputs( "\t", File );
01018     
01019     fprintf( File, "%s ", key );
01020     
01021     for ( int i = 0; i < size; i++) 
01022       {
01023       if (i && (i % valuesPerLine) == 0) 
01024         {
01025         fprintf( File, "\n\t");
01026         for ( int level = 0; level < currentLevel; level++ )
01027           fputs( "\t", File );
01028         }
01029       fprintf( File, "%d", (array[i/8]>>(i%8))&1 );
01030       }
01031     
01032     fputs( "\n", File );
01033     }
01034   
01035   return TYPEDSTREAM_OK;
01036 }
01037 
01038 TypedStreamCondition
01039 TypedStream
01040 ::WriteFloatArray( const char* key, const float* array, const int size, const int valuesPerLine )
01041 {
01042   if ( !array || size < 1) 
01043     {
01044     Status = TYPEDSTREAM_ERROR_ARG;
01045     return TYPEDSTREAM_ERROR;
01046     }
01047   
01048   int currentLevel = LevelStack.size();
01049   if ( GzFile ) 
01050     {
01051     for ( int level = 0; level < currentLevel; level++)
01052       gzputs( GzFile, "\t" );
01053     
01054     gzprintf( GzFile, "%s ", key );
01055     
01056     for ( int i = 0; i < size; i++ ) 
01057       {
01058       if (i && (i % valuesPerLine) == 0) 
01059         {
01060         gzprintf( GzFile, "\n\t");
01061         for ( int level = 0; level < currentLevel; level++ )
01062           gzputs( GzFile, "\t" );
01063         }
01064       gzprintf( GzFile, "%.*g ", PrecisionFloat, array[i] );
01065       }
01066     
01067     gzprintf( GzFile, "\n" );
01068     } 
01069   else
01070     {
01071     for ( int level = 0; level < currentLevel; level++)
01072       fputs( "\t", File );
01073     
01074     fprintf( File, "%s ", key );
01075     
01076     for ( int i = 0; i < size; i++ ) 
01077       {
01078       if (i && (i % valuesPerLine) == 0) 
01079         {
01080         fprintf( File, "\n\t");
01081         for ( int level = 0; level < currentLevel; level++ )
01082           fputs( "\t", File );
01083         }
01084       fprintf( File, "%.*g ", PrecisionFloat, array[i] );
01085       }
01086     
01087     fprintf( File, "\n" );
01088     }
01089   
01090   return TYPEDSTREAM_OK;
01091 }
01092 
01093 TypedStreamCondition
01094 TypedStream
01095 ::WriteDoubleArray( const char* key, const double* array, const int size, const int valuesPerLine )
01096 {
01097   if ( !array || size < 1) 
01098     {
01099     Status = TYPEDSTREAM_ERROR_ARG;
01100     return TYPEDSTREAM_ERROR;
01101     }
01102   
01103   int currentLevel = LevelStack.size();
01104   if ( GzFile )
01105     {
01106     for ( int level = 0; level < currentLevel; level++)
01107       gzputs( GzFile, "\t" );
01108     
01109     gzprintf( GzFile, "%s ", key );
01110     
01111     for ( int i = 0; i < size; i++ ) 
01112       {
01113       if (i && (i % valuesPerLine) == 0) 
01114         {
01115         gzprintf( GzFile, "\n\t");
01116         for ( int level = 0; level < currentLevel; level++ )
01117           gzputs( GzFile, "\t" );
01118         }
01119       gzprintf( GzFile, "%.*g ", PrecisionDouble, array[i] );
01120       }
01121     
01122     gzprintf( GzFile, "\n" );
01123     } 
01124   else
01125     {
01126     for ( int level = 0; level < currentLevel; level++)
01127       fputs( "\t", File );
01128     
01129     fprintf( File, "%s ", key );
01130     
01131     for ( int i = 0; i < size; i++ ) 
01132       {
01133       if (i && (i % valuesPerLine) == 0) 
01134         {
01135         fprintf( File, "\n\t");
01136         for ( int level = 0; level < currentLevel; level++ )
01137           fputs( "\t", File );
01138         }
01139       fprintf( File, "%.*g ", PrecisionDouble, array[i] );
01140       }
01141     
01142     fprintf( File, "\n" );
01143     }
01144   
01145   return TYPEDSTREAM_OK;
01146 }
01147 
01148 TypedStreamCondition
01149 TypedStream
01150 ::GenericReadArray( const char * key, const int type, void *const array, const int arraySize, const bool forward )
01151 {
01152   if (!array || arraySize < 1) 
01153     {
01154     Status = TYPEDSTREAM_ERROR_ARG;
01155     return TYPEDSTREAM_ERROR;
01156     }
01157   
01158   unsigned currentLevel = LevelStack.size();
01159   if ( ! forward ) 
01160     {
01161     if ( GzFile ) 
01162       {
01163       if ( currentLevel )
01164         gzseek( GzFile, LevelStack.top(), SEEK_SET );
01165       else
01166         gzseek( GzFile, 0, SEEK_SET );
01167       }
01168     else
01169       if ( currentLevel )
01170         fseek( File, LevelStack.top(), SEEK_SET );
01171       else
01172         fseek( File, 0, SEEK_SET );
01173     }
01174   
01175   int line;
01176   char *buffer;
01177   while ( TYPEDSTREAM_EOF != ( line = this->ReadLineToken() ) ) 
01178     {
01179     if ( line == TYPEDSTREAM_KEY) 
01180       {
01181       if ( (currentLevel == LevelStack.size()) && (this->StringCmp( BufferKey, key )) == 0 ) 
01182         {
01183         int i = 0;
01184         switch (type) 
01185           {
01186           case TYPEDSTREAM_TYPE_INT: 
01187           {
01188           int *arrayInt = static_cast<int*>( array ); 
01189           do
01190             {
01191             buffer = strtok( BufferValue, "\t\n " );
01192             while ( buffer ) 
01193               {
01194               if ( *buffer == '\"' ) 
01195                 {
01196                 Status = TYPEDSTREAM_ERROR_TYPE;
01197                 return TYPEDSTREAM_ERROR;
01198                 }
01199               if ( i >= arraySize )
01200                 return TYPEDSTREAM_OK;
01201               arrayInt[i++] = atoi(buffer);
01202               buffer = strtok( NULL, "\t\n " );
01203               }
01204             } while ( i < arraySize && TYPEDSTREAM_VALUE == this->ReadLineToken() );
01205           if ( i < arraySize) 
01206             {
01207             Status = TYPEDSTREAM_ERROR_ARG;
01208             return TYPEDSTREAM_ERROR;
01209             }
01210           break;
01211           }
01212           case TYPEDSTREAM_TYPE_BOOL: 
01213           {
01214           int *arrayInt = static_cast<int*>( array ); 
01215           if (arraySize != 1) 
01216             {
01217             Status = TYPEDSTREAM_ERROR_ARG;
01218             return TYPEDSTREAM_ERROR;
01219             }
01220           do 
01221             {
01222             buffer = strtok( BufferValue, "\t\n " );
01223             while ( buffer ) 
01224               {
01225               if ( i >= arraySize )
01226                 return TYPEDSTREAM_OK;
01227               if ((buffer[0] == 'y' || buffer[0] == 'Y') &&
01228                   (buffer[1] == 'e' || buffer[1] == 'E') &&
01229                   (buffer[2] == 's' || buffer[2] == 'S')) 
01230                 {
01231                 arrayInt[i++] = 1;
01232                 }
01233               else
01234                 {
01235                 arrayInt[i++] = 0;
01236                 }
01237               buffer = strtok( NULL, "\t\n " );
01238               }
01239             } while ( i < arraySize && TYPEDSTREAM_VALUE == this->ReadLineToken() );
01240           if ( i < arraySize ) 
01241             {
01242             Status = TYPEDSTREAM_ERROR_ARG;
01243             return TYPEDSTREAM_ERROR;
01244             }
01245           break;
01246           }
01247           case TYPEDSTREAM_TYPE_BINARYBOOL: 
01248           {
01249           byte *arrayInt = static_cast<byte*>( array ); 
01250           do 
01251             {
01252             buffer = strtok( BufferValue, "\t\n " );
01253             int idx = 0;
01254             while ( (buffer[idx]=='0') || (buffer[idx]=='1') ) 
01255               {
01256               if ( i >= arraySize )
01257                 return TYPEDSTREAM_OK;
01258               if ( buffer[idx] == '0' )
01259                 arrayInt[i/8] &= ~(1<<(i%8));
01260               else
01261                 arrayInt[i/8] |= (1<<(i%8));
01262               ++i;
01263               ++idx;
01264               }
01265             } while ( i < arraySize && TYPEDSTREAM_VALUE == this->ReadLineToken() );
01266           if ( i < arraySize ) 
01267             {
01268             Status = TYPEDSTREAM_ERROR_ARG;
01269             return TYPEDSTREAM_ERROR;
01270             }
01271           break;
01272           }
01273           case TYPEDSTREAM_TYPE_FLOAT: 
01274           {
01275           float *arrayFloat = static_cast<float*>( array );
01276           do
01277             {
01278             buffer = strtok( BufferValue, "\t\n " );
01279             while ( buffer ) 
01280               {
01281               if ( *buffer == '\"' ) 
01282                 {
01283                 Status = TYPEDSTREAM_ERROR_TYPE;
01284                 return TYPEDSTREAM_ERROR;
01285                 }
01286               if ( i >= arraySize )
01287                 return TYPEDSTREAM_OK;
01288               arrayFloat[i++] = static_cast<float>( atof( buffer ) );
01289               buffer = strtok( NULL, "\t\n " );
01290               }
01291             } while ( i < arraySize && TYPEDSTREAM_VALUE == this->ReadLineToken() );
01292           if ( i < arraySize ) 
01293             {
01294             Status = TYPEDSTREAM_ERROR_ARG;
01295             return TYPEDSTREAM_ERROR;
01296             }
01297           break;
01298           }
01299         case TYPEDSTREAM_TYPE_DOUBLE: 
01300         {
01301         double *arrayDouble = static_cast<double*>( array );
01302         do
01303           {
01304           buffer = strtok( BufferValue, "\t\n " );
01305           while ( buffer ) 
01306             {
01307             if ( *buffer == '\"' ) 
01308               {
01309               Status = TYPEDSTREAM_ERROR_TYPE;
01310               return TYPEDSTREAM_ERROR;
01311               }
01312             if ( i >= arraySize )
01313               return TYPEDSTREAM_OK;
01314             arrayDouble[i++] = atof( buffer );
01315             buffer = strtok( NULL, "\t\n " );
01316             }
01317           } while ( i < arraySize && TYPEDSTREAM_VALUE == this->ReadLineToken() );
01318         if ( i < arraySize ) 
01319           {
01320           Status = TYPEDSTREAM_ERROR_ARG;
01321           return TYPEDSTREAM_ERROR;
01322           }
01323         break;
01324         }
01325           case TYPEDSTREAM_TYPE_STRING: 
01326           {
01327           char **arrayString = static_cast<char**>( array );
01328           do 
01329             {
01330             buffer = this->StringSplit( BufferValue );
01331             while ( buffer ) 
01332               {
01333               if ( i >= arraySize )
01334                 return TYPEDSTREAM_OK;
01335               if ( *buffer != '\"' ) 
01336                 {
01337                 Status = TYPEDSTREAM_ERROR_TYPE;
01338                 return TYPEDSTREAM_ERROR;
01339                 }
01340               char *b;
01341               if (!(b = (char *)malloc(strlen(buffer)))) 
01342                 {
01343                 for (--i; i >= 0; i--)
01344                   free( arrayString[i] );
01345                 Status = TYPEDSTREAM_ERROR_SYSTEM;
01346                 return TYPEDSTREAM_ERROR;
01347                 }
01348               arrayString[i++] = b;
01349               buffer++;
01350               for (; *buffer && *buffer != '\n'; buffer++) 
01351                 {
01352                 if (*buffer == '\"')
01353                   continue;
01354                 if (*buffer == '\\') 
01355                   {
01356                   buffer++;
01357                   if (*buffer == 'n') 
01358                     {
01359                     *b++ = '\n';
01360                     continue;
01361                     }
01362                   if (*buffer == 't') 
01363                     {
01364                     *b++ = '\t';
01365                     continue;
01366                     }
01367                   if (*buffer == '\0')
01368                     break;
01369                   }
01370                 *b++ = *buffer;
01371                 }
01372               *b = '\0';
01373               buffer = this->StringSplit( NULL );
01374               }
01375             } while ( i < arraySize && TYPEDSTREAM_VALUE == this->ReadLineToken() );
01376           if ( i < arraySize ) 
01377             {
01378             for (--i; i >= 0; i--)
01379               free( arrayString[i] );
01380             Status = TYPEDSTREAM_ERROR_ARG;
01381             return TYPEDSTREAM_ERROR;
01382             }
01383           break;
01384           }
01385           }
01386         return TYPEDSTREAM_OK;
01387         }
01388       continue;
01389       }
01390     if ( line == TYPEDSTREAM_BEGIN ) 
01391       {
01392       if ( GzFile )
01393         LevelStack.push( gztell( GzFile ) );
01394       else
01395         LevelStack.push( ftell( File ) );
01396       continue;
01397       }
01398     if ( line == TYPEDSTREAM_END ) 
01399       {
01400       if ( currentLevel == LevelStack.size() ) 
01401         {
01402         Status = TYPEDSTREAM_ERROR_NONE;
01403         return TYPEDSTREAM_ERROR;
01404         }
01405       LevelStack.pop();
01406       continue;
01407       }
01408     }
01409   
01410   return TYPEDSTREAM_ERROR;
01411 }
01412 
01413 TypedStreamToken
01414 TypedStream
01415 ::ReadLineToken()
01416 {
01417   if ( GzFile )
01418     {
01419     if (! gzgets( GzFile, Buffer, TYPEDSTREAM_LIMIT_BUFFER ) )
01420       return TYPEDSTREAM_EOF;
01421     }
01422   else
01423     if (! fgets( Buffer, TYPEDSTREAM_LIMIT_BUFFER, File ) )
01424       return TYPEDSTREAM_EOF;
01425   
01426   char* buffer;
01427   for ( buffer = Buffer; *buffer; buffer++)
01428     if (*buffer != ' ' && *buffer != '\t')
01429       break;
01430 
01431   if (*buffer == '\n' || *buffer == '!' || *buffer == '#')
01432     return TYPEDSTREAM_COMMENT;
01433 
01434   if (*buffer == '}')
01435     return TYPEDSTREAM_END;
01436   
01437   if (*buffer == '\"' || *buffer == '-' || *buffer == '.' || (*buffer >= '0' && *buffer <= '9')) 
01438     {
01439     BufferValue = buffer;
01440     return TYPEDSTREAM_VALUE;
01441     }
01442   
01443   if (*buffer == '_' || (*buffer >= 'a' && *buffer <= 'z') || (*buffer >= 'A' && *buffer <= 'Z')) 
01444     {
01445     BufferKey = buffer;
01446     for (; *buffer; buffer++)
01447       if (*buffer == ' ' || *buffer == '\t')
01448         break;
01449     for (; *buffer; buffer++)
01450       if (*buffer != ' ' && *buffer != '\t')
01451         break;
01452     BufferValue = buffer;
01453     if (*buffer == '{')
01454       return TYPEDSTREAM_BEGIN;
01455     
01456     return TYPEDSTREAM_KEY;
01457     }
01458   
01459   return TYPEDSTREAM_COMMENT;
01460 }
01461 
01462 int
01463 TypedStream
01464 ::StringCmp( const char *s1, const char *s2 )
01465 {
01466   for (; *s1 && *s2; s1++, s2++) 
01467     {
01468     if (*s1 == ' ' || *s1 == '\t' || *s1 == '\n' || *s2 == ' ' || *s2 == '\t' || *s2 == '\n') 
01469       {
01470       break;
01471       }
01472     if (*s1 == *s2)
01473       continue;
01474     if (*s1 >= 'a' && *s1 <= 'z') 
01475       {
01476       if (*s1 - ('a'-'A') == *s2)
01477         continue;
01478       }
01479     if (*s2 >= 'a' && *s2 <= 'z') 
01480       {
01481       if (*s2 - ('a'-'A') == *s1)
01482         continue;
01483       }
01484     return 1;
01485     }
01486   
01487   if ((*s1 == ' ' || *s1 == '\0' || *s1 == '\t' || *s1 == '\n') && (*s2 == ' ' || *s2 == '\0' || *s2 == '\t' || *s2 == '\n')) 
01488     {
01489     return 0;
01490     }
01491   
01492   return 1;
01493 }
01494 
01495 char*
01496 TypedStream
01497 ::StringSplit( char * s1 ) const
01498 {
01499   if (s1)
01500     SplitPosition = s1-1;
01501   if (SplitPosition == NULL)
01502     return NULL;
01503   
01504   /* skip over leading white space */
01505   for ( SplitPosition++; *SplitPosition == '\0' || *SplitPosition == ' ' || 
01506           *SplitPosition == '\t' || *SplitPosition == '\n'; SplitPosition++ )
01507     if ( *SplitPosition == '\0' )
01508       return NULL;
01509   
01510   s1 = SplitPosition;
01511   
01512   /* find token's end */
01513   if ( *SplitPosition == '\"' ) 
01514     {
01515     /* skip over the special string token */
01516     for ( SplitPosition++; *SplitPosition && *SplitPosition != '\n' && *SplitPosition != '\t'; SplitPosition++) 
01517       {
01518       if ( *SplitPosition == '\\' && *(SplitPosition+1) ) 
01519         {
01520         SplitPosition++;
01521         continue;
01522         }
01523       if ( *SplitPosition == '\"' ) 
01524         {
01525         SplitPosition++;
01526         break;
01527         }
01528       }
01529     } 
01530   else
01531     {
01532     /* skip over a numeric value */
01533     for ( ; *SplitPosition; SplitPosition++ ) 
01534       {
01535       if ( *SplitPosition == ' ' || *SplitPosition == '\t' || *SplitPosition == '\n')
01536         break;
01537       }
01538     }
01539   
01540   if ( *SplitPosition ) 
01541     {
01542     *SplitPosition = '\0';
01543     } 
01544   else
01545     {
01546     SplitPosition = NULL;
01547     }
01548   
01549   return s1;
01550 }
01551 
01552 void
01553 TypedStream
01554 ::DebugOutput( const char* format, ... )
01555 {
01556   if ( DebugFlag != TYPEDSTREAM_DEBUG_ON ) return;
01557 
01558   static char buffer[1024];
01559 
01560   va_list args;
01561   va_start(args, format);
01562   vsnprintf( buffer, sizeof( buffer ), format, args );
01563   va_end(args);
01564 
01565   fputs( buffer, stderr );
01566   fputs( "\n", stderr );
01567 }
01568 
01569 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines