00001
00002
00003 #include <string.h>
00004 #include "gconfig.h"
00005
00006
00007
00008
00009
00010 gFileFetch::gFileFetch (int maxLines)
00011 : gFileText( NULL, false ),
00012 doEndNewLine( false ),
00013 maxNLines( maxLines ),
00014 isFetchBufferOk( true ),
00015 doResize( false ),
00016 doShowProgress( false ),
00017 fVRepErr( nil )
00018 {
00019 }
00020
00021 gFileFetch::gFileFetch (gString& sFName, int maxLines)
00022 : gFileText( sFName.Str(), true ),
00023 doEndNewLine( false ),
00024 maxNLines( maxLines ),
00025 isFetchBufferOk( true ),
00026 doResize( IsDevice()==false ),
00027 doShowProgress( false ),
00028 fVRepErr( nil )
00029 {
00030 bool isOk;
00031 thisReadFile( isOk, aL );
00032 }
00033
00034 gFileFetch::gFileFetch (char* fName, int maxLines, bool aShowProgress)
00035 : gFileText( fName, true ),
00036 doEndNewLine( false ),
00037 maxNLines( maxLines ),
00038 isFetchBufferOk( true ),
00039 doResize( IsDevice()==false ),
00040 doShowProgress( aShowProgress ),
00041 fVRepErr( nil )
00042 {
00043 bool isOk;
00044 if ( fName==NULL || fName[0]==0 ) {
00045 OpenDevice( e_fStdin );
00046 ASSERTION(doShowProgress==false,"progress?");
00047 }
00048 else {
00049 if ( doShowProgress ) SetDeviceReport( e_fStderr );
00050 }
00051 thisReadFile( isOk, aL );
00052 }
00053
00054 gFileFetch::gFileFetch (gString& sInput, bool aShowProgress)
00055 : gFileText( nil, false ),
00056 doEndNewLine( false ),
00057 maxNLines( -1 ),
00058 isFetchBufferOk( true ),
00059 doResize( false ),
00060 doShowProgress( aShowProgress ),
00061 fVRepErr( nil )
00062 {
00063 if ( doShowProgress ) SetDeviceReport( e_fStderr );
00064 thisReadStringAsFile( sInput, aL );
00065 }
00066
00067 gFileFetch::~gFileFetch ()
00068 {
00069 }
00070
00071 bool gFileFetch::SetFileReport (FILE* fRep)
00072 {
00073 doShowProgress = fRep!=nil;
00074 fVRepErr = fRep;
00075 return doShowProgress;
00076 }
00077
00078 bool gFileFetch::SetDeviceReport (eDeviceKind aDKind)
00079 {
00080 fVRepErr = nil;
00081 switch ( aDKind ) {
00082 case e_fDevOther:
00083 case e_fStdin:
00084 return false;
00085 case e_fStdout:
00086 fVRepErr = stdout;
00087 break;
00088 case e_fStderr:
00089 fVRepErr = stderr;
00090 break;
00091 default:
00092 return false;
00093 }
00094
00095 return SetFileReport( fVRepErr );
00096 }
00097
00098 bool gFileFetch::Fetch (gString& sFName)
00099 {
00100 bool isOk;
00101 int res;
00102
00103 isOk = sFName.IsEmpty()==false && OpenToRead( sFName.Str() )==true;
00104 if ( isOk==false ) return false;
00105 res = thisReadFile( isOk, aL );
00106 ASSERTION(res!=2,"res!=2");
00107 return isOk;
00108 }
00109
00110 int gFileFetch::thisReadFile (bool& isOk, gList& zL)
00111 {
00112 int error = 0;
00113 t_uint32 nBytes;
00114
00115 if ( IsOpened()==false ) return 2;
00116
00117 error = thisReadAll( isOk, isFetchBufferOk, zL );
00118 if ( error!=0 ) return error;
00119 if ( doResize==false ) return error;
00120
00121 ASSERTION(IsDevice()==false,"IsDevice()==false");
00122
00123 if ( isFetchBufferOk ) return 0;
00124
00125 zL.Delete();
00126 if ( Rewind()==false ) return 1;
00127 thisReadFileThrough( zL, nBytes );
00128 error = nBytes<Size() ? 4 : 0;
00129
00130 isFetchBufferOk = error==0;
00131 return error;
00132 }
00133
00134 int gFileFetch::thisReadAll (bool& isOk, bool& isBufOk, gList& zL)
00135 {
00136 int iCount=0;
00137
00138 isBufOk = true;
00139
00140 while ( ReadLine( isOk, doEndNewLine ) ) {
00141 iCount++;
00142 if ( maxNLines>=0 && iCount>maxNLines ) {
00143 doEndNewLine = true;
00144 return lastOpError = -9;
00145 }
00146
00147 #ifdef TARFS_MICE
00148 static t_uint16 dummyCount;
00149 t_uint16 dummyRand = gStorageControl::Self().GetRandom(TARFS_MICE), dummyLimit;
00150 dummyLimit = dummyRand<1;
00151 if ( dummyLimit!=0 ) {
00152 if ( dummyCount++==0 ) fprintf(stderr,"@TARFS_MICE: skipped (%u:%u)\n",dummyRand,TARFS_MICE);
00153 }
00154 if ( dummyLimit!=0 )
00155 #endif //TARFS_MICE
00156 zL.Add( Buffer() );
00157 if ( isBufferOk==false ) isBufOk = false;
00158 }
00159 isOk = true;
00160
00161 return 0;
00162 }
00163
00164 int gFileFetch::thisReadFileThrough (gList& zL, t_uint32& nBytes)
00165 {
00166 int iChr;
00167 t_uchar c;
00168 gString s;
00169 t_uint32 aSize = Size();
00170
00171 nBytes = 0;
00172 while ( (iChr = fgetc( f ))>=0 ) {
00173 c = (t_uchar)iChr;
00174 nBytes++;
00175 if ( c=='\r' ) continue;
00176 if ( c=='\n' ) {
00177 zL.Add( s );
00178 s.SetEmpty();
00179 if ( doShowProgress ) {
00180 fprintf(fVRepErr,"%ld of %ld\r",(long)nBytes,(long)aSize);
00181 fflush( fVRepErr );
00182 }
00183 continue;
00184 }
00185 s.Add( c );
00186 }
00187 if ( doShowProgress ) {
00188 fprintf(fVRepErr,".%20s\n"," ");
00189 }
00190 if ( s.IsEmpty() ) return 0;
00191 zL.Add( s );
00192 return 0;
00193 }
00194
00195 int gFileFetch::thisReadStringAsFile (gString& sInput, gList& zL)
00196 {
00197 unsigned i, len=sInput.Length();
00198 char* str;
00199 char chr;
00200
00201 gString sLine;
00202 for (i=0, str=sInput.Str(); i<len; i++) {
00203 chr = str[i];
00204 if ( chr=='\r' ) continue;
00205 if ( chr=='\n' ) {
00206 zL.Add( sLine );
00207 sLine.SetEmpty();
00208 }
00209 else {
00210 sLine.Add( chr );
00211 }
00212 }
00213 doEndNewLine = sLine.IsEmpty();
00214 if ( doEndNewLine==false ) zL.Add( sLine );
00215 return 0;
00216 }
00217
00218 gConfig::gConfig (eConfKind aKind)
00219 : lastOpError( 0 ),
00220 maxNLines( -1 )
00221 {
00222 SetConfKind( aKind );
00223 thisConfigInit();
00224 }
00225
00226 gConfig::gConfig (eConfKind aKind, char* fName, bool doOpenToRead)
00227 : lastOpError( 0 ),
00228 maxNLines( -1 )
00229 {
00230 SetConfKind( aKind );
00231 thisConfigInit();
00232 if ( doOpenToRead )
00233 lastOpError = thisRead( fName, cfgL, linesInputL );
00234 }
00235
00236 gConfig::~gConfig ()
00237 {
00238 thisConfigDelete();
00239 }
00240
00241 bool gConfig::HasSection (unsigned idxSection)
00242 {
00243 unsigned nLines;
00244 return HasSection( idxSection, nLines );
00245 }
00246
00247 bool gConfig::HasSection (unsigned idxSection, unsigned& nLines)
00248 {
00249 if ( hasSections==false ) return false;
00250 if ( idxSection>=1 && idxSection<=nConf ) {
00251 nLines = confL[idxSection].N();
00252 return true;
00253 }
00254 return false;
00255 }
00256
00257 unsigned gConfig::GetSectionFromName (char* sSection)
00258 {
00259 unsigned i;
00260 if ( sSection==nil ) return 0;
00261 for (i=1; i<=nConf; i++) {
00262 gString sTemp( sSection );
00263 if ( sTemp.Match( sectL.Str(i) ) ) return i;
00264 }
00265 return 0;
00266 }
00267
00268 gList* gConfig::GetSection (char* sSection)
00269 {
00270 unsigned i = GetSectionFromName( sSection );
00271 if ( i==0 ) return nil;
00272 return &conpL[ i ];
00273 }
00274
00275 bool gConfig::GetSectionLine (unsigned idxSection,
00276 unsigned idxLine,
00277 gString& sSep,
00278 gString& sLeft,
00279 gString& sRight,
00280 bool& isAssign)
00281 {
00282 unsigned nLines;
00283 gStorage* inObjL;
00284 gList* inL;
00285
00286 sSep.SetEmpty();
00287
00288 isAssign = false;
00289 if ( HasSection( idxSection, nLines )==false )
00290 return false;
00291 if ( idxLine<1 || idxLine>nLines )
00292 return false;
00293
00294 inObjL = conpL[idxSection].GetObjectPtr(idxLine);
00295 isAssign = inObjL->Kind()==e_List;
00296 if ( isAssign==false ) {
00297
00298 if ( inObjL->Kind()!=e_String ) return false;
00299 sLeft = inObjL->Str();
00300
00301
00302 return sLeft.IsEmpty()==false;
00303 }
00304 inL = (gList*)inObjL;
00305 isAssign = inL->N()==3;
00306 if ( isAssign ) {
00307 sSep = inL->Str( 1 );
00308 sLeft = inL->Str( 2 );
00309 sRight = inL->Str( 3 );
00310 }
00311 return isAssign;
00312 }
00313
00314 bool gConfig::SetConfKind (eConfKind aKind)
00315 {
00316 confKind = aKind;
00317 hasSections = false;
00318
00319 switch ( aKind ) {
00320 case e_ConfLinearFree:
00321 case e_ConfLinear:
00322 break;
00323 case e_ConfSectionStrict:
00324 case e_ConfSectionFree:
00325 hasSections = true;
00326 default:
00327 return false;
00328 }
00329 return true;
00330 }
00331
00332 bool gConfig::Process ()
00333 {
00334 if ( sFileName.IsEmpty() ) return false;
00335 return Process( sFileName.Str() );
00336 }
00337
00338 bool gConfig::Process (char* fName)
00339 {
00340 lastOpError = thisRead( fName, cfgL, linesInputL );
00341 return lastOpError==0;
00342 }
00343
00344 int gConfig::thisConfigInit ()
00345 {
00346 lineStartCommentL.Add( (char*)"#" );
00347 lineStartPos = 0;
00348 doTrim = true;
00349 lineSepChrs = (char*)"=";
00350 lineSepStrs.Delete();
00351
00352 sectionStartPos = 1;
00353 sectionSep = (char*)"[]";
00354
00355 iLineError = 0;
00356 nConf = 0;
00357 confL = conpL = nil;
00358 return 0;
00359 }
00360
00361 int gConfig::thisConfigDelete ()
00362 {
00363 linesInputL.Delete();
00364 cfgL.Delete();
00365 nConf = 0;
00366 sectL.Delete();
00367 delete[] confL;
00368 confL = nil;
00369 delete[] conpL;
00370 conpL = nil;
00371 return 0;
00372 }
00373
00374 int gConfig::thisRead (char* fName, gList& aL, gList& idxL)
00375 {
00376 bool isOk;
00377 bool isComment;
00378 int lineCount=0;
00379 unsigned i, pos;
00380
00381 ASSERTION(fName!=nil,"fName!=nil");
00382 sFileName = fName;
00383
00384 thisConfigDelete();
00385
00386 gFileText fCfg( fName );
00387 if ( fCfg.IsOpened()==false ) return 2;
00388 while ( fCfg.ReadLine(isOk) ) {
00389 lineCount++;
00390 if ( maxNLines>=0 && lineCount>maxNLines ) return 3;
00391 gString sTemp( fCfg.UBuffer() );
00392 gString sTrim( sTemp );
00393 if ( doTrim ) sTrim.Trim();
00394
00395 isComment = false;
00396 unsigned nCom = lineStartCommentL.N();
00397 for (i=1, pos=0; i<=nCom && isComment==false; i++) {
00398 gString sLineStartComment( lineStartCommentL.Str(i) );
00399 pos = sTrim.Find( sLineStartComment );
00400 if ( lineStartPos==0 ) {
00401
00402
00403
00404
00405
00406 if ( pos>0 ) isComment = true;
00407 }
00408 else {
00409 if ( pos==lineStartPos ) isComment = true;
00410 }
00411 }
00412 if ( isComment ) {
00413 if ( pos<=1 ) continue;
00414 sTrim.Delete( pos );
00415 if ( doTrim ) sTrim.Trim();
00416 }
00417 aL.Add( sTrim );
00418 idxL.Add( lineCount );
00419 }
00420 return thisProcess( aL, linesInputL, iLineError );
00421 }
00422
00423 int gConfig::thisProcess (gList& aL, gList& iLineL, int& lineError)
00424 {
00425
00426 bool isSection;
00427 int line;
00428 unsigned i, k, n=aL.N();
00429 unsigned pos, posEnd, len;
00430 unsigned idxSection=0;
00431 t_uchar uSecChr=sectionSep[1];
00432 t_uchar uSecChr2=sectionSep[2];
00433 bool isChrStartEnd=thisSectionChrStartEnd( uSecChr );
00434 char* str;
00435
00436 lineError = 0;
00437
00438
00439 if ( hasSections ) {
00440 if ( sectionSep.IsEmpty() ) return 21;
00441 for (i=1; i<=n; i++) {
00442 line = iLineL.GetInt( i );
00443 gString sTemp( aL.Str(i) );
00444 len = sTemp.Length();
00445 isSection = false;
00446 pos = sTemp.Find( (char)uSecChr );
00447 if ( sectionStartPos==0 ) {
00448 isSection = pos>0;
00449 }
00450 else {
00451 isSection = pos==sectionStartPos;
00452 }
00453 posEnd = sTemp.FindBack( (char)uSecChr2 );
00454 if ( isSection==false ) continue;
00455 ASSERTION(sectionSep.IsEmpty()==false,"sectionSep non empty");
00456 gString sSection;
00457 if ( isChrStartEnd ) {
00458 if ( posEnd!=len ) {
00459 lineError = line;
00460 return 22;
00461 }
00462 sTemp[posEnd] = 0;
00463 sSection.CopyFromTo( sTemp, pos+1 );
00464 }
00465 else {
00466 if ( pos==len ) sTemp[pos] = 0;
00467 if ( sectionStartPos==1 ) {
00468
00469 sSection.CopyFromTo( sTemp, sectionSep.Length()+1 );
00470 }
00471 else {
00472 sSection = sTemp;
00473 }
00474 }
00475
00476
00477 sSection.Trim();
00478 sectL.Add( sSection );
00479 nIdxSectL.Add( (int)i );
00480 }
00481 nConf = sectL.N();
00482 }
00483 else {
00484 nConf = n;
00485 }
00486
00487 confL = new gList[ nConf+1 ];
00488 conpL = new gList[ nConf+1 ];
00489 if ( nConf==0 ) return 0;
00490
00491
00492 if ( hasSections ) {
00493
00494 k = nIdxSectL.GetInt( 1 );
00495 for (i=1; i<k; i++) noSectL.Add( aL.Str(i) );
00496 for (idxSection=1; idxSection<=nConf; idxSection++) {
00497 unsigned nextK;
00498 k = nIdxSectL.GetInt( idxSection );
00499 nextK = idxSection<nConf ? nIdxSectL.GetInt( idxSection+1 )-1 : n;
00500 for (i=k+1; i<=nextK; i++) {
00501 str = aL.Str(i);
00502 confL[idxSection].Add( str );
00503 thisParseLine( str, conpL[idxSection] );
00504 }
00505 }
00506 }
00507 return 0;
00508 }
00509
00510 int gConfig::thisParseLine (char* str, gList& pL)
00511 {
00512
00513
00514
00515
00516
00517 ;
00518 unsigned len, pos, posAny;
00519
00520 ASSERTION(str!=nil,"str!=nil");
00521 len = lineSepStrs.N();
00522 if ( len>0 ) return -1;
00523 gString s( str );
00524 len = lineSepChrs.Length();
00525 pos = s.FindAnyChr( lineSepChrs, true, posAny );
00526 if ( pos==0 ) {
00527 pL.Add( str );
00528 return 0;
00529 }
00530 gString sLeft, sRight;
00531 if ( pos>1 ) sLeft.CopyFromTo( s, 1, pos-1 );
00532 sLeft.Trim();
00533 sRight.CopyFromTo( s, pos+1 );
00534 sRight.Trim();
00535
00536 gList lineL;
00537 gString sSepThis( lineSepChrs[posAny] );
00538 lineL.Add( sSepThis );
00539 lineL.Add( sLeft );
00540 lineL.Add( sRight );
00541
00542 return thisAddLineToList( lineL, pL );
00543 }
00544
00545 int gConfig::thisAddLineToList (gList& lineL, gList& pL)
00546 {
00547
00548 unsigned i, n = lineL.N();
00549 gList* newObj;
00550 if ( n!=3 ) return -1;
00551 for (i=1; i<=n; i++) {
00552 if ( lineL.GetObjectPtr(i)->Kind()!=e_String )
00553 return -2;
00554 }
00555 newObj = new gList;
00556 for (i=1; i<=n; i++) {
00557 newObj->Add( lineL.Str(i) );
00558 }
00559 pL.AppendObject( newObj );
00560 return 0;
00561 }
00562
00563 bool gConfig::thisSectionChrStartEnd (t_uchar uSecChr)
00564 {
00565 switch ( uSecChr ) {
00566 case '[':
00567 case '(':
00568 case '{':
00569 case '<':
00570 return true;
00571 default:
00572 break;
00573 }
00574 return false;
00575 }
00576
00577