Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

IFile.cxx

Go to the documentation of this file.
00001 // $Header: /nfs/slac/g/glast/ground/cvs/xml/src/IFile.cxx,v 1.6 2001/03/13 22:02:36 tlindner Exp $
00002 /*
00003  * User: Suson       Date: 6/29/98
00004  * Removed Rational Rose comments and restructured
00005  *   to use vectors
00006  */
00007 
00008 
00009 #include "xml/IFile.h"
00010 #include "xml/XmlParser.h"
00011 #include "xml/Dom.h"
00012 #include "facilities/error.h"
00013 #include "dom/DOM_Document.hpp"
00014 
00015 // #include <strstream>
00016 #include <vector>
00017 
00018 
00019 extern "C" {
00020   FILE *popen(const char *command, const char *type);
00021 }
00022 
00023 
00024 // implementation
00025 #include <stdio.h>
00026 #include <ctype.h>
00027 #include <string.h>
00028 
00029 
00030 // globals
00031 
00032 namespace xml {
00033 
00034 #define LEADING  1
00035 #define ALL      2
00036 #define TRAILING 4
00037 
00038 
00039   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00040   void IFile::printOn (std::ostream& out) {
00041     for (iterator section_map=begin(); section_map!=end(); ++section_map) {
00042       IFile_Section& section = *(*section_map).second;
00043       out << "\n[" <<  (*section_map).first << "]\n";
00044       
00045       for( IFile_Section::iterator item_map = section.begin();
00046            item_map != section.end(); ++item_map){
00047         IFile_Item& item = *(*item_map).second;
00048         out << (*item_map).first << " = "  << (item.mystring()) << "\n";
00049       }
00050     }
00051   }
00052   
00053   void IFile::print(){printOn(std::cout); std::cout.flush();}
00054 
00055   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00056   int IFile::stricmp (const char *str1, const char *str2)
00057     {
00058       while ( *str1  &&  *str2  &&  toupper(*str1)==toupper(*str2) )
00059       {
00060         str1++;
00061         str2++;
00062       }
00063       
00064       return (toupper(*str1) - toupper(*str2));
00065     }
00066   
00067   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00068   void IFile::stripBlanks (char *str1, const char *str2, int flags)
00069     {
00070       if (flags & ALL)
00071       {
00072         while ( *str2 )
00073         {
00074           if (*str2==' '  ||  *str2=='\t')
00075             str2++;
00076           else
00077             *str1++ = *str2++;
00078         }
00079         *str1=0;
00080       }
00081       else
00082       {
00083         if (flags & LEADING)
00084           while ( *str2  &&  (*str2==' '  ||  *str2=='\t'))
00085             str2++;
00086         
00087         strcpy (str1, str2);
00088         
00089         if (flags & TRAILING)
00090         {
00091           str1 += strlen (str1);
00092           
00093           do str1--; while (*str1==' '  ||  *str1=='\t');
00094           *++str1 = 0;
00095         }
00096       }
00097     }
00098   
00099   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00100   /*
00101     void IFile::stripBlanks2 (char *str1, const char *str2)
00102     {
00103     int flSkip=1;
00104     
00105     while ( *str2 )
00106     {
00107     if (flSkip)
00108     {
00109     if (*str2=='=')
00110     flSkip = 0;
00111     
00112     if (*str2==' '  ||  *str2=='\t')
00113     str2++;
00114     else
00115     *str1++ = *str2++;
00116     }
00117     else
00118     *str1++ = *str2++;
00119     }
00120     *str1=0;
00121     }
00122   */
00123   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00124   void IFile::extractEnvVar(std::string *fileStr) {
00125       //now pull out and substitute for environment vaiables
00126       // This routine, will modify the input string.
00127       int envStart = fileStr->find_first_of("$(");
00128       int envEnd = fileStr->find_first_of(")");
00129             
00130       // add 2 characters to get rid of $(
00131      int afterBracket = envStart + 2;
00132             
00133       if(!((envStart==-1)||(envEnd==-1)))
00134       {
00135           std::string envVariable = fileStr->substr(afterBracket,(envEnd-afterBracket));
00136           const char * path = ::getenv(envVariable.c_str());
00137           if(path) {
00138               fileStr->replace(envStart,(envEnd+1), path);
00139           }
00140       }
00141   }
00142 
00143   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00144   IFile::~IFile ()
00145     {
00146       iterator it = begin();
00147       while (it != end())
00148         delete (*it++).second;
00149       
00150     }
00151   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00152   IFile_Section::~IFile_Section()
00153     {
00154       iterator it = begin();
00155       while (it != end())
00156         delete (*it++).second;
00157     }
00158   
00159   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00160   // IFile::IFile( std::istream & infile) : status(2)       ##Obsolete##
00161   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00162   IFile::IFile (const DOM_Document& instrument)  
00163     {
00164       // check that argument is non-null
00165       if (instrument == DOM_Document()) {
00166         FATAL_MACRO("Attempt to construct IFile from null DOM_Document");
00167         return;
00168       }
00169       // If so, call service to do the actual work
00170       domToIni(instrument);
00171     }
00172   
00173   IFile::IFile (const DOM_Element& instrument)  
00174     {
00175       // check that argument is non-null
00176       if (instrument == DOM_Element()) {
00177         FATAL_MACRO("Attempt to construct IFile from null DOM_Element");
00178         return;
00179       }
00180       // If so, call service to do the actual work
00181       domToIni(instrument);
00182     }
00183   
00184 
00185   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00186   IFile::IFile (const char *filename) 
00187     {          
00188       XmlParser parser;
00189       
00190       std::string filenameStr = filename;
00191       extractEnvVar(&filenameStr);
00192 
00193       // What if this fails (e.g., file doesn't exist or is not 
00194       // well-formed)?? How to report it?
00195       DOM_Document doc = parser.parse(filenameStr.c_str());
00196       
00197       // Check it's a good doc.  
00198       if (doc == DOM_Document()) {
00199         FATAL_MACRO("Attempt to construct IFile from null DOM_Document");
00200         return;
00201       }
00202       
00203       // If so, initialize IFile from it
00204       domToIni(doc);
00205     }
00206 
00207   // Work of constructor minus parsing
00208   void IFile::domToIni(const DOM_Document& doc) {
00209     DOM_Element  root = doc.getDocumentElement();
00210     
00211     // Now invoke element version to do the work
00212     domToIni(root);
00213   }        
00214 
00215   void IFile::domToIni(const DOM_Element& root) {
00216     // Done this way, any child elements which are *not* sections
00217     // will simply be ignored.  Another strategy would be to look 
00218     // at all children and complain if any are not sections
00219     DOM_NodeList list = root.getElementsByTagName("section");
00220     
00221     DOM_Element   child;
00222     int           nChild = list.getLength();
00223     int           iChild;
00224     
00225     for (iChild = 0; iChild < nChild; iChild++) {
00226       DOM_Node node = list.item(iChild);
00227       // Only handle immediate children here
00228       if (node.getParentNode() == root) {
00229         child = DOM_Element(static_cast<DOM_Element &>(node));
00230         addSection(child);
00231       }
00232     }
00233   }
00234   
00235   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00236   void IFile::addSection(const DOM_Element& section)  {
00237     if (!((section.getTagName()).equals("section"))) {
00238       FATAL_MACRO("Expecting tagName==section, found " << 
00239                 Dom::transToChar(section.getTagName()) );
00240     }
00241     
00242     // start a section
00243     // DOM_Element::getAttribute returns a DOMString; hence need to transcode
00244     char*  sectName = Dom::transToChar((section.getAttribute("name")));
00245     IFile_Section* curSection = new IFile_Section(sectName);
00246     (*this)[curSection->title()]=curSection;
00247     
00248     DOM_NodeList list = section.getChildNodes();
00249     DOM_Element   child;
00250     int           nChild = list.getLength();
00251     int           iChild;
00252     
00253     for (iChild = 0; iChild < nChild; iChild++) {
00254       DOM_Node node = list.item(iChild);
00255       if (node.getNodeType() == DOM_Node::ELEMENT_NODE) {
00256         child = DOM_Element(static_cast<DOM_Element &>(node));
00257         
00258         if ((child.getTagName()).equals("section")) {
00259           addSection(child);
00260         }
00261         else if ((child.getTagName()).equals("item")) {
00262           // force a copy because Dom::transToChar uses a fixed buffer
00263           std::string  itemName(Dom::transToChar(child.getAttribute("name")));
00264           std::string itemValue(Dom::transToChar(child.getAttribute("value")));
00265           
00266           // Make the new item
00267           IFile_Item* newItem = 
00268             new IFile_Item(itemName, itemValue);
00269           // Add it to the section map
00270           (*curSection)[newItem->title()]= newItem;
00271         }
00272         else {
00273           char *tag = Dom::transToChar(child.getTagName());
00274           FATAL_MACRO("unexpected tag in initialization:" << tag);
00275         }
00276       }
00277     }
00278     
00279   }
00280   
00281   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00282   bool IFile::contains (const char *section, const char *item)
00283     {
00284       return (IFile::_getstring (section, item, 0) != 0);
00285     }
00286   
00287   
00288   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00289   const char *IFile::_getstring(const char *sectionname, const char *itemname, 
00290                                 int failFlag)
00291     {
00292       char     hitem[1000], hsection[1000];
00293       IFile_Item    *item = 0;
00294       IFile_Section *section =0;
00295       
00296       stripBlanks (hitem,    itemname,    ALL);
00297       stripBlanks (hsection, sectionname, ALL);
00298       
00299       const_iterator entry = find(std::string(hsection));
00300       
00301       if (entry  != end() )      {
00302         section = (*entry).second;
00303         
00304         IFile_Section::const_iterator it = section->find(std::string(hitem));
00305         item = (it != section->end() ) ?item = (*it).second :  0;
00306         
00307       }
00308       
00309       if (item != 0)   {
00310 #ifdef DEBUG
00311         INFO ("getstring: [" << hsection << "]" << hitem << ": ->" << 
00312               (item->string()) << "<-");
00313 #endif
00314         return item->mystring().c_str();
00315       }
00316       else if (failFlag)
00317       {
00318         if (section == 0)
00319           FATAL_MACRO ("cannot find section [" << sectionname << "]");
00320         else
00321           FATAL_MACRO ("cannot find item \"" << itemname << "\" in section [" << 
00322                        sectionname << "]");
00323         return 0;
00324       }
00325       
00326       else   return 0;
00327     }
00328   
00329   // getting data from [section]item, exiting when not found
00330   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00331   const char *IFile::getString (const char *section, const char *item)
00332     {
00333       return _getstring(section, item);
00334     }
00335   
00336   // setting data in [section]
00337   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00338   void IFile::setString(const char *sectionname, const char *itemname, 
00339                         const char* newString)
00340     {
00341       char     hitem[1000], hsection[1000];
00342       IFile_Item    *item =0;
00343       IFile_Section *section=0;
00344       
00345       stripBlanks (hitem,    itemname,    ALL);
00346       stripBlanks (hsection, sectionname, ALL);
00347       
00348       iterator it = find(std::string(hsection));
00349       
00350       if ( it != end() )      {
00351         section = (*it).second;
00352         
00353         if (section->contains(hitem) )
00354           item = section->lookUp(hitem);
00355       }
00356       
00357       if (item) item->mystring()=newString;
00358     }
00359   
00360   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00361   double IFile::getDouble (const char *section, const char *item)
00362     {
00363       double    hf;
00364       std::string hilf (IFile::_getstring (section, item));
00365       
00366       if (sscanf(hilf.c_str(), "%le", &hf) != 1)
00367         FATAL_MACRO ("[" << section << "]" << item << " = \'" << hilf << 
00368                      "\' cannot be converted to double");
00369       
00370       return hf;
00371     }
00372   
00373   
00374   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00375   int IFile::getInt (const char *section, const char *item)
00376     {
00377       int       hf;
00378       std::string hilf (IFile::_getstring (section, item));
00379       
00380       if (sscanf(hilf.c_str(), "%d", &hf) != 1)
00381         FATAL_MACRO ("[" << section << "]" << item << " = \'" << hilf << 
00382                      "\' cannot be converted to int");
00383       
00384       return (hf);
00385     }
00386   
00387   
00388   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00389   int IFile::getBool (const char *section, const char *item)
00390     {
00391       std::string hilf (IFile::_getstring (section, item));
00392       
00393       if      (hilf == "yes")
00394         return (1);
00395       else if (hilf == "true")
00396         return (1);
00397       else if (hilf == "1")
00398         return (1);
00399       else if (hilf == "no")
00400         return (0);
00401       else if (hilf == "false")
00402         return (0);
00403       else if (hilf == "0")
00404         return (0);
00405       else
00406         FATAL_MACRO ("[" << section << "]" << item << " = \'" << hilf << 
00407                      "\' is not boolean");
00408       return (0);
00409     }
00410   
00411   
00412   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00413   IFile::intVector IFile::getIntVector (const char *section, const char *item)
00414     {
00415       intVector iv;
00416       char buffer[1024];
00417       
00418       strncpy(buffer, IFile::_getstring(section,item), sizeof(buffer) -1);
00419       if ( strlen(buffer) >= sizeof(buffer) ) {
00420         FATAL_MACRO("string returned from _getstring is too long");
00421         return iv;
00422       }
00423       
00424       char *vString = strtok(buffer,"}");
00425       vString = strtok(buffer,"{");
00426       
00427       char *test = strtok(vString,",");
00428       while (test != NULL) {
00429         iv.push_back(atoi(test));
00430         test = strtok((char*)NULL,",");
00431       }
00432       if (iv.size() <= 0) {
00433         std::string hilf (buffer);
00434         FATAL_MACRO ("[" << section << "]"  << item << " = \'"
00435                      << hilf << "\' is not an integer vector");
00436       }
00437       return (iv);
00438     }
00439   
00440   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00441   IFile::doubleVector IFile::getDoubleVector (const char *section, 
00442                                               const char *item)
00443     {
00444       doubleVector dv;
00445       char buffer[1024];
00446       
00447       strncpy(buffer, IFile::_getstring(section,item), sizeof(buffer) );
00448       if (strlen(buffer) >= sizeof(buffer) ) {
00449         FATAL_MACRO("string from _getstring() too long");
00450         return dv;
00451       }
00452       char *vString = strtok(buffer,"}");
00453       vString = strtok(buffer,"{");
00454       
00455       char *test = strtok(vString,",");
00456       while (test != NULL) {
00457         dv.push_back(atof(test));
00458         test = strtok((char*)NULL,",");
00459       }
00460       if (dv.size() <= 0) {
00461         std::string hilf (buffer);
00462         FATAL_MACRO ("[" << section << "]"  << item << " = \'"
00463                      << hilf << "\' is not an double vector");
00464       }
00465       return (dv);
00466     }
00467   
00468   // getting data from [section]item, with def. values provided
00469   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00470   int IFile::getInt (const char *section, const char *item, int defValue) {
00471     return ( contains(section, item) )? getInt( section, item ):defValue;
00472   }
00473   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00474   int IFile::getBool (const char *section, const char *item, int defValue)
00475     {
00476       return ( contains(section, item) )? getBool( section, item ):defValue;
00477     }
00478   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00479   double IFile::getDouble(const char *section, const char *item, 
00480                           double defValue)   {
00481     return ( contains(section, item) )? getDouble( section, item ):defValue;
00482   }
00483   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00484   const char *IFile::getString (const char *section, const char *item, 
00485                                 const char *defValue) {
00486     return ( contains(section, item) )? getString( section, item ):defValue;
00487   }
00488   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00489   IFile::intVector IFile::getIntVector (const char *section, const char *item, 
00490                                         intVector defValues)    {
00491     return (contains(section, item))? getIntVector(section, item) 
00492       : defValues;
00493   }
00494   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00495   IFile::doubleVector IFile::getDoubleVector (const char *section, 
00496                                               const char *item, 
00497                                               doubleVector defValues)  {
00498     return (contains(section, item))? getDoubleVector(section, item):defValues;
00499   }
00500 } //   end namespace xml
00501 

Generated at Wed Nov 21 12:22:26 2001 by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000