ParamMap.C

Go to the documentation of this file.
00001 /*!@file Component/ParamMap.C I/O operations for parameter files */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00005 // University of Southern California (USC) and the iLab at USC.         //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Rob Peters <rjpeters@klab.caltech.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Component/ParamMap.C $
00035 // $Id: ParamMap.C 12962 2010-03-06 02:13:53Z irock $
00036 //
00037 
00038 #ifndef PARAMMAP_C_DEFINED
00039 #define PARAMMAP_C_DEFINED
00040 
00041 #include "Component/ParamMap.H"
00042 
00043 #include "Util/Assert.H"
00044 #include "Util/Types.H"
00045 #include "Util/log.H"
00046 
00047 #include <fstream>
00048 #include <iomanip>
00049 #include <iostream>
00050 #include <limits>
00051 #include <map>
00052 #include <sstream>
00053 #include <string>
00054 #include <vector>
00055 
00056 // ######################################################################
00057 namespace dummy_namespace_to_avoid_gcc411_bug_ParamMap_C
00058 {
00059   void escapeWrite(std::ostream& ostrm, const std::string& s)
00060   {
00061     for (uint i = 0; i < s.size(); ++i)
00062       {
00063         switch (s[i])
00064           {
00065           // Need to escape whitespace in order to allow interior
00066           // whitespace within attribute values:
00067           case ' '   : ostrm << '\\' << ' '; break;
00068           case '\t'  : ostrm << '\\' << '\t'; break;
00069           case '\n'  : ostrm << '\\' << '\n'; break;
00070 
00071           // Must escape a backslash itself in order to not confuse it with
00072           // "backslash-as-escape-character"
00073           case '\\'  : ostrm << '\\' << '\\'; break;
00074 
00075           // Anything else can be written literally
00076           default    : ostrm << s[i]; break;
00077           }
00078       }
00079   }
00080 
00081   std::string escapeRead(std::istream& istrm)
00082   {
00083     // Read into a std::vector<char> rather than a std::string since it has
00084     // amortized-constant push_back(), which is not necessarily the case
00085     // for std::string.
00086     std::vector<char> buf;
00087 
00088     bool finished = false;
00089 
00090     // Skip over any unescaped whitespace that precedes the text of interest:
00091     istrm >> std::ws;
00092 
00093     while (!finished)
00094       {
00095         const int c = char(istrm.get());
00096 
00097         switch(c)
00098           {
00099           // (1) In case of unescaped whitespace or EOF, we're done:
00100           case EOF:
00101           case ' ':
00102           case '\t':
00103           case '\n':
00104             finished = true;
00105             break;
00106 
00107           // (2) In case of a backslash, take the subsequent character literally:
00108           case '\\':
00109             if (istrm.peek() == EOF)
00110               {
00111                 // We'd better not find EOF following a backslash
00112                 LFATAL("Incomplete escape sequence before EOF!");
00113               }
00114             buf.push_back(char(istrm.get()));
00115             break;
00116 
00117           // (3) Otherwise, take the current character literally:
00118           default:
00119             buf.push_back(char(c));
00120             break;
00121           }
00122       }
00123 
00124     // Must add a null-terminator
00125     buf.push_back('\0');
00126 
00127     // Gobble up any trailing un-escaped whitespace from the input stream
00128     while( istrm.peek() == '\t' || istrm.peek() == ' ' )
00129       istrm.get();
00130 
00131     return std::string(&buf[0]);
00132   }
00133 
00134   struct Param
00135   {
00136     Param() : str(), pmap() {}
00137 
00138     Param(double v) : str(), pmap()
00139     {
00140       std::ostringstream oss;
00141       oss << std::setprecision(25) << v;
00142       str = oss.str();
00143     }
00144 
00145     Param(int v) : str(), pmap()
00146     {
00147       std::ostringstream oss; oss << v; str = oss.str();
00148     }
00149 
00150     Param(const std::string& s) : str(s), pmap() {}
00151 
00152     Param(const rutz::shared_ptr<ParamMap>& p) : str(), pmap(p) {}
00153 
00154     void put(std::ostream& ostrm, int indentlev = 0) const
00155     {
00156       if (pmap.get() != 0)
00157         {
00158           ostrm << "{\n";
00159           pmap->format(ostrm, indentlev+1);
00160           for (int i = 0; i < indentlev; ++i) ostrm << '\t';
00161           ostrm << '}';
00162         }
00163       else
00164         {
00165           escapeWrite(ostrm, str);
00166         }
00167     }
00168 
00169     double getDouble() const
00170     {
00171       std::istringstream iss(str);
00172       double val;
00173       iss >> val;
00174       return val;
00175     }
00176 
00177     int getInt() const
00178     {
00179       std::istringstream iss(str);
00180       int val;
00181       iss >> val;
00182       return val;
00183     }
00184 
00185     rutz::shared_ptr<ParamMap> getMap() const
00186     {
00187       if (pmap.get() == 0)
00188         {
00189           LFATAL("No such parameter submap.");
00190         }
00191       return pmap;
00192     }
00193 
00194     bool isLeaf() const
00195     {
00196       if (pmap.get() == 0)
00197         return true;
00198       else
00199         return false;
00200     }
00201 
00202    std::string str;
00203     mutable rutz::shared_ptr<ParamMap> pmap;
00204   };
00205 }
00206 
00207 using namespace dummy_namespace_to_avoid_gcc411_bug_ParamMap_C;
00208 
00209 // ######################################################################
00210 struct ParamMap::Impl
00211 {
00212   typedef std::map<std::string, Param> MapType;
00213 
00214   MapType itsParams;
00215 };
00216 
00217 // ######################################################################
00218 struct ParamMap::key_iterator::IterRep
00219 {
00220   ParamMap::Impl::MapType::const_iterator iter;
00221 };
00222 
00223 // ######################################################################
00224 ParamMap::key_iterator::key_iterator() :
00225   rep(new IterRep)
00226 {}
00227 
00228 // ######################################################################
00229 ParamMap::key_iterator::~key_iterator()
00230 {
00231   delete rep;
00232 }
00233 
00234 // ######################################################################
00235 ParamMap::key_iterator::key_iterator(const key_iterator& other) :
00236   rep(new IterRep)
00237 {
00238   rep->iter = other.rep->iter;
00239 }
00240 
00241 // ######################################################################
00242 ParamMap::key_iterator&
00243 ParamMap::key_iterator::operator=(const key_iterator& other)
00244 {
00245   rep->iter = other.rep->iter; return *this;
00246 }
00247 
00248 // ######################################################################
00249 const std::string& ParamMap::key_iterator::operator*() const
00250 {
00251   return (*(rep->iter)).first;
00252 }
00253 
00254 // ######################################################################
00255 ParamMap::key_iterator&
00256 ParamMap::key_iterator::operator++()
00257 {
00258   ++(rep->iter); return *this;
00259 }
00260 
00261 // ######################################################################
00262 bool ParamMap::key_iterator::operator==(const key_iterator& other) const
00263 {
00264   return rep->iter == other.rep->iter;
00265 }
00266 
00267 // ######################################################################
00268 bool ParamMap::key_iterator::operator!=(const key_iterator& other) const
00269 {
00270   return rep->iter != other.rep->iter;
00271 }
00272 
00273 // ######################################################################
00274 rutz::shared_ptr<ParamMap> ParamMap::loadPmapFile(const std::string& fname)
00275 {
00276   rutz::shared_ptr<ParamMap> result(new ParamMap);
00277   result->load(fname);
00278   return result;
00279 }
00280 
00281 // ######################################################################
00282 rutz::shared_ptr<ParamMap> ParamMap::loadConfFile(const std::string& fname)
00283 {
00284   rutz::shared_ptr<ParamMap> pmap(new ParamMap);
00285 
00286   std::ifstream inFile(fname.c_str());
00287 
00288   int counter = 0;
00289   bool inComment = false;
00290   std::string instring;
00291   std::string paramName;
00292   while (inFile >> instring)
00293     {
00294       if (instring == "#")
00295         {
00296           // the comment code "#" toggles our in-comment state
00297           inComment = !inComment;
00298         }
00299       else if (!inComment) //real line found
00300         {
00301           if (paramName.length() == 0)
00302             {
00303               paramName.swap(instring);
00304             }
00305           else
00306             {
00307               pmap->putStringParam(paramName, instring);
00308               LINFO("%s[%d]: %s = %s",
00309                     fname.c_str(), counter,
00310                     paramName.c_str(), instring.c_str());
00311               paramName.clear();
00312               ++counter;
00313             }
00314         }
00315     }
00316 
00317   return pmap;
00318 }
00319 
00320 /*
00321 // ######################################################################
00322 template <class T>
00323 rutz::shared_ptr<ParamMap> ParamMap::loadC_Map(const std::map <std::string, T> c_map)
00324 {
00325   typedef std::map<std::string, T> TMap;
00326   rutz::shared_ptr<ParamMap> pmap(new ParamMap);
00327 
00328   int counter = 0;
00329   T val;
00330   std::string str, paramName;
00331   TMap::iterator i;
00332   for(i = c_map.begin(); i != c_map.end(); ++i)
00333     {
00334       paramName = i->first;
00335       val = i->second;
00336       std::ostringstream oss; oss << val; str = oss.str();
00337       pmap->putStringParam(paramName, str);
00338       LINFO("cmap:[%d]: %s = %s",
00339             counter, paramName.c_str(), str.c_str());
00340       paramName.clear();
00341       ++counter;
00342     }
00343   return pmap;
00344   }
00345 */
00346 // ######################################################################
00347 ParamMap::ParamMap() :
00348   rep(new Impl)
00349 {}
00350 
00351 // ######################################################################
00352 ParamMap::ParamMap(const std::string& fname) :
00353   rep(new Impl)
00354 {
00355   load(fname);
00356 }
00357 
00358 // ######################################################################
00359 ParamMap::~ParamMap()
00360 {
00361   delete rep;
00362 }
00363 
00364 // ######################################################################
00365 ParamMap::key_iterator
00366 ParamMap::keys_begin() const
00367 {
00368   key_iterator result;
00369   result.rep->iter = rep->itsParams.begin();
00370   return result;
00371 }
00372 
00373 // ######################################################################
00374 ParamMap::key_iterator
00375 ParamMap::keys_end() const
00376 {
00377   key_iterator result;
00378   result.rep->iter = rep->itsParams.end();
00379   return result;
00380 }
00381 
00382 // ######################################################################
00383 void ParamMap::load(std::istream& istrm)
00384 {
00385   while (istrm.peek() != EOF)
00386     {
00387       if (istrm.peek() == '#')
00388         {
00389           istrm.ignore(std::numeric_limits<int>::max(), '\n');
00390           istrm >> std::ws;
00391           continue;
00392         }
00393 
00394       const std::string attribname = escapeRead(istrm);
00395 
00396       if (istrm.peek() != '{')
00397         {
00398           std::string attribval;
00399           while( istrm.peek() == '\t' || istrm.peek() == ' ' )
00400               istrm.get();
00401           if ( istrm.peek() == '\n' )
00402               attribval = "";
00403           else
00404             attribval = escapeRead(istrm);
00405 
00406           rep->itsParams.insert(Impl::MapType::value_type(attribname,
00407                                                           attribval));
00408         }
00409       else
00410         {
00411           std::string attribval;
00412 
00413           int bracelevel = 0;
00414           // First time through loop we pick up the opening brace '{'
00415           do
00416             {
00417               int c = istrm.get();
00418 
00419               if (c == EOF)
00420                 {
00421                   LFATAL("Unexpected EOF before closing brace '}'.");
00422                 }
00423               switch (c)
00424                 {
00425                 case '{':
00426                   // Don't add the opening brace to the value string
00427                   if (bracelevel++ > 0)
00428                     attribval.push_back(char(c));
00429                   break;
00430                 case '}':
00431                   // Don't add the closing brace to the value string
00432                   if (--bracelevel > 0)
00433                     attribval.push_back(char(c));
00434                   break;
00435                 default:
00436                   attribval.push_back(char(c));
00437                   break;
00438                 }
00439             }
00440           while (bracelevel > 0);
00441 
00442           rutz::shared_ptr<ParamMap> submap(new ParamMap);
00443 
00444           std::istringstream iss(attribval);
00445           submap->load(iss);
00446 
00447           rep->itsParams.insert(Impl::MapType::value_type(attribname, submap));
00448         }
00449 
00450       istrm >> std::ws;
00451     }
00452 }
00453 
00454 // ######################################################################
00455 void ParamMap::load(const std::string& fname)
00456 {
00457   std::ifstream ifs(fname.c_str());
00458 
00459   if (!ifs.is_open())
00460     {
00461       LFATAL("Couldn't open file '%s' for reading.", fname.c_str());
00462     }
00463 
00464   load(ifs);
00465 
00466   ifs.close();
00467 }
00468 
00469 // ######################################################################
00470 void ParamMap::format(std::ostream& ostrm, int indentlev) const
00471 {
00472   for (Impl::MapType::const_iterator
00473          itr = rep->itsParams.begin(), stop = rep->itsParams.end();
00474        itr != stop;
00475        ++itr)
00476     {
00477       for (int i = 0; i < indentlev; ++i) ostrm << '\t';
00478       escapeWrite(ostrm, (*itr).first);
00479       ostrm << "  ";
00480       (*itr).second.put(ostrm, indentlev);
00481       ostrm << '\n';
00482     }
00483 }
00484 
00485 // ######################################################################
00486 void ParamMap::format(const std::string& fname) const
00487 {
00488   std::ofstream ofs(fname.c_str());
00489 
00490   if (!ofs.is_open())
00491     {
00492       LFATAL("Couldn't open file '%s' for writing.", fname.c_str());
00493     }
00494 
00495   format(ofs);
00496 
00497   ofs.close();
00498 }
00499 
00500 // ######################################################################
00501 bool ParamMap::hasParam(const std::string& paramname) const
00502 {
00503   Impl::MapType::const_iterator itr = rep->itsParams.find(paramname);
00504   return (itr != rep->itsParams.end());
00505 }
00506 
00507 // ######################################################################
00508 bool ParamMap::isLeaf(const std::string& paramname) const
00509 {
00510   Impl::MapType::const_iterator itr = rep->itsParams.find(paramname);
00511   if (itr->second.isLeaf())
00512     return true;
00513   else
00514     return false;
00515 }
00516 
00517 // ######################################################################
00518 uint ParamMap::getsize() const
00519 {
00520   return rep->itsParams.size();
00521 }
00522 
00523 // ######################################################################
00524 rutz::shared_ptr<ParamMap> ParamMap::getSubpmap(const std::string& paramname) const
00525 {
00526   Impl::MapType::const_iterator itr = rep->itsParams.find(paramname);
00527   if (itr == rep->itsParams.end())
00528     {
00529       LFATAL("No parameter named '%s'.", paramname.c_str());
00530     }
00531   return (*itr).second.getMap();
00532 }
00533 
00534 // ######################################################################
00535 std::string ParamMap::getStringParam(const std::string& paramname) const
00536 {
00537   Impl::MapType::const_iterator itr = rep->itsParams.find(paramname);
00538   if (itr == rep->itsParams.end())
00539     {
00540       LFATAL("No parameter named '%s'.", paramname.c_str());
00541     }
00542   return (*itr).second.str;
00543 }
00544 
00545 // ######################################################################
00546 double ParamMap::getDoubleParam(const std::string& paramname) const
00547 {
00548   Impl::MapType::const_iterator itr = rep->itsParams.find(paramname);
00549   if (itr == rep->itsParams.end())
00550     {
00551       LFATAL("No parameter named '%s'.", paramname.c_str());
00552     }
00553   return (*itr).second.getDouble();
00554 }
00555 
00556 // ######################################################################
00557 int ParamMap::getIntParam(const std::string& paramname) const
00558 {
00559   Impl::MapType::const_iterator itr = rep->itsParams.find(paramname);
00560   if (itr == rep->itsParams.end())
00561     {
00562       LFATAL("No parameter named '%s'.", paramname.c_str());
00563     }
00564   return (*itr).second.getInt();
00565 }
00566 
00567 // ######################################################################
00568 std::string ParamMap::getStringParam(const std::string& paramname,
00569                                      const std::string& defval) const
00570 {
00571   std::string result = defval;
00572   queryStringParam(paramname, result);
00573   return result;
00574 }
00575 
00576 // ######################################################################
00577 double ParamMap::getDoubleParam(const std::string& paramname,
00578                                 const double defval) const
00579 {
00580   double result = defval;
00581   queryDoubleParam(paramname, result);
00582   return result;
00583 }
00584 
00585 // ######################################################################
00586 int ParamMap::getIntParam(const std::string& paramname,
00587                           const int defval) const
00588 {
00589   int result = defval;
00590   queryIntParam(paramname, result);
00591   return result;
00592 }
00593 
00594 // ######################################################################
00595 rutz::shared_ptr<ParamMap> ParamMap::lookupSubpmap(const std::string& paramname)
00596 {
00597   if (hasParam(paramname))
00598     return getSubpmap(paramname);
00599 
00600   // else...
00601   rutz::shared_ptr<ParamMap> submap(new ParamMap);
00602   putSubpmap(paramname, submap);
00603   return submap;
00604 }
00605 
00606 // ######################################################################
00607 ParamMap::ReturnCode
00608 ParamMap::queryStringParam(const std::string& paramname, std::string& result) const
00609 {
00610   Impl::MapType::const_iterator itr = rep->itsParams.find(paramname);
00611   if (itr != rep->itsParams.end())
00612     {
00613       const std::string new_val = (*itr).second.str;
00614       if (result.compare(new_val) != 0)
00615         {
00616           result = new_val;
00617           return CHANGED;
00618         }
00619       else
00620         return UNCHANGED;
00621     }
00622 
00623   // else...
00624   LINFO("Parameter '%s' not found; using default value '%s'.",
00625         paramname.c_str(), result.c_str());
00626   return MISSING;
00627 }
00628 
00629 // ######################################################################
00630 ParamMap::ReturnCode
00631 ParamMap::queryDoubleParam(const std::string& paramname, double& result) const
00632 {
00633   Impl::MapType::const_iterator itr = rep->itsParams.find(paramname);
00634   if (itr != rep->itsParams.end())
00635     {
00636       const double new_val = (*itr).second.getDouble();
00637       if (new_val != result)
00638         {
00639           result = new_val;
00640           return CHANGED;
00641         }
00642       else
00643         return UNCHANGED;
00644     }
00645 
00646   // else...
00647   LINFO("Parameter '%s' not found; using default value '%f'.",
00648         paramname.c_str(), result);
00649   return MISSING;
00650 }
00651 
00652 // ######################################################################
00653 ParamMap::ReturnCode
00654 ParamMap::queryIntParam(const std::string& paramname, int& result) const
00655 {
00656   Impl::MapType::const_iterator itr = rep->itsParams.find(paramname);
00657   if (itr != rep->itsParams.end())
00658     {
00659       const int new_val = (*itr).second.getInt();
00660       if (new_val != result)
00661         {
00662           result = new_val;
00663           return CHANGED;
00664         }
00665       else
00666         return UNCHANGED;
00667     }
00668 
00669   // else...
00670   LINFO("Parameter '%s' not found; using default value '%d'.",
00671         paramname.c_str(), result);
00672   return MISSING;
00673 }
00674 
00675 // ######################################################################
00676 void ParamMap::putSubpmap(const std::string& paramname, const rutz::shared_ptr<ParamMap>& val)
00677 {
00678   rep->itsParams.insert(Impl::MapType::value_type(paramname, val));
00679 }
00680 
00681 // ######################################################################
00682 void ParamMap::putStringParam(const std::string& paramname, const std::string& val)
00683 {
00684   rep->itsParams.insert(Impl::MapType::value_type(paramname, val));
00685 }
00686 
00687 // ######################################################################
00688 void ParamMap::putDoubleParam(const std::string& paramname, double val)
00689 {
00690   rep->itsParams.insert(Impl::MapType::value_type(paramname, val));
00691 }
00692 
00693 // ######################################################################
00694 void ParamMap::putIntParam(const std::string& paramname, int val)
00695 {
00696   rep->itsParams.insert(Impl::MapType::value_type(paramname, val));
00697 }
00698 
00699 // ######################################################################
00700 void ParamMap::replaceSubpmap(const std::string& paramname,
00701                               const rutz::shared_ptr<ParamMap>& val)
00702 {
00703   rep->itsParams.erase(rep->itsParams.find(paramname));
00704   rep->itsParams.insert(Impl::MapType::value_type(paramname, val));
00705 }
00706 
00707 // ######################################################################
00708 void ParamMap::replaceStringParam(const std::string& paramname, const std::string& val)
00709 {
00710   rep->itsParams.erase(rep->itsParams.find(paramname));
00711   rep->itsParams.insert(Impl::MapType::value_type(paramname, val));
00712 }
00713 
00714 // ######################################################################
00715 void ParamMap::replaceDoubleParam(const std::string& paramname, double val)
00716 {
00717   rep->itsParams.erase(rep->itsParams.find(paramname));
00718   rep->itsParams.insert(Impl::MapType::value_type(paramname, val));
00719 }
00720 
00721 // ######################################################################
00722 void ParamMap::replaceIntParam(const std::string& paramname, int val)
00723 {
00724   rep->itsParams.erase(rep->itsParams.find(paramname));
00725   rep->itsParams.insert(Impl::MapType::value_type(paramname, val));
00726 }
00727 
00728 // ######################################################################
00729 void ParamMap::clear()
00730 {
00731    rep->itsParams.clear();
00732 }
00733 
00734 // ######################################################################
00735 void ParamMap::erase(const std::string& paramname)
00736 {
00737   // should have error handling
00738   rep->itsParams.erase(rep->itsParams.find(paramname));
00739 }
00740 
00741 // ######################################################################
00742 void ParamMap::print(const std::string& name) const
00743 {
00744   std::cout << "--- begin " << name << " ---\n";
00745   for (Impl::MapType::const_iterator
00746          itr = rep->itsParams.begin(), stop = rep->itsParams.end();
00747        itr != stop;
00748        ++itr)
00749     {
00750       std::cout << "name: " << (*itr).first <<"****" <<std::endl;
00751       std::cout << "val: " << (*itr).second.str <<"****"<< std::endl;
00752     }
00753   std::cout << "--- end " << name << " ---\n";
00754 }
00755 
00756 // ######################################################################
00757 /* So things look consistent in everyone's emacs... */
00758 /* Local Variables: */
00759 /* indent-tabs-mode: nil */
00760 /* End: */
00761 
00762 #endif // !PARAMMAP_C_DEFINED
Generated on Sun May 8 08:04:42 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3