dictionary.hpp

Go to the documentation of this file.
00001 // -*- mode: c++; indent-tabs-mode: nil; -*-
00002 //
00003 //The Biomolecule Toolkit (BTK) is a C++ library for use in the
00004 //modeling, analysis, and design of biological macromolecules.
00005 //Copyright (C) 2006, Tim Robertson <kid50@users.sourceforge.net>
00006 //
00007 //This program is free software; you can redistribute it and/or modify
00008 //it under the terms of the GNU Lesser General Public License as published
00009 //by the Free Software Foundation; either version 2.1 of the License, or (at
00010 //your option) any later version.
00011 //
00012 //This program is distributed in the hope that it will be useful,  but
00013 //WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015 //Lesser General Public License for more details.
00016 //
00017 //You should have received a copy of the GNU Lesser General Public License
00018 //along with this program; if not, write to the Free Software Foundation,
00019 //Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00020 
00023 
00024 #ifndef BTK_IO_DICTIONARY_HPP
00025 #define BTK_IO_DICTIONARY_HPP
00026 
00027 #include <cctype>
00028 #include <string>
00029 #include <vector>
00030 #include <map>
00031 
00032 #include <btk/core/common/debugging.hpp>
00033 #include <btk/core/utility/type_id_traits.hpp>
00034 
00035 namespace BTK {
00036 namespace IO {
00037   
00038 template <typename IDType>
00039 class Dictionary 
00040 {
00041   typedef std::map<IDType,std::string> data_map;
00042   typedef std::map<std::string,typename data_map::iterator> symbol_index;
00043   
00044 public:
00045   typedef Dictionary<IDType> self_type;
00046 
00047   typedef IDType id_type;
00048   typedef typename data_map::value_type value_type;
00049   typedef typename data_map::const_iterator const_iterator;
00050   typedef typename data_map::const_reverse_iterator const_reverse_iterator;
00051 
00052   Dictionary(bool case_sensitive = true) : 
00053     _data(), _symbol_index(), _case_sensitive(case_sensitive) {}
00054 
00055   Dictionary(self_type const & d) :
00056     _data(d._data), _symbol_index(), 
00057     _case_sensitive(d._case_sensitive)
00058   {
00059     // data already copied; build the index.
00060     for (typename data_map::iterator i = _data.begin(); 
00061          i != _data.end(); ++i) {
00062       update_index(i->second,i);
00063     }
00064   }
00065   
00066   virtual ~Dictionary() {}
00067 
00068   const_iterator begin() const { return _data.begin(); }
00069   const_iterator end() const { return _data.end(); }
00070 
00071   const_reverse_iterator rbegin() const { return _data.rbegin(); }
00072   const_reverse_iterator rend() const { return _data.rend(); }
00073 
00074   virtual const_iterator find(id_type id) const { return _data.find(id); }
00075 
00076   virtual const_iterator find(std::string const & sym) const 
00077   {
00078     typename symbol_index::const_iterator i;
00079 
00080     if (!_case_sensitive) {
00081       i = _symbol_index.find(make_upper_case(sym));
00082     } else {
00083       i = _symbol_index.find(sym);
00084     }
00085 
00086     if (i != _symbol_index.end()) {
00087       return i->second;
00088     }
00089 
00090     return _data.end();
00091   }
00092 
00102   id_type get_type(std::string const & name)
00103   {
00104     typedef BTK::UTILITY::TypeIDTraits<id_type> type_id_traits;
00105     const_iterator i = find(name);
00106     
00107     if (i == end()) { // name not found! try to add a new type.
00108 
00109       // if this is a dynamic type, add a new type id
00110       if (type_id_traits::dynamic) {
00111         id_type new_id;
00112         
00113         if (_data.empty()) {            
00114           // dictionary empty? use first type!
00115           new_id = type_id_traits::first();
00116         } else {  
00117           // get new id using generator function 
00118           // (the id after last defined id value)
00119           new_id = type_id_traits::next(rbegin()->first);
00120         }
00121 
00122         if (insert(value_type(new_id,name))) {
00123           // insert of new type succeeded -- return it
00124           return new_id;
00125         }
00126       }
00127 
00128       // if here, either the type ID wasn't dynamic, or the dictionary
00129       // insert failed.  Return unknown.
00130       return type_id_traits::unknown();
00131     }
00132 
00133     // normal case:  ID found.  Return it.
00134     return i->first;
00135   }
00136 
00137   virtual bool insert(value_type const & vt)
00138   {
00139     std::pair<typename data_map::iterator,bool> tmp;
00140 
00141     if (!_case_sensitive) {
00142       tmp = _data.insert(value_type(vt.first,
00143                                     make_upper_case(vt.second)));
00144     } else {
00145       tmp = _data.insert(vt);
00146     }
00147 
00148     if (tmp.second) {
00149       // insert succeeded, add to index.
00150       if (!update_index(vt.second,tmp.first)) {
00151         // index insert failed -- symbol already exists.
00152         // remove entry from data and return failure
00153         _data.erase(tmp.first);
00154         return false;
00155       }
00156     } else return false; // insert failed
00157      
00158     return true;
00159   }
00160   
00161   virtual bool add_alternate_symbol(id_type id,
00162                                     std::string const & symbol) 
00163   {
00164     typename data_map::iterator i = _data.find(id);
00165     if (i == _data.end()) return false;
00166     
00167     if (!_case_sensitive) 
00168       return update_index(make_upper_case(symbol),i);
00169     else
00170       return update_index(symbol,i);
00171   }
00172 
00173   virtual void clear() { _data.clear(); _symbol_index.clear(); }
00174 
00175 protected:
00176   
00177   bool update_index(std::string const & s,
00178                     typename data_map::iterator i)
00179   {
00180     typedef typename symbol_index::value_type vt;
00181 
00182     if (!_case_sensitive)
00183       return _symbol_index.insert(vt(make_upper_case(s),i)).second;
00184     else
00185       return _symbol_index.insert(vt(s,i)).second; 
00186   }
00187 
00188   std::string make_upper_case(std::string const & s) const
00189   {
00190     std::string tmp(s);
00191 
00192     for (std::string::iterator i = tmp.begin(); i != tmp.end(); ++i)
00193       *i = std::toupper(*i);
00194 
00195     return tmp;
00196   }
00197   
00198 private:
00199   data_map _data;
00200   symbol_index _symbol_index;
00201   bool _case_sensitive;
00202 };
00203 
00204 } // IO
00205 } // BTK
00206 
00207 #endif 

Generated on Sun Jul 15 20:46:25 2007 for BTK Core by  doxygen 1.5.1