IniFile.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *   http://www.apache.org/licenses/LICENSE-2.0
00009 
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016  
00017 
00018 #include <cob_utilities/IniFile.h>
00019 
00020 #include <math.h>
00021 #include <string.h>
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 
00025 using namespace std;
00026 
00027 //-------------------------------------------------------------------
00028 IniFile::IniFile(): m_vectorSize(500), m_CurCharInd(0)
00029 {
00030         m_bFileOK=false;
00031         m_CurLine.resize(m_vectorSize);
00032 }
00033 //--------------------------------------------------------------------------------
00034 
00035 IniFile::IniFile(std::string fileName): m_vectorSize(500), m_CurCharInd(0)
00036 {
00037         m_bFileOK=false;
00038         m_CurLine.resize(m_vectorSize);
00039         if(fileName != "")
00040                 SetFileName(fileName);
00041 }
00042 //--------------------------------------------------------------------------------
00043 IniFile::~IniFile()
00044 {
00045 }
00046 //--------------------------------------------------------------------------------
00047 int IniFile::SetFileName(std::string fileName, std::string strIniFileUsedBy, bool bCreate)
00048 {
00049         m_fileName = fileName;
00050         m_strIniFileUsedBy = strIniFileUsedBy;
00051 
00052         if ((f = fopen(m_fileName.c_str(),"r")) == NULL)
00053         {
00054                 if (bCreate == true)
00055                 {
00056                         f = fopen(m_fileName.c_str(),"w");      // create new file
00057                         std::cout << "Creating new INI-File " << m_fileName.c_str() << std::endl;
00058                         fclose(f);
00059                 }
00060                 else
00061                 {
00062                         std::cout << "INI-File not found " << m_fileName.c_str() << std::endl;
00063                         return -1;
00064                 }
00065         }
00066         else fclose(f);
00067         m_bFileOK = true;
00068         return 0;
00069 }
00070 //--------------------------------------------------------------------------------
00071 int IniFile::WriteKeyString(const char* pSect, const char* pKey, const std::string* pStrToWrite, bool bWarnIfNotfound)
00072 {
00073         std::string StrWithDelimeters = '"' + *pStrToWrite + '"';
00074         return WriteKeyValue(pSect, pKey, StrWithDelimeters.c_str(), bWarnIfNotfound);
00075 }
00076 //--------------------------------------------------------------------------------
00077 int IniFile::WriteKeyValue(const char* szSect,const char* szKey,const char* szValue, bool bWarnIfNotfound)
00078 {
00079         if (!m_bFileOK) return -1;
00080 
00081         FILE* ftemp;
00082         int   lS,lK,i,bEoff;
00083         int   bFoundSect,bFoundKey;
00084         char  c;
00085         long fpos;
00086 
00087 
00088 /*------------------------verifications*/
00089 
00090         bFoundSect = 1 /* true*/;
00091         bFoundKey = 0 /* */;
00092         bEoff = 0;
00093         lS = strlen(szSect);
00094         lK = strlen(szKey);
00095         if ((lS * lK) == 0) return -1;
00096 
00097 /*--------------------- file opening */
00098 
00099         f = fopen(m_fileName.c_str(),"r");
00100         if (f == NULL)
00101         {
00102                 std::cout << "INI-File not found " << m_fileName.c_str() << std::endl;
00103                 return -1;
00104         }
00105         if ((ftemp = tmpfile()) == NULL)
00106         {
00107                 std::cout << "tmpfile() did not work!" << std::endl;
00108                 return -1;
00109         }
00110 
00111 
00112 /* ---------------------- search section and key */
00113         if (FindSection(szSect, bWarnIfNotfound) != 0)
00114         {
00115                 bFoundSect = 0;
00116         }
00117         fpos = ftell(f);
00118         if (bFoundSect)
00119         {
00120                 if (!FindKey(szKey, false))     bFoundKey = 1;
00121                 fpos = ftell(f);
00122         }
00123         if (feof(f)) bEoff = 1;
00124 
00125 /* --------------------- updating the file */
00126         fseek(f,0,SEEK_SET);
00127         for (i=0;i<fpos;i++)
00128         {
00129                 fscanf(f,"%c",&c);
00130                 fprintf(ftemp,"%c",c);
00131                 // MMB/23.02.2006: The counter i must not be incremented here on Linux machines!
00132 #ifdef WIN32
00133                 if (c=='\n')
00134                         i++;
00135 #endif
00136         };
00137 
00138         if (!bFoundSect) {
00139                 fprintf(ftemp,"\n\n[%s]\n",szSect);
00140         }
00141         if (bFoundSect && (!bFoundKey) && (bEoff))
00142         {
00143                 fprintf(ftemp,"\n");
00144         }
00145 
00146 
00147         if (!bFoundKey)
00148         {
00149                 fprintf(ftemp,"%s=",szKey);
00150         }
00151 
00152         fprintf(ftemp,"%s",szValue);
00153 
00154         if (bFoundKey) FindNextLine(m_CurLine, m_CurCharInd);
00155         if (!(bEoff || feof(f)))
00156         {       fprintf(ftemp,"\n");
00157                 while (!feof(f))
00158                 {
00159                         fscanf(f,"%c",&c);
00160                         if (!feof(f))
00161                         {
00162                                 fprintf(ftemp,"%c",c);
00163                         }
00164                 }
00165         }
00166         fpos = ftell(ftemp);
00167         fclose(f);
00168 
00169         if ((f = fopen(m_fileName.c_str(),"w")) == NULL)
00170         {
00171                 if ((f = fopen(m_fileName.c_str(),"r")) != NULL)
00172                 {
00173                         fclose(f);
00174                         std::cout << "INI-File is write protected " << m_fileName.c_str() << std::endl;
00175                         return -1;
00176                 }
00177 
00178                 std::cout << "INI-File not found " << m_fileName.c_str() << std::endl;
00179                 return -1;
00180         }
00181         fseek(ftemp,0,SEEK_SET);
00182         for (i=0;i<fpos;i++)
00183         {
00184                 fscanf(ftemp,"%c",&c);
00185                 fprintf(f,"%c",c);
00186         };
00187         fclose(f);
00188         fclose(ftemp);
00189         return 0;
00190 
00191 }
00192 //--------------------------------------------------------------------------------
00193 int IniFile::WriteKeyBool(const char* pSect, const char* pKey, bool bValue, bool bWarnIfNotfound)
00194 {       if(bValue)
00195                 return WriteKeyValue(pSect, pKey, "true", bWarnIfNotfound);
00196         else
00197                 return WriteKeyValue(pSect, pKey, "false", bWarnIfNotfound);
00198 }
00199 //--------------------------------------------------------------------------------
00200 int IniFile::WriteKeyInt(const char* szSect,const char* szKey,int nValue, bool bWarnIfNotfound)
00201 {
00202         char buff[20];
00203         snprintf(buff, 10, "%d", nValue);
00204         return WriteKeyValue(szSect,szKey,buff, bWarnIfNotfound);
00205 }
00206 //--------------------------------------------------------------------------------
00207 int IniFile::WriteKeyDouble(const char* szSect,const char* szKey,double Value,
00208                                                    int Length/*=12*/,int decimals/*=5*/, bool bWarnIfNotfound)
00209 {
00210         char buff[100];
00211         sprintf(buff, "%g", Value);
00212         return WriteKeyValue(szSect,szKey, buff, bWarnIfNotfound);
00213 }
00214 //--------------------------------------------------------------------------------
00215 int IniFile::GetKeyBool(const char* pSect, const char* pKey, bool* pValue,
00216                                                         bool bWarnIfNotfound)
00217 {
00218         std::string strRead;
00219         char pBuf[20];
00220         *pValue = false;
00221         if (GetKeyValue(pSect, pKey, pBuf, 20, bWarnIfNotfound) == -1)
00222                 return -1;
00223 
00224         char* pChar = pBuf;
00225         while( *pChar == ' ' )  pChar++;                // skip spaces
00226 
00227         if( strncmp(pChar, "true", 4) == 0 )
00228         {
00229                 *pValue = true;
00230                 return 0;
00231         }
00232         if( strncmp(pChar, "false", 5) == 0 )
00233         {
00234                 *pValue = false;
00235                 return 0;
00236         }
00237 
00238         return -1;
00239 }
00240 //--------------------------------------------------------------------------------
00241 int IniFile::GetKeyInt(const char* szSect,const char* szKey,int* pValue,
00242                                                         bool bWarnIfNotfound)
00243 {
00244         char buf[9];
00245         if (GetKeyValue(szSect,szKey,buf,9, bWarnIfNotfound)!=-1)
00246         {
00247                 //first get rid of spaces
00248                 if (buf[0] == ' ')
00249                 {
00250                         for (int i=0; i<=6; i++)
00251                                 buf[i] = buf[i+1];
00252                         buf[7]='\0';
00253                 }
00254 
00255                 if ((buf[0]=='0') && (buf[1] == 'x'))
00256                 {
00257                         int iNumLength = 0;
00258                         //check how long the hex-number is
00259                         for (int z=0; z<=7; z++)
00260                         {
00261                                 //if its not a number..
00262                                 if ((buf[z+2]<0x30) || (buf[z+2]>0x3A))
00263                                 {
00264                                         iNumLength = z-1;
00265                                         break;
00266                                 }
00267                         }
00268                         *pValue = 0;
00269                         for (int i=0; i<=(iNumLength); i++)
00270                         {
00271                                 //convert hex-string from character into int
00272                                 *pValue += (buf[i+2]-0x30) * (int)pow((double)16, (iNumLength-i));
00273                         }
00274                 }
00275                 else
00276                 {
00277                         *pValue = atoi(buf);
00278                 }
00279                 return 0;
00280 
00281         }
00282         else return -1;
00283 }
00284 //--------------------------------------------------------------------------------
00285 int IniFile::GetKeyLong(const char* szSect,const char* szKey,long* pValue,
00286                                                         bool bWarnIfNotfound)
00287 {
00288         char buf[9];
00289         if (GetKeyValue(szSect,szKey,buf,9, bWarnIfNotfound)!=-1)
00290         {
00291                 *pValue = atol(buf);
00292                 return 0;
00293         }
00294         else return -1;
00295 }
00296 //--------------------------------------------------------------------------------
00297 int IniFile::GetKeyDouble(const char* szSect,const char* szKey,double* pValue,
00298                                                         bool bWarnIfNotfound)
00299 {
00300         char buf[50];
00301         if (GetKeyValue(szSect, szKey, buf, 50, bWarnIfNotfound) == -1)
00302         {
00303                 if( bWarnIfNotfound )
00304                         std::cout << "Setting parameter " << szKey <<" = " << *pValue << " of section '" << szSect <<
00305                                                                                         "' in File '" << m_fileName.c_str() << std::endl;
00306                 return -1;
00307         }
00308 
00309         *pValue = atof(buf);
00310         return 0;
00311 }
00312 //-----------------------------------------------
00313 int IniFile::GetKeyDouble(const char* pSect,const char* pKey,double* pValue,
00314                                                   double dDefault, bool bWarnIfNotfound)
00315 {
00316         (*pValue) = dDefault;
00317         return GetKeyDouble(pSect, pKey, pValue, bWarnIfNotfound);
00318 }
00319 //--------------------------------------------------------------------------------
00320 int IniFile::GetKeyValue(const char* szSect,const char* szKey,char* szBuf,
00321                                                 int lenBuf,     bool bWarnIfNotfound)
00322 {
00323         if (!m_bFileOK) return -1;
00324 
00325         int   lS,lK;
00326 
00327         lS = strlen(szSect);
00328         lK = strlen(szKey);
00329         if ((lS * lK) == 0) return -1;
00330         if ((f = fopen(m_fileName.c_str(),"r")) == NULL)
00331         {
00332                 std::cout << "INI-File not found " << m_fileName.c_str() << std::endl;
00333                 return -1;
00334         }
00335         if ( FindSection(szSect, bWarnIfNotfound) )
00336         {       fclose(f);
00337                 return -1;
00338         }
00339         if ( FindKey(szKey, bWarnIfNotfound) )
00340         {       fclose(f);
00341                 return -1;
00342         }
00343 
00344         if (feof(f))
00345         {
00346                 fclose(f);
00347                 return -1;
00348         }
00349 
00350         //----------- read szBuf bytes from file into szKey
00351         int BytesRead = fread( szBuf, 1, lenBuf, f );
00352 
00353         // terminate string
00354         int StrLen;
00355         if(BytesRead < lenBuf)
00356         {
00357                 if( BytesRead == 0 && (!feof(f)) )
00358                 {
00359                         std::cout << "file read" << std::endl;
00360                 }
00361                 StrLen = BytesRead;
00362         }
00363         else
00364         {
00365                 StrLen = lenBuf-1;
00366         }
00367         szBuf[StrLen] = '\0';
00368 
00369         fclose(f);
00370         return StrLen;
00371 }
00372 //--------------------------------------------------------------------------------
00373 int IniFile::GetKeyString(const char* szSect,const char* szKey, std::string* pStrToRead,
00374                                                         bool bWarnIfNotfound)
00375 {
00376         if (!m_bFileOK) return -1;
00377 
00378         int   lS,lK;
00379 
00380         lS = strlen(szSect);
00381         lK = strlen(szKey);
00382         if ((lS * lK) == 0) return -1;
00383         if ((f = fopen(m_fileName.c_str(),"r")) == NULL)
00384         {
00385                 std::cout << "INI-File not found " << m_fileName.c_str() << std::endl;
00386                 return -1;
00387         }
00388         if ( FindSection(szSect, bWarnIfNotfound) )
00389         {       fclose(f);
00390                 return -1;
00391         }
00392         if ( FindKey(szKey, bWarnIfNotfound) )
00393         {       fclose(f);
00394                 return -1;
00395         }
00396 
00397         if (feof(f))
00398         {
00399                 fclose(f);
00400                 return -1;
00401         }
00402 
00403         //----------- read szBuf bytes from file into szKey
00404         int res = SkipLineUntil(f, '"'); // find begin of string
00405         if(res == -1)
00406         {       if(bWarnIfNotfound)
00407                 {
00408                         std::cout << "GetKeyString section " << szSect << " key " << szKey << " first \" not found" << std::endl;
00409                 }
00410                 fclose(f);
00411                 return -1;
00412         }
00413 
00414         std::string strRead;
00415         res = ReadLineUntil(f, '"', strRead); // read string
00416         if(res == -1)
00417         {
00418                 if(bWarnIfNotfound)
00419                 {
00420                         std::cout << "GetKeyString section " << szSect << " key " << szKey << " string not found" << std::endl;
00421                 }
00422                 fclose(f);
00423                 return -1;
00424         }
00425 
00426         // success
00427         *pStrToRead = strRead;
00428         fclose(f);
00429         return 0;
00430 }
00431 //--------------------------------------------------------------------------------
00432 int IniFile::SkipLineUntil(FILE* pFile, const char EndChar)
00433 {
00434         int CharsRead = 0;
00435         while (1)
00436         {
00437                 int Char = fgetc(pFile);
00438 
00439                 if (Char == EndChar)                    // end found?
00440                         return CharsRead;                       // read finished
00441 
00442                 if (Char == EOF || Char == '\n')
00443                         return -1;                              // end not found
00444 
00445                 CharsRead++;
00446         }
00447 }
00448 //--------------------------------------------------------------------------------
00449 int IniFile::ReadLineUntil(FILE* pFile, const char EndChar, std::string& ReadIntoStr)
00450 {
00451         int CharsRead = 0;
00452         while (1)
00453         {
00454                 int Char = fgetc(pFile);
00455 
00456                 if (Char == EndChar)                    // end found?
00457                         return CharsRead;                       // read finished
00458 
00459                 if (Char == EOF || Char == '\n')
00460                         return -1;                              // end not found
00461 
00462                 ReadIntoStr.append(1, char(Char));
00463 
00464                 CharsRead++;
00465         }
00466 }
00467 //--------------------------------------------------------------------------------
00468 int IniFile::FindNextLine(std::vector<char>& NewLine, int& CharInd)
00469 {
00470         if (!feof(f))
00471         {
00472                 fgets(&NewLine[0], NewLine.size(), f); // store next line in NewLine
00473                 CharInd=0;        // makes CharInd reference the first char of the line
00474                 return 0;
00475         }
00476         return -1;
00477 }
00478 //--------------------------------------------------------------------------------
00479 int IniFile::FindNextSection(std::string* pSect, std::string prevSect, bool bWarnIfNotfound)
00480 {
00481         std::vector<char> line;
00482         //int charInd = 0;
00483         //int res = -1;
00484 
00485         if (!m_bFileOK) return -1;
00486 
00487         // Make sure that there is no old data.
00488         pSect->erase();
00489 
00490 /*--------------------- file opening */
00491         f = fopen(m_fileName.c_str(),"r");
00492         if (f == NULL)
00493         {
00494                 std::cout << "INI-File not found " << m_fileName.c_str() << std::endl;
00495                 return -1;
00496         }
00497         if (feof(f)) return -1;
00498 
00499 /*--------------------- search the section */
00500         if( prevSect != "" ) {
00501                 FindSection( prevSect.c_str(), bWarnIfNotfound );
00502         } else {
00503                 fseek(f,0,SEEK_SET);
00504         }
00505 
00506         FindNextLine(m_CurLine, m_CurCharInd); //read first line of file
00507         do
00508         {
00509                 if (m_CurLine[0] == '[')
00510                 {
00511                         while( m_CurCharInd < (int)m_CurLine.size() ) {
00512                                 m_CurCharInd++;
00513                                 if (m_CurLine[m_CurCharInd] == ']') // if found section name equals searched one
00514                                 {
00515                                         for( int i=1; i<m_CurCharInd; ++i )
00516                                                 pSect->append(1, char(m_CurLine[i]));
00517                                         return 0;
00518                                 }
00519                         }
00520                 }
00521                 else
00522                 {
00523                         FindNextLine(m_CurLine, m_CurCharInd);
00524                 }
00525         }while (!feof(f));
00526 
00527 /*--------------------- file closing */
00528         fclose(f);
00529 
00530         return 0;
00531 }
00532 //--------------------------------------------------------------------------------
00533 int IniFile::FindSection(const char* sect,
00534                                                         bool bWarnIfNotfound)
00535 {
00536         int   lS;
00537         lS = strlen(sect);
00538         if (feof(f)) return -1;
00539 
00540         FindNextLine(m_CurLine, m_CurCharInd); //read first line of file
00541         do
00542         {
00543                 if (m_CurLine[0] == '[')
00544                 {
00545                         m_CurCharInd++;
00546                         if ((strncmp(&m_CurLine[m_CurCharInd], sect, lS) == 0) && (m_CurLine[m_CurCharInd+lS] == ']')) // if found section name equals searched one
00547                 {
00548                                 return 0;
00549                         }
00550                         else
00551                         {
00552                                 FindNextLine(m_CurLine, m_CurCharInd);
00553                         }
00554                 }
00555                 else if (m_CurLine[m_CurCharInd] == ' ') // if a blank is found
00556                 {
00557                         m_CurCharInd++;
00558                 }
00559                 else
00560                 {
00561                         FindNextLine(m_CurLine, m_CurCharInd);
00562                 }
00563         }while (!feof(f));
00564 
00565         // not found
00566         if(bWarnIfNotfound)
00567         {
00568                 std::cout << "Section [" << sect << "] in IniFile " << m_fileName.c_str() << " used by "
00569                         << m_strIniFileUsedBy << " not found" << std::endl;
00570         }
00571 
00572         return -1;
00573 }
00574 //--------------------------------------------------------------------------------
00575 int IniFile::FindKey(const char* skey,
00576                                                         bool bWarnIfNotfound)
00577 {
00578         int   lS;
00579         long  fpos = 0l;
00580         lS = strlen(skey);
00581         if (feof(f)) return -1;
00582 
00583         do
00584         {
00585                 fpos=ftell(f);// pointer to the begin of the last read line
00586                 FindNextLine(m_CurLine, m_CurCharInd);
00587 
00588                 while ( m_CurLine[m_CurCharInd] == ' ' ) // skip blanks
00589                         {
00590                                 m_CurCharInd++;
00591                                 fpos++;
00592                         }
00593 
00594                 if (m_CurLine[m_CurCharInd] == '[') // next section?
00595                         break; // not found
00596 
00597                 if (strncmp(&m_CurLine[m_CurCharInd], skey, lS) == 0) //Found
00598                 {
00599                         m_CurCharInd+=lS;
00600                         fpos+=lS; // set file pointer to end of found key
00601             while ( m_CurLine[m_CurCharInd] == ' ' ) // skip blanks
00602                         {
00603                                 m_CurCharInd++;
00604                                 fpos++;
00605                         }
00606                         if ( m_CurLine[m_CurCharInd] == '=' )
00607                         {
00608                                 m_CurCharInd++; // set index to first char after the =
00609                                 fpos++;
00610                                 fseek(f,fpos,SEEK_SET);// set file pointer to first char after the =
00611                                 return 0;
00612                         }
00613 
00614                 }
00615 
00616         }while (!feof(f));
00617 
00618         if(bWarnIfNotfound)
00619         {
00620                 std::cout << "Key " << skey << " in IniFile '" << m_fileName.c_str() << "' used by "
00621                         << m_strIniFileUsedBy << " not found" << std::endl;
00622         }
00623         return -1;
00624 }
00625 //-----------------------------------------------
00626 int IniFile::GetKey(const char* pSect,const char* pKey, std::string* pStrToRead, bool bWarnIfNotfound)
00627 {
00628         return GetKeyString(pSect,pKey,pStrToRead,bWarnIfNotfound);
00629 }
00630 //-----------------------------------------------
00631 int IniFile::GetKey(const char* pSect,const char* pKey,int* pValue, bool bWarnIfNotfound)
00632 {
00633         return GetKeyInt(pSect,pKey,pValue,bWarnIfNotfound);
00634 }
00635 //-----------------------------------------------
00636 
00637 int IniFile::GetKey(const char* pSect, const char* pKey, bool* pValue, bool bWarnIfNotfound)
00638 {
00639         return GetKeyBool(pSect,pKey,pValue,bWarnIfNotfound);
00640 }
00641 //-----------------------------------------------
00642 int IniFile::GetKey(const char* pSect,const char* pKey,double* pValue, bool bWarnIfNotfound)
00643 {
00644         return GetKeyDouble(pSect,pKey,pValue,bWarnIfNotfound);
00645 }
00646 


cob_utilities
Author(s): Christian Connette
autogenerated on Sat Jun 8 2019 21:02:25