$extrastylesheet
parameters.h
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 
00019 
00020 #ifndef LIBMESH_PARAMETERS_H
00021 #define LIBMESH_PARAMETERS_H
00022 
00023 // C++ includes
00024 #include <typeinfo>
00025 #include <string>
00026 #include <map>
00027 
00028 // Local includes
00029 #include "libmesh/libmesh_common.h"
00030 #include "libmesh/reference_counted_object.h"
00031 #include "libmesh/print_trace.h"
00032 
00033 // C++ includes
00034 #include <cstddef>
00035 #include <map>
00036 #include <string>
00037 #include <typeinfo>
00038 #include <sstream>
00039 
00040 namespace libMesh
00041 {
00045 template<typename P>
00046 void print_helper(std::ostream& os, const P* param);
00047 
00048 template<typename P>
00049 void print_helper(std::ostream& os, const std::vector<P>* param);
00050 
00061 // ------------------------------------------------------------
00062 // Parameters class definition
00063 class Parameters
00064 {
00065 public:
00066 
00070   Parameters () {}
00071 
00075   Parameters (const Parameters&);
00076 
00080   virtual ~Parameters ();
00081 
00086   virtual Parameters& operator= (const Parameters& source);
00087 
00093   virtual Parameters& operator+= (const Parameters& source);
00094 
00102   template <typename T>
00103   bool have_parameter (const std::string&) const;
00104 
00109   template <typename T>
00110   const T& get (const std::string&) const;
00111 
00117   template <typename T>
00118   void insert (const std::string&);
00119 
00126   template <typename T>
00127   T& set (const std::string&);
00128 
00133   virtual void set_attributes(const std::string&, bool /*inserted_only*/) {}
00134 
00138   void remove (const std::string&);
00139 
00143   std::size_t n_parameters () const { return _values.size(); }
00144 
00145 #ifdef LIBMESH_HAVE_RTTI
00146 
00149   template <typename T>
00150   unsigned int n_parameters () const;
00151 #endif // LIBMESH_HAVE_RTTI
00152 
00156   virtual void clear ();
00157 
00161   void print (std::ostream& os=libMesh::out) const;
00162 
00163 private:
00164 
00168   class Value : public ReferenceCountedObject<Value>
00169   {
00170   public:
00171 
00175     virtual ~Value() {}
00176 
00177 #ifdef LIBMESH_HAVE_RTTI
00178 
00182     virtual std::string type () const = 0;
00183 #endif // LIBMESH_HAVE_RTTI
00184 
00189     virtual void print(std::ostream&) const = 0;
00190 
00195     virtual Value* clone () const = 0;
00196   };
00197 
00198 public:
00199 
00204   template <typename T>
00205   class Parameter : public Value
00206   {
00207   public:
00208 
00212     const T& get () const { return _value; }
00213 
00217     T& set () { return _value; }
00218 
00219 #ifdef LIBMESH_HAVE_RTTI
00220 
00223     virtual std::string type () const;
00224 #endif // LIBMESH_HAVE_RTTI
00225 
00229     virtual void print(std::ostream&) const;
00230 
00234     virtual Value* clone () const;
00235 
00236   private:
00240     T _value;
00241   };
00242 
00246   typedef std::map<std::string, Value*>::iterator iterator;
00247 
00251   typedef std::map<std::string, Value*>::const_iterator const_iterator;
00252 
00256   iterator begin();
00257 
00261   const_iterator begin() const;
00262 
00266   iterator end();
00267 
00271   const_iterator end() const;
00272 
00273 protected:
00274 
00278   std::map<std::string, Value*> _values;
00279 
00280 };
00281 
00282 // ------------------------------------------------------------
00283 // Parameters::Parameter<> class inline methods
00284 
00285 // This only works with Run-Time Type Information, even though
00286 // typeid(T) *should* be determinable at compile time regardless...
00287 #ifdef LIBMESH_HAVE_RTTI
00288 template <typename T>
00289 inline
00290 std::string Parameters::Parameter<T>::type () const
00291 {
00292   return demangle(typeid(T).name());
00293 }
00294 #endif
00295 
00296 template <typename T>
00297 inline
00298 void Parameters::Parameter<T>::print (std::ostream& os) const
00299 {
00300   // Call helper function overloaded for basic scalar and vector types
00301   print_helper(os, static_cast<const T*>(&_value));
00302 }
00303 
00304 template <typename T>
00305 inline
00306 Parameters::Value* Parameters::Parameter<T>::clone () const
00307 {
00308   // No good for Solaris C++! - BSK
00309   //  Parameters::Parameter<T>
00310   //    *copy = new Parameters::Parameter<T>;
00311   Parameter<T>
00312     *copy = new Parameter<T>;
00313 
00314   libmesh_assert(copy);
00315 
00316   copy->_value = _value;
00317 
00318   return copy;
00319 }
00320 
00321 
00322 // ------------------------------------------------------------
00323 // Parameters class inline methods
00324 inline
00325 void Parameters::clear () // since this is inline we must define it
00326 {                         // before its first use (for some compilers)
00327   while (!_values.empty())
00328     {
00329       Parameters::iterator it = _values.begin();
00330 
00331       delete it->second;
00332       it->second = NULL;
00333 
00334       _values.erase(it);
00335     }
00336 }
00337 
00338 
00339 
00340 inline
00341 Parameters& Parameters::operator= (const Parameters& source)
00342 {
00343   this->clear();
00344   *this += source;
00345 
00346   return *this;
00347 }
00348 
00349 inline
00350 Parameters& Parameters::operator+= (const Parameters& source)
00351 {
00352   for (Parameters::const_iterator it = source._values.begin();
00353        it != source._values.end(); ++it)
00354     {
00355       if (_values.find(it->first) != _values.end())
00356         delete _values[it->first];
00357       _values[it->first] = it->second->clone();
00358     }
00359 
00360   return *this;
00361 }
00362 
00363 inline
00364 Parameters::Parameters (const Parameters& p)
00365 {
00366   *this = p;
00367 }
00368 
00369 
00370 
00371 inline
00372 Parameters::~Parameters ()
00373 {
00374   this->clear ();
00375 }
00376 
00377 
00378 
00379 inline
00380 void Parameters::print (std::ostream& os) const
00381 {
00382   Parameters::const_iterator it = _values.begin();
00383 
00384   os << "Name\t Type\t Value\n"
00385      << "---------------------\n";
00386   while (it != _values.end())
00387     {
00388       os << " "   << it->first
00389 #ifdef LIBMESH_HAVE_RTTI
00390          << "\t " << it->second->type()
00391 #endif // LIBMESH_HAVE_RTTI
00392          << "\t ";   it->second->print(os);
00393       os << '\n';
00394 
00395       ++it;
00396     }
00397 }
00398 
00399 
00400 
00401 // Declare this now that Paramers::print() is defined.
00402 // By declaring this early we can use it in subsequent
00403 // methods.  Required for gcc-4.0.2 -- 11/30/2005, BSK
00404 inline
00405 std::ostream& operator << (std::ostream& os, const Parameters& p)
00406 {
00407   p.print(os);
00408   return os;
00409 }
00410 
00411 
00412 
00413 template <typename T>
00414 inline
00415 bool Parameters::have_parameter (const std::string& name) const
00416 {
00417   Parameters::const_iterator it = _values.find(name);
00418 
00419   if (it != _values.end())
00420 #ifdef LIBMESH_HAVE_RTTI
00421     if (dynamic_cast<const Parameter<T>*>(it->second) != NULL)
00422 #else // LIBMESH_HAVE_RTTI
00423       if (cast_ptr<const Parameter<T>*>(it->second) != NULL)
00424 #endif // LIBMESH_HAVE_RTTI
00425         return true;
00426 
00427   return false;
00428 }
00429 
00430 
00431 
00432 template <typename T>
00433 inline
00434 const T& Parameters::get (const std::string& name) const
00435 {
00436   if (!this->have_parameter<T>(name))
00437     {
00438       std::ostringstream oss;
00439 
00440       oss << "ERROR: no";
00441 #ifdef LIBMESH_HAVE_RTTI
00442       oss << ' ' << demangle(typeid(T).name());
00443 #endif
00444       oss << " parameter named \""
00445           << name << "\":\n"
00446           << *this;
00447 
00448       libmesh_error_msg(oss.str());
00449     }
00450 
00451   Parameters::const_iterator it = _values.find(name);
00452 
00453   libmesh_assert(it != _values.end());
00454   libmesh_assert(it->second);
00455 
00456   return cast_ptr<Parameter<T>*>(it->second)->get();
00457 }
00458 
00459 template <typename T>
00460 inline
00461 void Parameters::insert (const std::string &name)
00462 {
00463   if (!this->have_parameter<T>(name))
00464     _values[name] = new Parameter<T>;
00465 
00466   set_attributes(name, true);
00467 }
00468 
00469 
00470 template <typename T>
00471 inline
00472 T& Parameters::set (const std::string& name)
00473 {
00474   if (!this->have_parameter<T>(name))
00475     _values[name] = new Parameter<T>;
00476 
00477   set_attributes(name, false);
00478 
00479   return cast_ptr<Parameter<T>*>(_values[name])->set();
00480 }
00481 
00482 inline
00483 void Parameters::remove (const std::string& name)
00484 {
00485   Parameters::iterator it = _values.find(name);
00486 
00487   if (it != _values.end())
00488     {
00489       delete it->second;
00490       it->second = NULL;
00491 
00492       _values.erase(it);
00493     }
00494 }
00495 
00496 
00497 
00498 #ifdef LIBMESH_HAVE_RTTI
00499 template <typename T>
00500 inline
00501 unsigned int Parameters::n_parameters () const
00502 {
00503   unsigned int cnt = 0;
00504 
00505   Parameters::const_iterator       it  = _values.begin();
00506   const Parameters::const_iterator vals_end = _values.end();
00507 
00508   for (; it != vals_end; ++it)
00509     if (dynamic_cast<Parameter<T>*>(it->second) != NULL)
00510       cnt++;
00511 
00512   return cnt;
00513 }
00514 #endif
00515 
00516 inline
00517 Parameters::iterator Parameters::begin()
00518 {
00519   return _values.begin();
00520 }
00521 
00522 inline
00523 Parameters::const_iterator Parameters::begin() const
00524 {
00525   return _values.begin();
00526 }
00527 
00528 inline
00529 Parameters::iterator Parameters::end()
00530 {
00531   return _values.end();
00532 }
00533 
00534 inline
00535 Parameters::const_iterator Parameters::end() const
00536 {
00537   return _values.end();
00538 }
00539 
00540 //non-member scalar print function
00541 template<typename P>
00542 void print_helper(std::ostream& os, const P* param)
00543 {
00544   os << *param;
00545 }
00546 
00547 //non-member vector print function
00548 template<typename P>
00549 void print_helper(std::ostream& os, const std::vector<P>* param)
00550 {
00551   for (unsigned int i=0; i<param->size(); ++i)
00552     os << (*param)[i] << " ";
00553 }
00554 
00555 } // namespace libMesh
00556 
00557 #endif // LIBMESH_PARAMETERS_H