00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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()) {
00108
00109
00110 if (type_id_traits::dynamic) {
00111 id_type new_id;
00112
00113 if (_data.empty()) {
00114
00115 new_id = type_id_traits::first();
00116 } else {
00117
00118
00119 new_id = type_id_traits::next(rbegin()->first);
00120 }
00121
00122 if (insert(value_type(new_id,name))) {
00123
00124 return new_id;
00125 }
00126 }
00127
00128
00129
00130 return type_id_traits::unknown();
00131 }
00132
00133
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
00150 if (!update_index(vt.second,tmp.first)) {
00151
00152
00153 _data.erase(tmp.first);
00154 return false;
00155 }
00156 } else return false;
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 }
00205 }
00206
00207 #endif