00001
00021 #include <stdio.h>
00022 #include "extra.h"
00023 #include "vec.h"
00024
00028
00029 #define EXTRA_BUFFER_SIZE 4*1048576 // 1M - size of the data chunk stored in memory
00030 #define EXTRA_OFFSET_SIZE 4096 // 4K - load new data when less than this is left
00031
00032 #define EXTRA_MINIMUM(a,b) (((a) < (b))? (a) : (b))
00033
00034 struct Extra_FileReader_t_
00035 {
00036
00037 char * pFileName;
00038 FILE * pFile;
00039 int nFileSize;
00040 int nFileRead;
00041
00042 char pCharMap[256];
00043
00044 char * pBuffer;
00045 int nBufferSize;
00046 char * pBufferCur;
00047 char * pBufferEnd;
00048 char * pBufferStop;
00049
00050 Vec_Ptr_t * vTokens;
00051 Vec_Int_t * vLines;
00052 int nLineCounter;
00053
00054 int fStop;
00055 };
00056
00057
00058 typedef enum {
00059 EXTRA_CHAR_COMMENT,
00060 EXTRA_CHAR_NORMAL,
00061 EXTRA_CHAR_STOP,
00062 EXTRA_CHAR_CLEAN
00063 } Extra_CharType_t;
00064
00065
00066 static void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p );
00067 static void Extra_FileReaderReload( Extra_FileReader_t * p );
00068
00072
00084 Extra_FileReader_t * Extra_FileReaderAlloc( char * pFileName,
00085 char * pCharsComment, char * pCharsStop, char * pCharsClean )
00086 {
00087 Extra_FileReader_t * p;
00088 FILE * pFile;
00089 char * pChar;
00090 int nCharsToRead;
00091
00092 pFile = fopen( pFileName, "rb" );
00093 if ( pFile == NULL )
00094 {
00095 printf( "Extra_FileReaderAlloc(): Cannot open input file \"%s\".\n", pFileName );
00096 return NULL;
00097 }
00098
00099 p = ALLOC( Extra_FileReader_t, 1 );
00100 memset( p, 0, sizeof(Extra_FileReader_t) );
00101 p->pFileName = pFileName;
00102 p->pFile = pFile;
00103
00104 memset( p->pCharMap, EXTRA_CHAR_NORMAL, 256 );
00105 for ( pChar = pCharsComment; *pChar; pChar++ )
00106 p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_COMMENT;
00107 for ( pChar = pCharsStop; *pChar; pChar++ )
00108 p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_STOP;
00109 for ( pChar = pCharsClean; *pChar; pChar++ )
00110 p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_CLEAN;
00111
00112 fseek( pFile, 0, SEEK_END );
00113 p->nFileSize = ftell( pFile );
00114 rewind( pFile );
00115
00116 p->pBuffer = ALLOC( char, EXTRA_BUFFER_SIZE+1 );
00117 p->nBufferSize = EXTRA_BUFFER_SIZE;
00118 p->pBufferCur = p->pBuffer;
00119
00120 nCharsToRead = EXTRA_MINIMUM(p->nFileSize, EXTRA_BUFFER_SIZE);
00121
00122 fread( p->pBuffer, nCharsToRead, 1, p->pFile );
00123 p->nFileRead = nCharsToRead;
00124
00125 p->pBufferEnd = p->pBuffer + nCharsToRead;
00126 p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + EXTRA_BUFFER_SIZE - EXTRA_OFFSET_SIZE;
00127
00128 p->vTokens = Vec_PtrAlloc( 100 );
00129 p->vLines = Vec_IntAlloc( 100 );
00130 p->nLineCounter = 1;
00131 return p;
00132 }
00133
00145 void Extra_FileReaderFree( Extra_FileReader_t * p )
00146 {
00147 if ( p->pFile )
00148 fclose( p->pFile );
00149 FREE( p->pBuffer );
00150 Vec_PtrFree( p->vTokens );
00151 Vec_IntFree( p->vLines );
00152 free( p );
00153 }
00154
00166 char * Extra_FileReaderGetFileName( Extra_FileReader_t * p )
00167 {
00168 return p->pFileName;
00169 }
00170
00182 int Extra_FileReaderGetFileSize( Extra_FileReader_t * p )
00183 {
00184 return p->nFileSize;
00185 }
00186
00198 int Extra_FileReaderGetCurPosition( Extra_FileReader_t * p )
00199 {
00200 return p->nFileRead - (p->pBufferEnd - p->pBufferCur);
00201 }
00202
00214 int Extra_FileReaderGetLineNumber( Extra_FileReader_t * p, int iToken )
00215 {
00216 assert( iToken >= 0 && iToken < p->vTokens->nSize );
00217 return p->vLines->pArray[iToken];
00218 }
00219
00220
00232 void * Extra_FileReaderGetTokens( Extra_FileReader_t * p )
00233 {
00234 Vec_Ptr_t * vTokens;
00235 while ( vTokens = Extra_FileReaderGetTokens_int( p ) )
00236 if ( vTokens->nSize > 0 )
00237 break;
00238 return vTokens;
00239 }
00240
00252 void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p )
00253 {
00254 char * pChar;
00255 int fTokenStarted, MapValue;
00256 if ( p->fStop )
00257 return NULL;
00258
00259 p->vTokens->nSize = 0;
00260 p->vLines->nSize = 0;
00261 fTokenStarted = 0;
00262
00263 if ( p->pBufferCur > p->pBufferStop )
00264 Extra_FileReaderReload( p );
00265
00266
00267
00268
00269 for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ )
00270 {
00271
00272 if ( *pChar == '\n' )
00273 p->nLineCounter++;
00274
00275 MapValue = p->pCharMap[*pChar];
00276
00277
00278
00279
00280 switch ( MapValue )
00281 {
00282 case EXTRA_CHAR_COMMENT:
00283 if ( *pChar != '/' || *(pChar+1) == '/' )
00284 {
00285
00286 if ( fTokenStarted )
00287 fTokenStarted = 0;
00288
00289 while ( *pChar != '\n' )
00290 {
00291 *pChar++ = 0;
00292 if ( pChar == p->pBufferEnd )
00293 {
00294
00295 printf( "Extra_FileReader failed to parse the file \"%s\".\n", p->pFileName );
00296 return NULL;
00297 }
00298 }
00299 pChar--;
00300 break;
00301 }
00302
00303 case EXTRA_CHAR_NORMAL:
00304 if ( !fTokenStarted )
00305 {
00306 Vec_PtrPush( p->vTokens, pChar );
00307 Vec_IntPush( p->vLines, p->nLineCounter );
00308 fTokenStarted = 1;
00309 }
00310 break;
00311 case EXTRA_CHAR_STOP:
00312 if ( fTokenStarted )
00313 fTokenStarted = 0;
00314 *pChar = 0;
00315
00316 p->pBufferCur = pChar + 1;
00317 return p->vTokens;
00318 case EXTRA_CHAR_CLEAN:
00319 if ( fTokenStarted )
00320 fTokenStarted = 0;
00321 *pChar = 0;
00322 break;
00323 default:
00324 assert( 0 );
00325 }
00326 }
00327
00328
00329 if ( p->pBufferStop == p->pBufferEnd )
00330 {
00331 *pChar = 0;
00332 p->fStop = 1;
00333 return p->vTokens;
00334 }
00335 printf( "Extra_FileReader failed to parse the file \"%s\".\n", p->pFileName );
00336
00337
00338
00339
00340
00341
00342
00343
00344 return NULL;
00345 }
00346
00358 void Extra_FileReaderReload( Extra_FileReader_t * p )
00359 {
00360 int nCharsUsed, nCharsToRead;
00361 assert( !p->fStop );
00362 assert( p->pBufferCur > p->pBufferStop );
00363 assert( p->pBufferCur < p->pBufferEnd );
00364
00365 nCharsUsed = p->pBufferEnd - p->pBufferCur;
00366
00367 memmove( p->pBuffer, p->pBufferCur, nCharsUsed );
00368 p->pBufferCur = p->pBuffer;
00369
00370 nCharsToRead = EXTRA_MINIMUM( p->nBufferSize - nCharsUsed, p->nFileSize - p->nFileRead );
00371
00372 fread( p->pBuffer + nCharsUsed, nCharsToRead, 1, p->pFile );
00373 p->nFileRead += nCharsToRead;
00374
00375 p->pBufferEnd = p->pBuffer + nCharsUsed + nCharsToRead;
00376 p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + EXTRA_BUFFER_SIZE - EXTRA_OFFSET_SIZE;
00377 }
00378
00382
00383