00001 /* SimData: Data Infrastructure for Simulations 00002 * Copyright (C) 2002 Mark Rose <tm2@stm.lbl.gov> 00003 * 00004 * This file is part of SimData. 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00019 */ 00020 00021 00027 #ifndef __SIMDATA_OBJECTINTERFACE_H__ 00028 #define __SIMDATA_OBJECTINTERFACE_H__ 00029 00030 00031 #include <string> 00032 #include <vector> 00033 00034 #include <SimData/hash_map.h> 00035 #include <SimData/TypeAdapter.h> 00036 #include <SimData/Namespace.h> 00037 #include <SimData/Archive.h> 00038 00039 /* 00040 * Simulated Partial Template Specialization 00041 * 00042 * Adapted from: metactrl.h 00043 * by Krzysztof Czarnecki & Ulrich Eisenecker 00044 */ 00045 #include <SimData/PTS.h> 00046 00047 00048 00049 NAMESPACE_SIMDATA 00050 00051 00052 class Object; 00053 00054 00055 SIMDATA_EXCEPTION(InterfaceError) 00056 00057 00058 00059 00064 class MemberAccessorBase 00065 { 00066 public: 00067 virtual ~MemberAccessorBase() {} 00068 00069 typedef HASH_MAPS<std::string, MemberAccessorBase *, hashstring, eqstring>::Type map; 00070 00071 00072 virtual void set(Object *, TypeAdapter const &) throw(TypeMismatch) { 00073 throw TypeMismatch("Cannot set vector<> '" + name + "' directly, use push_back() instead."); 00074 } 00075 virtual void push_back(Object *, TypeAdapter const &) throw(TypeMismatch) { 00076 throw TypeMismatch("Cannot call push_back() on non-vector<> variable '" + name + "'."); 00077 } 00078 virtual void clear(Object *) throw(TypeMismatch) { 00079 throw TypeMismatch("Cannot call clear() on non-vector<> variable '" + name + "'."); 00080 } 00081 virtual TypeAdapter const get(Object *) const throw(TypeMismatch) { 00082 throw TypeMismatch("get() '" + name + "': not supported for variables of type vector<>."); 00083 } 00084 bool isRequired() const { return required; }; 00085 std::string getName() const { return name; } 00086 virtual void pack(Object *, Packer &) const { 00087 assert(0); 00088 } 00089 virtual void unpack(Object *, UnPacker &) { 00090 assert(0); 00091 } 00092 std::string getType() const { return type; } 00093 virtual unsigned int getMask() const { return 0; } 00094 protected: 00095 void setType(BaseType &x) { type = x.typeString(); } 00096 void setType(double &x) { type = "builtin::double"; } 00097 void setType(float &x) { type = "builtin::float"; } 00098 void setType(unsigned int &x) { type = "builtin::uint"; } 00099 void setType(int &x) { type = "builtin::int"; } 00100 void setType(unsigned char &x) { type = "builtin::uint8"; } 00101 void setType(char &x) { type = "builtin::int8"; } 00102 void setType(unsigned short &x) { type = "builtin::uint16"; } 00103 void setType(short &x) { type = "builtin::int16"; } 00104 void setType(bool &x) { type = "builtin::bool"; } 00105 void setType(std::string const &x) { type = "builtin::string"; } 00106 MemberAccessorBase(): type("none") {} 00107 std::string name; 00108 std::string help; 00109 std::string type; 00110 bool required; 00111 }; 00112 00113 00119 template <class C, typename T> 00120 class MemberMaskAccessor: public MemberAccessorBase 00121 { 00122 T C::* member; 00123 T mask; 00124 public: 00125 MemberMaskAccessor(T C::*pm, std::string name_, int mask_, bool required_) { 00126 member = pm; 00127 name = name_; 00128 mask = mask_; 00129 required = required_; 00130 { 00131 T prototype; 00132 setType(prototype); 00133 } 00134 } 00135 virtual TypeAdapter const get(Object *o) const throw(TypeMismatch) { 00136 C * object = dynamic_cast<C *>(o); 00137 if (object == NULL) { 00138 throw TypeMismatch("get(\"" + name + "\"): Object class does not match interface."); 00139 } 00140 return TypeAdapter(object->*member); 00141 } 00142 virtual void set(Object *o, TypeAdapter const &v) throw(TypeMismatch) { 00143 C * object = dynamic_cast<C *>(o); 00144 if (object == NULL) { 00145 throw TypeMismatch("set(\"" + name + "\"): Object class does not match interface."); 00146 } 00147 try { 00148 if (mask != 0) { 00149 T value; 00150 v.set(value); 00151 if (value != 0) { 00152 object->*member |= mask; 00153 } else { 00154 object->*member &= ~mask; 00155 } 00156 } else { 00157 v.set(object->*member); 00158 } 00159 } catch (Exception &e) { 00160 e.addMessage("MemberMaskAccessor::set(" + name + "):"); 00161 throw; 00162 } 00163 } 00164 virtual void pack(Object *o, Packer &p) const { 00165 C * object = dynamic_cast<C *>(o); 00166 p(object->*member); 00167 } 00168 virtual void unpack(Object *o, UnPacker &p) { 00169 C * object = dynamic_cast<C *>(o); 00170 p(object->*member); 00171 } 00172 virtual unsigned int getMask() const { return static_cast<unsigned int>(mask); } 00173 }; 00174 00175 00181 template <class C, typename T> 00182 class MemberAccessor: public MemberAccessorBase 00183 { 00184 T C::* member; 00185 public: 00186 MemberAccessor(T C::*pm, std::string name_, bool required_) { 00187 member = pm; 00188 name = name_; 00189 required = required_; 00190 { 00191 T prototype; 00192 setType(prototype); 00193 } 00194 } 00195 virtual TypeAdapter const get(Object *o) const throw(TypeMismatch) { 00196 C * object = dynamic_cast<C *>(o); 00197 if (object == NULL) { 00198 throw TypeMismatch("get(\"" + name + "\"): Object class does not match interface."); 00199 } 00200 return TypeAdapter(object->*member); 00201 } 00202 virtual void set(Object *o, TypeAdapter const &v) throw(TypeMismatch) { 00203 C * object = dynamic_cast<C *>(o); 00204 if (object == NULL) { 00205 throw TypeMismatch("set(\"" + name + "\"): Object class does not match interface."); 00206 } 00207 try { 00208 v.set(object->*member); 00209 } catch (Exception &e) { 00210 e.addMessage("MemberAccessor::set(" + name + "):"); 00211 throw; 00212 } 00213 } 00214 virtual void pack(Object *o, Packer &p) const { 00215 C * object = dynamic_cast<C *>(o); 00216 p(object->*member); 00217 } 00218 virtual void unpack(Object *o, UnPacker &p) { 00219 C * object = dynamic_cast<C *>(o); 00220 p(object->*member); 00221 } 00222 }; 00223 00224 00230 #ifdef __SIMDATA_PTS_SIM 00231 template <class C, typename T> 00232 class VectorMemberAccessor: public MemberAccessorBase 00233 { 00234 T C::* member; 00235 public: 00236 VectorMemberAccessor(T C::*pm, std::string name_, bool required_) { 00237 member = pm; 00238 name = name_; 00239 required = required_; 00240 { 00241 T prototype; 00242 setType(prototype); 00243 type = "vector::" + type; 00244 } 00245 } 00246 virtual void push_back(Object *o, TypeAdapter const &v) throw(TypeMismatch) { 00247 C * object = dynamic_cast<C *>(o); 00248 if (object == NULL) { 00249 throw TypeMismatch("push_back(\"" + name + "\"): Object class does not match interface."); 00250 } 00251 typename T::value_type value; 00252 try { 00253 v.set(value); 00254 } catch (Exception &e) { 00255 e.addMessage("VectorMemberAccessor::push_back(" + name + "):"); 00256 throw; 00257 } 00258 (object->*member).push_back(value); 00259 } 00260 virtual void clear(Object *o) throw(TypeMismatch) { 00261 C * object = dynamic_cast<C *>(o); 00262 if (object == NULL) { 00263 throw TypeMismatch("push_back(\"" + name + "\"): Object class does not match interface."); 00264 } 00265 (object->*member).clear(); 00266 } 00267 virtual void pack(Object *o, Packer &p) const { 00268 C * object = dynamic_cast<C *>(o); 00269 T &m = object->*member; 00270 int n = static_cast<int>(m.size()); 00271 p(n); 00272 typename T::iterator idx; 00273 for (idx = m.begin(); idx != m.end(); idx++) { 00274 p(*idx); 00275 } 00276 } 00277 virtual void unpack(Object *o, UnPacker &p) { 00278 C * object = dynamic_cast<C *>(o); 00279 T &m = object->*member; 00280 typename T::value_type temp; 00281 int n; 00282 p(n); 00283 while (--n >= 0) { 00284 p(temp); 00285 m.push_back(temp); 00286 } 00287 } 00288 }; 00289 00290 #else // #if !defined(__SIMDATA_PTS_SIM) 00291 template <class C, typename T> 00292 class MemberAccessor< C, std::vector<T> >: public MemberAccessorBase 00293 { 00294 std::vector<T> C::* member; 00295 public: 00296 MemberAccessor(std::vector<T> C::*pm, std::string name_, bool required_) { 00297 member = pm; 00298 name = name_; 00299 required = required_; 00300 { 00301 T prototype; 00302 setType(prototype); 00303 type = "vector::" + type; 00304 } 00305 } 00306 virtual void push_back(Object *o, TypeAdapter const &v) throw(TypeMismatch) { 00307 C * object = dynamic_cast<C *>(o); 00308 if (object == NULL) { 00309 throw TypeMismatch("push_back(\"" + name + "\"): Object class does not match interface."); 00310 } 00311 T value; 00312 try { 00313 v.set(value); 00314 } catch (Exception &e) { 00315 e.addMessage("MemberAccessor::push_back(" + name + "):"); 00316 throw; 00317 } 00318 (object->*member).push_back(value); 00319 } 00320 virtual void clear(Object *o) throw(TypeMismatch) { 00321 C * object = dynamic_cast<C *>(o); 00322 if (object == NULL) { 00323 throw TypeMismatch("push_back(\"" + name + "\"): Object class does not match interface."); 00324 } 00325 (object->*member).clear(); 00326 } 00327 virtual void pack(Object *o, Packer &p) const { 00328 C * object = dynamic_cast<C *>(o); 00329 std::vector<T> &m = object->*member; 00330 int n = static_cast<int>(m.size()); 00331 p(n); 00332 typename std::vector<T>::iterator idx; 00333 for (idx = m.begin(); idx != m.end(); ++idx) { 00334 p(*idx); 00335 } 00336 } 00337 virtual void unpack(Object *o, UnPacker &p) { 00338 C * object = dynamic_cast<C *>(o); 00339 std::vector<T> &m = object->*member; 00340 T temp; 00341 int n; 00342 p(n); 00343 m.reserve(n); 00344 while (--n >= 0) { 00345 p(temp); 00346 m.push_back(temp); 00347 } 00348 } 00349 }; 00350 00356 template <class C> 00357 class MemberAccessor< C, int >: public MemberMaskAccessor<C, int> { 00358 public: 00359 MemberAccessor(int C::*pm, std::string name_, bool required_): 00360 MemberMaskAccessor<C, int>(pm, name_, 0, required_) { } 00361 MemberAccessor(int C::*pm, std::string name_, int mask_, bool required_): 00362 MemberMaskAccessor<C, int>(pm, name_, mask_, required_) { } 00363 }; 00364 00370 template <class C> 00371 class MemberAccessor< C, short >: public MemberMaskAccessor<C, short> { 00372 public: 00373 MemberAccessor(short C::*pm, std::string name_, bool required_): 00374 MemberMaskAccessor<C, short>(pm, name_, 0, required_) { } 00375 MemberAccessor(short C::*pm, std::string name_, int mask_, bool required_): 00376 MemberMaskAccessor<C, short>(pm, name_, mask_, required_) { } 00377 }; 00378 00384 template <class C> 00385 class MemberAccessor< C, char >: public MemberMaskAccessor<C, char> { 00386 public: 00387 MemberAccessor(char C::*pm, std::string name_, bool required_): 00388 MemberMaskAccessor<C, char>(pm, name_, 0, required_) { } 00389 MemberAccessor(char C::*pm, std::string name_, int mask_, bool required_): 00390 MemberMaskAccessor<C, char>(pm, name_, mask_, required_) { } 00391 }; 00392 00393 #endif // !defined(__SIMDATA_PTS_SIM) 00394 00395 00396 #ifdef __SIMDATA_PTS_SIM 00397 00413 namespace PTS { 00414 00415 template <typename T> 00416 char IsVector(std::vector<T> const *); // no implementation is required 00417 00418 int IsVector(BaseType const *); // no implementation is required 00419 int IsVector(float const *); // no implementation is required 00420 int IsVector(double const *); // no implementation is required 00421 int IsVector(int const *); // no implementation is required 00422 int IsVector(bool const*); // no implementation is required 00423 int IsVector(char const*); // no implementation is required 00424 int IsVector(short const*); // no implementation is required 00425 int IsVector(std::string const*);// no implementation is required 00426 int IsVector(TypeAdapter const *);// no implementation is required 00427 00428 template <typename T> 00429 struct ISVECTOR { 00430 enum { RET = (sizeof(IsVector((T*)0)) == 1) }; 00431 }; 00432 00433 template <class C, typename T> 00434 struct SELECT_ACCESSOR { 00435 typedef typename meta::IF<ISVECTOR<T>::RET, 00436 simdata::VectorMemberAccessor<C, T>, simdata::MemberAccessor<C, T> >::RET ACCESSOR; 00437 }; 00438 } 00439 00440 #endif // __SIMDATA_PTS_SIM 00441 00442 00448 class ObjectInterfaceBase { 00449 public: 00450 virtual ~ObjectInterfaceBase() {} 00451 00457 virtual bool variableExists(std::string const &name) const = 0; 00458 00464 virtual bool variableRequired(std::string const &name) const = 0; 00465 00470 virtual std::string variableType(std::string const &name) const = 0; 00471 00474 virtual std::vector<std::string> getVariableNames() const = 0; 00475 00478 virtual std::vector<std::string> getRequiredNames() const = 0; 00479 00482 virtual const TypeAdapter get(Object *o, std::string const &name) const = 0; 00483 00486 virtual void set(Object *o, std::string const &name, const TypeAdapter &v) const = 0; 00487 00490 virtual void push_back(Object *o, std::string const &name, const TypeAdapter &v) const = 0; 00491 00494 virtual void clear(Object *o, std::string const &name) const = 0; 00495 }; 00496 00497 00503 template <class C> 00504 class ObjectInterface: public ObjectInterfaceBase { 00505 00506 typedef ObjectInterface<C> Self; 00507 MemberAccessorBase::map table; 00508 00509 void __not_found(std::string const &name) const throw (InterfaceError) { 00510 throw InterfaceError("Variable '"+name+"' not found in interface to class '" + C::_getClassName()+"'"); 00511 } 00512 00513 MemberAccessorBase *getAccessor(std::string const &name) const { 00514 MemberAccessorBase::map::const_iterator idx = table.find(name); 00515 if (idx == table.end()) return 0; 00516 return idx->second; 00517 } 00518 00519 public: 00520 ObjectInterface() {} 00521 virtual ~ObjectInterface() {} 00522 00529 template<typename T> 00530 Self& def(std::string const &name, T C::*pm, bool required) throw(InterfaceError) { 00531 if (variableExists(name)) throw InterfaceError("interface variable \"" + std::string(name) + "\" multiply defined in class '" + C::_getClassName() + "'."); 00532 #ifdef __SIMDATA_PTS_SIM 00533 table[name] = new typename PTS::SELECT_ACCESSOR<C, T>::ACCESSOR(pm, name, required); 00534 #else 00535 table[name] = new MemberAccessor<C, T>(pm, name, required); 00536 #endif 00537 return *this; 00538 } 00539 template<typename T> 00540 Self& def(std::string const &name, T C::*pm, int mask, bool required) throw(InterfaceError) { 00541 if (variableExists(name)) throw InterfaceError("interface variable \"" + std::string(name) + "\" multiply defined in class '" + C::_getClassName() + "'."); 00542 #ifdef __SIMDATA_PTS_SIM 00543 table[name] = new typename PTS::SELECT_ACCESSOR<C, T>::ACCESSOR(pm, name, required); 00544 #else 00545 table[name] = new MemberAccessor<C, T>(pm, name, mask, required); 00546 #endif 00547 return *this; 00548 } 00549 00550 inline Self& pass() { return *this; } 00551 00557 virtual bool variableExists(std::string const &name) const { 00558 return table.find(name) != table.end(); 00559 } 00560 00566 virtual bool variableRequired(std::string const &name) const { 00567 MemberAccessorBase::map::const_iterator idx = table.find(name); 00568 if (idx == table.end()) return false; 00569 return idx->second->isRequired(); 00570 } 00571 00576 virtual std::string variableType(std::string const &name) const { 00577 MemberAccessorBase::map::const_iterator idx = table.find(name); 00578 if (idx == table.end()) __not_found(name); 00579 return idx->second->getType(); 00580 } 00581 00584 virtual std::vector<std::string> getVariableNames() const { 00585 std::vector<std::string> names; 00586 MemberAccessorBase::map::const_iterator idx; 00587 for (idx = table.begin(); idx != table.end(); idx++) { 00588 names.push_back(idx->first); 00589 } 00590 return names; 00591 } 00592 00595 virtual std::vector<std::string> getRequiredNames() const { 00596 std::vector<std::string> names; 00597 MemberAccessorBase::map::const_iterator idx; 00598 for (idx = table.begin(); idx != table.end(); idx++) { 00599 if (idx->second->isRequired()) { 00600 names.push_back(idx->first); 00601 } 00602 } 00603 return names; 00604 } 00605 00608 virtual const TypeAdapter get(Object *o, std::string const &name) const { 00609 return getAccessor(name)->get(o); 00610 } 00611 00614 virtual void set(Object *o, std::string const &name, const TypeAdapter &v) const { 00615 getAccessor(name)->set(o, v); 00616 } 00617 00620 virtual void push_back(Object *o, std::string const &name, const TypeAdapter &v) const { 00621 getAccessor(name)->push_back(o, v); 00622 } 00623 00626 virtual void clear(Object *o, std::string const &name) const { 00627 getAccessor(name)->clear(o); 00628 } 00629 00630 private: 00631 // These methods are currently in limbo. Minimally they should be 00632 // updated to use serialize(Archive&), but the usefulness of this 00633 // feature is still in doubt. 00634 virtual void pack(Object *o, Packer &p) const { 00635 MemberAccessorBase::map::const_iterator idx; 00636 for (idx = table.begin(); idx != table.end(); ++idx) { 00637 idx->second->pack(o, p); 00638 } 00639 } 00640 00641 virtual void unpack(Object *o, UnPacker &p) const { 00642 MemberAccessorBase::map::const_iterator idx; 00643 for (idx = table.begin(); idx != table.end(); ++idx) { 00644 idx->second->unpack(o, p); 00645 } 00646 } 00647 }; 00648 00649 00650 NAMESPACE_SIMDATA_END 00651 00652 00653 #endif // __SIMDATA_OBJECTINTERFACE_H__ 00654
|
SimData version pre-0.4.0. For more information on SimData, visit the SimData Homepage. Generated on Tue Oct 14 12:06:39 2003, using Doxygen 1.2.18. |