ConfDataReader.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: ConfDataReader.cpp 3140 2012-06-18 15:03:02Z susancummins $"
00002 
00008 //============================================================================
00009 //
00010 //  This file is part of GPSTk, the GPS Toolkit.
00011 //
00012 //  The GPSTk is free software; you can redistribute it and/or modify
00013 //  it under the terms of the GNU Lesser General Public License as published
00014 //  by the Free Software Foundation; either version 2.1 of the License, or
00015 //  any later version.
00016 //
00017 //  The GPSTk is distributed in the hope that it will be useful,
00018 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 //  GNU Lesser General Public License for more details.
00021 //
00022 //  You should have received a copy of the GNU Lesser General Public
00023 //  License along with GPSTk; if not, write to the Free Software Foundation,
00024 //  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
00025 //
00026 //  Dagoberto Salazar - gAGE ( http://www.gage.es ). 2008
00027 //
00028 //============================================================================
00029 
00030 
00031 
00032 
00033 #include "ConfDataReader.hpp"
00034 
00035 using namespace std;
00036 
00037 namespace gpstk
00038 {
00039 
00040       // Method to store conf data in this class' data map
00041    void ConfDataReader::loadData(void)
00042       throw(ConfigurationException)
00043    {
00044 
00045          // By default, section name is "DEFAULT"
00046       std::string sectionName("DEFAULT");
00047 
00048          // Do this until end-of-file reached or something else happens
00049       while(1)
00050       {
00051          try
00052          {
00053 
00054             std::string line;
00055             std::string variable;
00056             std::string value;
00057 
00058             formattedGetLine(line, true);
00059 
00060                // If line is too long, we throw an exception
00061             if (line.size()>255)
00062             {
00063                ConfigurationException e(
00064                                     "Line too long in configuration file '" +
00065                                     filename + "'." );
00066                GPSTK_THROW(e);
00067             }
00068               // Skip the blank line
00069             if(line.size()<1) continue;
00070                 
00071                // Let's find and strip comment lines
00072             if( (StringUtils::firstWord(line)[0] == '#') ||
00073                 (StringUtils::firstWord(line)[0] == ';')  )
00074             {
00075                formattedGetLine(line, true);
00076             }
00077 
00078                // Let's strip comments at the end of lines
00079             std::string::size_type idx(line.find('#'));
00080             if( !(idx == std::string::npos) )
00081             {
00082                line = line.substr(0, idx);
00083             }
00084 
00085             idx = line.find(';');
00086             if( !(idx == std::string::npos) )
00087             {
00088                line = line.substr(0, idx);
00089             }
00090 
00091                // Remove trailing and leading blanks
00092             line = StringUtils::strip(line);
00093 
00094                // Skip blank lines
00095             if (line.size()==0)
00096             {
00097                continue;
00098             }
00099 
00100 
00101                // Let's start to get data out of file
00102 
00103                // First, handle section names
00104 
00105                // Test if this line declares a new section. Check for '['
00106             idx = line.find('[');
00107             if( !(idx == std::string::npos) )
00108             {
00109 
00110                   // Now, check if there is a closing ']'
00111                std::string::size_type idx2(line.find(']'));
00112                if( !(idx2 == std::string::npos) )
00113                {
00114                      // Extract name and remove trailing and leading blanks
00115                   line = StringUtils::strip( line.substr(idx+1, idx2-idx-1) );
00116 
00117                      // Check if section name is appropriate
00118                   if( checkName(line) )
00119                   {
00120 
00121                         // Update 'sectionName': make it uppercase
00122                      sectionName = StringUtils::upperCase(line);
00123 
00124                   }
00125                   else
00126                   {
00127                         // Throw an exception if section name isn't appropriate
00128                      ConfigurationException e(
00129                                           "Section name '" +
00130                                           line + "' in configuration file '" +
00131                                           filename +
00132                                           "' does not comply with rules.");
00133 
00134                      GPSTK_THROW(e);
00135                   }
00136 
00137                      // If this was a section line, continue with next line
00138                   continue;
00139 
00140                }
00141                else
00142                {
00143                      // Throw an exception if section line is not closed
00144                   ConfigurationException e(
00145                                        "Section line '" +
00146                                        line +
00147                                        "' in configuration file '" +
00148                                        filename +
00149                                        "' was improperly closed" );
00150 
00151                   GPSTK_THROW(e);
00152                }
00153 
00154             }
00155 
00156                // Second, handle variables
00157 
00158                // Separate variable name from value. Look for separators
00159             idx = line.find('=');
00160             if( idx == std::string::npos )
00161             {
00162                idx = line.find(':');
00163             }
00164 
00165 
00166                // If we found a separator, keep processing
00167             if( !(idx == std::string::npos) )
00168             {
00169 
00170                   // Read variable and value
00171                variable = StringUtils::strip( line.substr(0, idx) );
00172                value = StringUtils::strip( line.substr(idx+1) );
00173 
00174                   // Now separate comments
00175 
00176                   // Work on 'variable'
00177                std::string varComment;
00178 
00179                idx = variable.find(',');
00180                if( !(idx == std::string::npos) )
00181                {
00182                   varComment = StringUtils::strip(variable.substr(idx+1));
00183                   variable   = StringUtils::strip(variable.substr(0, idx));
00184                }
00185 
00186                   // Check if variable name is appropriate
00187                if( checkName(variable) )
00188                {
00189                      // Make 'variable' uppercase
00190                   variable = StringUtils::upperCase(variable);
00191 
00192                }
00193                else
00194                {
00195                      // Throw an exception if variable name isn't appropriate
00196                   ConfigurationException e(
00197                                        "Variable name '" +
00198                                        variable + "' in configuration file '" +
00199                                        filename +
00200                                        "' does not comply with rules.");
00201 
00202                   GPSTK_THROW(e);
00203                }
00204 
00205                   // Now work on 'value'
00206                std::string valueComment;
00207 
00208                idx = value.find(',');
00209                if( !(idx == std::string::npos) )
00210                {
00211                   valueComment = StringUtils::strip(value.substr(idx+1));
00212                   value        = StringUtils::strip(value.substr(0, idx));
00213                }
00214 
00215                   // Store configuration data
00216                variableData varData;
00217                varData.varComment   = varComment;
00218                varData.value        = value;
00219                varData.valueComment = valueComment;
00220 
00221                confData[sectionName][variable] = varData;
00222 
00223             }
00224 
00225          }  // End of try block
00226          catch (ConfigurationException& e)
00227          {
00228             GPSTK_THROW(e);
00229          }
00230          catch (EndOfFile& e)
00231          {
00232 
00233                // Initialize itCurrentSection
00234             itCurrentSection = confData.begin();
00235 
00236             return;
00237 
00238          }
00239          catch (...)
00240          {
00241 
00242             return;
00243 
00244          }
00245 
00246       } // End of 'while(1)'
00247 
00248    }  // End of method 'ConfDataReader::loadData()'
00249 
00250 
00251 
00252       /* Method to get the value of a given variable as a string
00253        *
00254        * @param variable   Variable name.
00255        * @param section    Section the variable belongs to.
00256        *
00257        */
00258    string ConfDataReader::getValue( string variable,
00259                                     string section,
00260                                     string defaultVal )
00261       throw(ConfigurationException)
00262    {
00263 
00264          // Let's make sure that section and variable names are uppercase
00265       section  = StringUtils::upperCase(section);
00266       variable = StringUtils::upperCase(variable);
00267 
00268 
00269       try
00270       {
00271 
00272             // Auxiliar variable to store current 'issueException' state
00273          bool exceptionState( getIssueException() );
00274 
00275             // If 'fallback2Default' is set, and this is NOT the 'DEFAULT'
00276             // section, we need to temporarily disable 'issueException'.
00277             // This implies that there is no fallback for 'DEFAULT' variables
00278          if( (section != "DEFAULT") && (section != "") )
00279          {
00280             if( getFallback2Default() )
00281             {
00282                setIssueException(false);
00283             }
00284          }
00285 
00286 
00287             // Check if section and variable exist
00288          if( ifExist(variable, section) )
00289          {
00290 
00291                // Reset 'issueException' to its correct value before continue
00292             setIssueException( exceptionState );
00293 
00294             return confData[section][variable].value;
00295 
00296          }
00297          else
00298          {
00299 
00300                // Reset 'issueException' to its correct value before continue
00301             setIssueException( exceptionState );
00302 
00303                // If 'fallback2Default' is set, check also in 'DEFAULT' section
00304             if ( getFallback2Default() )
00305             {
00306 
00307                if( ifExist(variable) )
00308                {
00309 
00310                   return confData["DEFAULT"][variable].value;
00311 
00312                }
00313                else
00314                {
00315 
00316                   return defaultVal;
00317 
00318                }
00319 
00320             }
00321             else
00322             {
00323 
00324                return defaultVal;
00325 
00326             }  // End of 'if ( getFallback2Default() )'
00327 
00328          }  // End of 'if( ifExist(variable, section) )'
00329 
00330       }
00331       catch (ConfigurationException& e)
00332       {
00333 
00334          GPSTK_RETHROW(e);
00335 
00336       }  // End of 'try-catch' block
00337 
00338    }  // End of method 'ConfDataReader::getValue()'
00339 
00340 
00341 
00342       /* Method to get the value of a given variable as a boolean
00343        *
00344        * @param variable   Variable name.
00345        * @param section    Section the variable belongs to.
00346        *
00347        */
00348    bool ConfDataReader::getValueAsBoolean( string variable,
00349                                            string section,
00350                                            bool   defaultVal )
00351       throw(ConfigurationException)
00352    {
00353 
00354          // Let's make sure that section and variable names are uppercase
00355       section  = StringUtils::upperCase(section);
00356       variable = StringUtils::upperCase(variable);
00357 
00358       try
00359       {
00360 
00361             // Declare result variable
00362          string result( getValue( variable, section ) );
00363 
00364 
00365             // Test if result is empty (variable does not exist)
00366          if( result == "" )
00367          {
00368                // Return false if variable is empty. Be aware that an empty
00369                // variable is NOT the same as an unexistent variable
00370             return defaultVal;
00371 
00372          }
00373 
00374 
00375             // 'result' isn't empty. Convert it to uppercase
00376          result = StringUtils::upperCase(result);
00377 
00378             // Test if it is "TRUE" or "FALSE"
00379          if( result == "TRUE" )
00380          {
00381 
00382             return true;
00383 
00384          }
00385          else
00386          {
00387 
00388             if( result == "FALSE" )
00389             {
00390 
00391                return false;
00392 
00393             }
00394             else
00395             {
00396 
00397                   // Throw an exception if value is neither TRUE nor FALSE
00398                ConfigurationException e(
00399                                     "Variable name '" +
00400                                     variable + "' in configuration file '" +
00401                                     filename +
00402                                     "' is neither TRUE nor FALSE.");
00403 
00404                GPSTK_THROW(e);
00405 
00406             }  // End of 'if( result == "FALSE" )'
00407 
00408          }  // End of 'if( result == "TRUE" )'
00409 
00410       }
00411       catch (ConfigurationException& e)
00412       {
00413          GPSTK_RETHROW(e);
00414       }
00415 
00416    }  // End of method 'ConfDataReader::getValueAsBoolean()'
00417 
00418 
00419 
00420       /* Method to fetch (as string) the first value of a given
00421        * variable list.
00422        *
00423        * In this context, a variable list is the same as a variable but
00424        * it is composed of several parts (words), separated by spaces.
00425        *
00426        * @param variableList   Variable list name.
00427        * @param section        Section the variable list belongs to.
00428        *
00429        * \warning This method will MODIFY the original content of
00430        * 'variableList'.
00431        */
00432    string ConfDataReader::fetchListValue( string variableList,
00433                                           string section, 
00434                                           string defaultVal )
00435       throw(ConfigurationException)
00436    {
00437 
00438       try
00439       {
00440 
00441             // Let's make sure that section and variable names are uppercase
00442          section      = StringUtils::upperCase(section);
00443          variableList = StringUtils::upperCase(variableList);
00444 
00445             // Store the original value of 'variableList'
00446          string origValue( getValue(variableList, section) );
00447 
00448             // Get the first word in 'originalValue'
00449          string firstValue( StringUtils::stripFirstWord(origValue) );
00450 
00451             // Modify the originalValue value
00452          confData[section][variableList].value = StringUtils::strip(origValue);
00453 
00454             // Return the first value
00455          string value = StringUtils::strip(firstValue);
00456          return ( (value=="") ? string(defaultVal) : value );
00457 
00458       }
00459       catch (ConfigurationException& e)
00460       {
00461          GPSTK_RETHROW(e);
00462       }
00463 
00464    }  // End of method 'ConfDataReader::fetchListValue()'
00465 
00466 
00467 
00468       /* Method to fetch (as boolean) the first value of a given
00469        * variable list.
00470        *
00471        * In this context, a variable list is the same as a variable but
00472        * it is composed of several parts (words), separated by spaces.
00473        *
00474        * @param variableList   Variable list name.
00475        * @param section        Section the variable list belongs to.
00476        *
00477        * \warning This method will MODIFY the original content of
00478        * 'variableList'.
00479        */
00480    bool ConfDataReader::fetchListValueAsBoolean( string variableList,
00481                                                  string section,
00482                                                  bool   defaultVal )
00483       throw(ConfigurationException)
00484    {
00485 
00486       try
00487       {
00488 
00489             // Let's make sure that section and variable names are uppercase
00490          section      = StringUtils::upperCase(section);
00491          variableList = StringUtils::upperCase(variableList);
00492 
00493             // Get first value in 'variableList' and make it uppercase
00494          string result( fetchListValue(variableList,section) );
00495 
00496          result = StringUtils::upperCase(result);
00497 
00498             // Test if it is "TRUE" or "FALSE"
00499          if( result == "TRUE" )
00500          {
00501 
00502             return true;
00503 
00504          }
00505          else
00506          {
00507 
00508             if( (result == "FALSE") ||
00509                 (result == "") )    // If list is empty returns false
00510             {
00511 
00512                return defaultVal;
00513 
00514             }
00515             else
00516             {
00517 
00518                   // Throw an exception if value is neither TRUE nor FALSE
00519                ConfigurationException e(
00520                                     "Variable list '" +
00521                                     variableList + "' in configuration file '" +
00522                                     filename +
00523                                     "' have a value that is neither TRUE " +
00524                                     "nor FALSE.");
00525 
00526                GPSTK_THROW(e);
00527 
00528             }  // End of 'if( result == "FALSE" )'
00529 
00530          }  // End of 'if( result == "TRUE" )'
00531 
00532       }  // End of 'try' block
00533       catch (ConfigurationException& e)
00534       {
00535          GPSTK_RETHROW(e);
00536       }
00537 
00538    }  // End of method 'ConfDataReader::fetchListValueAsBoolean()'
00539 
00540 
00541 
00542       /* Method to get the description of a given variable
00543        *
00544        * @param variable   Variable name.
00545        * @param section    Section the variable belongs to.
00546        *
00547        */
00548    string ConfDataReader::getVariableDescription( string variable,
00549                                                   string section )
00550       throw(ConfigurationException)
00551    {
00552 
00553          // Let's make sure that section and variable names are uppercase
00554       section  = StringUtils::upperCase(section);
00555       variable = StringUtils::upperCase(variable);
00556 
00557       try
00558       {
00559 
00560             // Auxiliar variable to store current 'issueException' state
00561          bool exceptionState( getIssueException() );
00562 
00563             // If 'fallback2Default' is set, and this is NOT the 'DEFAULT'
00564             // section, we need to temporarily disable 'issueException'.
00565             // This implies that there is no fallback for 'DEFAULT' variables
00566          if( (section != "DEFAULT") && (section != "") )
00567          {
00568             if( getFallback2Default() )
00569             {
00570                setIssueException(false);
00571             }
00572          }
00573 
00574 
00575             // Check if section and variable exist
00576          if( ifExist(variable, section) )
00577          {
00578 
00579                // Reset 'issueException' to its correct value before continue
00580             setIssueException( exceptionState );
00581 
00582             return confData[section][variable].varComment;
00583 
00584          }
00585          else
00586          {
00587 
00588                // Reset 'issueException' to its correct value before continue
00589             setIssueException( exceptionState );
00590 
00591                // If 'fallback2Default' is set, check also in 'DEFAULT' section
00592             if ( getFallback2Default() )
00593             {
00594 
00595                if( ifExist(variable) )
00596                {
00597 
00598                   return confData["DEFAULT"][variable].varComment;
00599 
00600                }
00601                else
00602                {
00603 
00604                   return "";
00605 
00606                }
00607 
00608             }
00609             else
00610             {
00611 
00612                return "";
00613 
00614             }  // End of 'if ( getFallback2Default() )'
00615 
00616          }  // End of 'if( ifExist(variable, section) )'
00617 
00618       }
00619       catch (ConfigurationException& e)
00620       {
00621          GPSTK_RETHROW(e);
00622       }
00623 
00624    }  // End of method 'ConfDataReader::getVariableDescription()'
00625 
00626 
00627 
00628       /* Method to get the description of a given value
00629        *
00630        * @param variable   Variable name.
00631        * @param section    Section the variable belongs to.
00632        *
00633        */
00634    string ConfDataReader::getValueDescription( string variable,
00635                                                string section )
00636       throw(ConfigurationException)
00637    {
00638 
00639          // Let's make sure that section and variable names are uppercase
00640       section  = StringUtils::upperCase(section);
00641       variable = StringUtils::upperCase(variable);
00642 
00643       try
00644       {
00645 
00646             // Auxiliar variable to store current 'issueException' state
00647          bool exceptionState( getIssueException() );
00648 
00649             // If 'fallback2Default' is set, and this is NOT the 'DEFAULT'
00650             // section, we need to temporarily disable 'issueException'.
00651             // This implies that there is no fallback for 'DEFAULT' variables
00652          if( (section != "DEFAULT") && (section != "") )
00653          {
00654             if( getFallback2Default() )
00655             {
00656                setIssueException(false);
00657             }
00658          }
00659 
00660 
00661             // Check if section and variable exist
00662          if( ifExist(variable, section) )
00663          {
00664 
00665                // Reset 'issueException' to its correct value before continue
00666             setIssueException( exceptionState );
00667 
00668             return confData[section][variable].valueComment;
00669 
00670          }
00671          else
00672          {
00673 
00674                // Reset 'issueException' to its correct value before continue
00675             setIssueException( exceptionState );
00676 
00677                // If 'fallback2Default' is set, check also in 'DEFAULT' section
00678             if ( getFallback2Default() )
00679             {
00680 
00681                if( ifExist(variable) )
00682                {
00683 
00684                   return confData["DEFAULT"][variable].valueComment;
00685 
00686                }
00687                else
00688                {
00689 
00690                   return "";
00691 
00692                }
00693 
00694             }
00695             else
00696             {
00697 
00698                return "";
00699 
00700             }  // End of 'if ( getFallback2Default() )'
00701 
00702          }  // End of 'if( ifExist(variable, section) )'
00703 
00704       }
00705       catch (ConfigurationException& e)
00706       {
00707          GPSTK_RETHROW(e);
00708       }
00709 
00710    }  // End of method 'ConfDataReader::getValueDescription()'
00711 
00712 
00713 
00714       /* Method to check if a given section/variable pair exists.
00715        *
00716        * @param variable   Variable name.
00717        * @param section    Section the variable belongs to.
00718        *
00719        */
00720    bool ConfDataReader::ifExist( string variable,
00721                                  string section )
00722       throw(ConfigurationException)
00723    {
00724 
00725          // Let's make sure that section and variable names are uppercase
00726       section  = StringUtils::upperCase(section);
00727       variable = StringUtils::upperCase(variable);
00728 
00729          // Check if section and variable exist
00730       confMap::const_iterator it;
00731       it = confData.find(section);
00732       if( it != confData.end() )
00733       {
00734          variableMap::const_iterator it2;
00735          it2 = (*it).second.find(variable);
00736          if( it2 != (*it).second.end() )
00737          {
00738 
00739             // Return the corresponding value, if it exists
00740             return true;
00741 
00742          }
00743          else
00744          {
00745 
00746             if(issueException)
00747             {
00748 
00749                   // Throw an exception if variable name doesn't exist
00750                ConfigurationException e(
00751                                     "Variable '" + variable
00752                                     + "' in section '" + section
00753                                     + "' of configuration file '" + filename
00754                                     + "' does not exist.");
00755 
00756                GPSTK_THROW(e);
00757 
00758             }
00759             else
00760             {
00761 
00762                return false;
00763 
00764             }  // End of 'if(issueException)'
00765 
00766          }  // End of 'if( it2 != (*it).second.end() )'
00767 
00768       }
00769       else
00770       {
00771 
00772          if(issueException)
00773          {
00774 
00775                // Check if problem is with section "DEFAULT"
00776             if ( section == "DEFAULT" )
00777             {
00778 
00779                   // Throw an exception if section name doesn't exist
00780                ConfigurationException e(
00781                                     "Section 'DEFAULT' in configuration file '"
00782                                     + filename
00783                                     + "' does not exist. Does file '"
00784                                     + filename + "' exist?. Do you have "
00785                                     + "permission to read it?." );
00786 
00787                GPSTK_THROW(e);
00788 
00789             }
00790             else
00791             {
00792 
00793                   // Throw an exception if section name doesn't exist
00794                ConfigurationException e(
00795                                     "Section '" + section
00796                                     + "' in configuration file '" + filename
00797                                     + "' does not exist.");
00798 
00799                GPSTK_THROW(e);
00800 
00801             }  // End of 'if ( section == "DEFAULT" )'
00802 
00803          }
00804          else
00805          {
00806 
00807             return false;
00808 
00809          }  // End of 'if(issueException)'
00810 
00811       }  // End of 'if( it != confData.end() )'
00812 
00813    }  // End of method 'ConfDataReader::ifExist()'
00814 
00815 
00816 
00817       // Method to open AND load configuration data file.
00818    void ConfDataReader::open(const char* fn)
00819    {
00820 
00821          // We always open configuration file as "read-only"
00822       FFTextStream::open(fn, std::ios::in);
00823 
00824       loadData();
00825 
00826       return;
00827 
00828    }  // End of method 'ConfDataReader::open()'
00829 
00830 
00831 
00832       // Method to get the name of each section in order.
00833    string ConfDataReader::getEachSection(void)
00834    {
00835 
00836       if ( itCurrentSection != confData.end() )
00837       {
00838 
00839             // Store result
00840          string result( (*itCurrentSection).first );
00841 
00842             // Increment iterator for next time
00843          ++itCurrentSection;
00844 
00845             // Return result
00846          return result;
00847 
00848       }
00849       else
00850       {
00851             // If we are at the end, return an empty string
00852          return "";
00853       }
00854 
00855    }  // End of method 'ConfDataReader::getEachSection()'
00856 
00857 
00858 
00859       /* Method to check if the given name is properly formed.
00860        *
00861        * @param name    Name to the checked.
00862        */
00863    bool ConfDataReader::checkName(string name)
00864    {
00865 
00866       try
00867       {
00868 
00869             // Test if first character is alphabetic
00870          if( StringUtils::isAlphaString(name.substr(0, 1)) )
00871          {
00872 
00873                // Translate all allowed characters to 'a'
00874             name = StringUtils::translate( name,"0123456789-_", "a", 'a');
00875 
00876                // If the result is an alphabetic string, the name is valid
00877             return ( StringUtils::isAlphaString(name) );
00878 
00879          }
00880          else
00881          {
00882                // If first character is not alphabetic, we return false
00883             return false;
00884          }
00885 
00886       }
00887       catch (...)
00888       {
00889             // In case of any problem we return false
00890          return false;
00891       }
00892 
00893    }  // End of method 'ConfDataReader::checkName()'
00894 
00895 
00896 
00897 }  // End of namespace gpstk
00898 
00899 

Generated on Fri May 24 03:31:04 2013 for GPS ToolKit Software Library by  doxygen 1.3.9.1