gconfig.cpp

Go to the documentation of this file.
00001 // gconfig.cpp -- Version 0.2
00002 
00003 #include <string.h>
00004 #include "gconfig.h"
00005 
00006 // Static members
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  // doShowProgress is here updated as well...
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  // Check if there was a buffer overun
00123  if ( isFetchBufferOk ) return 0;
00124  // Empty list meanwhile used: zL
00125  zL.Delete();
00126  if ( Rewind()==false ) return 1;
00127  thisReadFileThrough( zL, nBytes );
00128  error = nBytes<Size() ? 4 : 0;
00129  //if ( error!=0 ) fprintf(stderr,"DBG::: nBytes=%ld, size()=%ld\n",(long)nBytes,(long)Size())
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;  //for quickness
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      // Then it should be a string
00298      if ( inObjL->Kind()!=e_String ) return false;
00299      sLeft = inObjL->Str();
00300      // Returning ok, though 'isAssign' is false: it's not an assignment (e.g. Param=Value);
00301      // the exception is when there is no string (an empty line)
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      // Get rid of comments...
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              // Process rest of line from comment
00402              // onwards, e.g.:
00403              //      param=yes  ;comment
00404              // Process
00405              //      param=yes
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  // Returns 0 on success, on >20 for parse errors
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  // If has sections, count them first (nSections)
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                  // e.g. ":abc" => "abc"
00469                  sSection.CopyFromTo( sTemp, sectionSep.Length()+1 );
00470              }
00471              else {
00472                  sSection = sTemp;
00473              }
00474          }
00475 
00476          // Add section name
00477          sSection.Trim();
00478          sectL.Add( sSection );
00479          nIdxSectL.Add( (int)i );
00480      }//end FOR (check sections)
00481      nConf = sectL.N();
00482  }//end IF (has sections)
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; // nothing to process
00490 
00491  // Process sections
00492  if ( hasSections ) {
00493      // Process 'header lines' before sections, if any
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  // Returns the error-code.
00513  // pL contains: a list with
00514  //              -> the separating character (lineSepChrs)
00515  //              -> left arg
00516  //              -> right arg
00517  ;
00518  unsigned len, pos, posAny;
00519 
00520  ASSERTION(str!=nil,"str!=nil");
00521  len = lineSepStrs.N();
00522  if ( len>0 ) return -1; //TODO: separators as strings
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  // Add one element 'lineL' to list 'pL'
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 

Generated on Sat Aug 18 02:40:51 2007 for xpfweb_v2x lib by  doxygen 1.4.2