00001
00002
00003
00004
00005
00006
00007
00008 #ifndef IMP_KEY_H
00009 #define IMP_KEY_H
00010
00011 #include "macros.h"
00012 #include "exception.h"
00013 #include "utility.h"
00014 #include "internal/key_helpers.h"
00015
00016 #include <map>
00017 #include <vector>
00018
00019 IMP_BEGIN_NAMESPACE
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 template <unsigned int ID, bool LazyAdd>
00045 class KeyBase
00046 {
00047 int str_;
00048
00049 static const internal::KeyData::Map& get_map()
00050 {
00051 return IMP::internal::get_key_data(ID).get_map();
00052 }
00053 static const internal::KeyData::RMap& get_rmap() {
00054 return IMP::internal::get_key_data(ID).get_rmap();
00055 }
00056
00057
00058 static unsigned int find_index(std::string sc) {
00059 if (get_map().find(sc) == get_map().end()) {
00060 IMP_INTERNAL_CHECK(LazyAdd, "You must explicitly create the type"
00061 << " first: " << sc);
00062 return IMP::internal::get_key_data(ID).add_key(sc);
00063 } else {
00064 return get_map().find(sc)->second;
00065 }
00066 }
00067 private:
00068 bool is_default() const;
00069 public:
00070 #ifndef DOXYGEN
00071 static unsigned int get_ID() {
00072 return ID;
00073 }
00074
00075 static const std::string get_string(int i)
00076 {
00077 if (static_cast<unsigned int>(i)
00078 < get_rmap().size()) {
00079 return get_rmap()[i];
00080 } else {
00081 IMP_THROW("Corrupted Key Table asking for key " << i
00082 << " with a table of size " << get_rmap().size(),
00083 ValueException);
00084 }
00085 }
00086
00087 typedef KeyBase<ID, LazyAdd> This;
00088 #endif
00089
00090
00091 KeyBase(): str_(-1) {}
00092
00093
00094
00095 explicit KeyBase(std::string c) {
00096 str_= find_index(c);
00097 }
00098
00099
00100 #if !defined(IMP_DOXYGEN)
00101 explicit KeyBase(unsigned int i): str_(i) {
00102 IMP_INTERNAL_CHECK(str_ >= 0, "Invalid initializer " << i);
00103
00104 }
00105 #endif
00106
00107 static unsigned int add_key(std::string sc) {
00108 return IMP::internal::get_key_data(ID).add_key(sc);
00109 }
00110
00111
00112 static bool get_key_exists(std::string sc) {
00113 return get_map().find(sc) != get_map().end();
00114 }
00115
00116
00117 const std::string get_string() const {
00118 if (is_default()) return std::string("NULL");
00119 return get_string(str_);
00120
00121 }
00122
00123 IMP_COMPARISONS_1(str_);
00124
00125 void show(std::ostream &out = std::cout) const {
00126 out << "\"" << get_string() << "\"";
00127 }
00128
00129
00130
00131
00132
00133
00134
00135 static KeyBase<ID, LazyAdd> add_alias(KeyBase<ID, LazyAdd> old_key,
00136 std::string new_name) {
00137 IMP_INTERNAL_CHECK(get_map().find(new_name) == get_map().end(),
00138 "The name is already taken with an existing key or alias");
00139 IMP::internal::get_key_data(ID).add_alias(new_name, old_key.get_index());
00140 return KeyBase<ID, LazyAdd>(new_name.c_str());
00141 }
00142
00143 #ifndef DOXYGEN
00144 unsigned int get_index() const {
00145 IMP_INTERNAL_CHECK(!is_default(),
00146 "Cannot get index on defaultly constructed Key");
00147 return str_;
00148 }
00149 #endif
00150
00151
00152 static void show_all(std::ostream &out);
00153
00154
00155
00156
00157
00158 static std::vector<std::string> get_all_strings();
00159
00160
00161
00162
00163
00164
00165 static unsigned int get_number_unique() {
00166 return get_rmap().size();
00167 }
00168
00169 #ifndef SWIG
00170
00171
00172 This& operator++() {
00173 ++str_;
00174 return *this;
00175 }
00176 This& operator--() {
00177 --str_;
00178 return *this;
00179 }
00180 This operator+(int o) const {
00181 This c=*this;
00182 c.str_+= o;
00183 return c;
00184 }
00185 #endif
00186 };
00187
00188 #ifndef IMP_DOXYGEN
00189
00190 template <unsigned int ID, bool LA>
00191 std::ostream &operator<<(std::ostream &out, KeyBase<ID, LA> k) {
00192 k.show(out);
00193 return out;
00194 }
00195
00196 template <unsigned int ID, bool LA>
00197 inline bool KeyBase<ID, LA>::is_default() const
00198 {
00199 return str_==-1;
00200 }
00201
00202
00203 template <unsigned int ID, bool LA>
00204 inline void KeyBase<ID, LA>::show_all(std::ostream &out)
00205 {
00206 internal::get_key_data(ID).show(out);
00207 }
00208
00209 template <unsigned int ID, bool LA>
00210 std::vector<std::string> KeyBase<ID, LA>::get_all_strings()
00211 {
00212 std::vector<std::string> str;
00213 for (internal::KeyData::Map::const_iterator it= get_map().begin();
00214 it != get_map().end(); ++it) {
00215 str.push_back(it->first);
00216 }
00217 return str;
00218 }
00219 #endif
00220
00221 IMP_END_NAMESPACE
00222
00223 #endif