Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

DataEvent.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_DataEvent_h_
00003 #define INCLUDED_DataEvent_h_
00004 
00005 #include "Events/EventBase.h"
00006 #include <sstream>
00007 #include <libxml/tree.h>
00008 
00009 //! Event type for passing around data (or pointers to data).  In a state machine, use a SignalTrans to test for a specific data value and make the sid the address of the node posting the event.
00010 template<class T, int TID=-1>
00011 class DataEvent : public EventBase {
00012 public:
00013   //!@name Constructors
00014   //!
00015   DataEvent() : EventBase(), data() {}
00016   DataEvent(const T& d, EventGeneratorID_t gid, size_t sid, EventTypeID_t tid, unsigned int dur=0) : EventBase(gid,sid,tid,dur), data(d) {}
00017   DataEvent(const T& d, EventGeneratorID_t gid, size_t sid, EventTypeID_t tid, unsigned int dur, const std::string& n, float mag) : EventBase(gid,sid,tid,dur,n,mag), data(d) {}
00018 
00019   //! copy constructor
00020   DataEvent(const DataEvent& evt) : EventBase(evt), data(evt.data) {}
00021   
00022   //! assignment
00023   const DataEvent& operator=(const DataEvent& evt) { EventBase::operator=(evt); data=evt.data; return *this; }
00024 
00025   virtual EventBase* clone() const { return new DataEvent<T>(*this); }
00026   //@}
00027 
00028   void setData(const T& d) { data=d; } //!< assigns @a d to the internal #data
00029   const T& getData() const { return data; } //!< returns #data
00030   T& getData() { return data; } //!< returns #data
00031   
00032   inline static unsigned int encode(const T& x, char buf[], unsigned int cap) { if(cap<sizeof(T)) return 0; memcpy(buf,(const void*)&x,sizeof(x)); return sizeof(x); }
00033   inline static unsigned int decode(T& x, const char buf[], unsigned int cap) { if(cap<sizeof(T)) return 0; memcpy((void*)&x,buf,sizeof(x)); return sizeof(x); }
00034   
00035   virtual unsigned int getBinSize() const;
00036   virtual unsigned int loadBinaryBuffer(const char buf[], unsigned int len);
00037   virtual unsigned int saveBinaryBuffer(char buf[], unsigned int len) const;
00038   virtual void loadXML(xmlNode* node);
00039   virtual void saveXML(xmlNode * node) const;
00040   
00041   virtual classTypeID_t getClassTypeID() const { return autoRegisterDataEvent; }
00042 
00043   virtual void getDataFromString(std::stringstream &s);
00044   virtual void sendDataToString(std::stringstream &s) const;
00045 
00046 protected:
00047   T data; //!< the data being communicated
00048   
00049   //! this silliness is to work around parsing issue in gcc 3.3 branch
00050   static EventBase::classTypeID_t registerDataType(EventBase::classTypeID_t classid) {
00051 #if !defined(__GNUC__) || __GNUC__>3 || __GNUC__==3 && __GNUC_MINOR__>3
00052     // if here, using gcc 3.4 or later...
00053     // gcc 3.3 won't let me call this templated member function?!?!
00054     registry_t& reg = getTypeRegistry();
00055     return reg.registerType<DataEvent>(classid);
00056 #else // using gcc 3.3.x or prior
00057     // instead I have to wind up registering my own instance instead of using the FamilyFactory's instance generation
00058     return getTypeRegistry().registerFactory(classid,new EventBase::registry_t::FactoryType< DataEvent<T,TID> >);
00059 #endif
00060   }
00061   static const EventBase::classTypeID_t autoRegisterDataEvent; //!< causes class type id to automatically be regsitered with EventBase's FamilyFactory (getTypeRegistry())
00062 };
00063 
00064 #define DATAEVENT_IMPLEMENTATION(_abstract_type, _implementation) \
00065   template<> void DataEvent<_abstract_type, -1>::getDataFromString(std::stringstream &ss) \
00066    { _implementation x; ss >> x; data = (_abstract_type)x; } \
00067   template<> void DataEvent<_abstract_type, -1>::sendDataToString(std::stringstream &ss) const { ss << (_implementation)data; }
00068 
00069 #define DATAEVENT_IMPLEMENTATION_H(_abstract_type, _implementation) \
00070   template<> void DataEvent<_abstract_type, -1>::getDataFromString(std::stringstream &ss); \
00071   template<> void DataEvent<_abstract_type, -1>::sendDataToString(std::stringstream &ss) const;
00072 
00073 #define DATAEVENT_IMPLEMENTATION_CC(_abstract_type, _implementation) \
00074   template<> void DataEvent<_abstract_type, -1>::getDataFromString(std::stringstream &ss) \
00075    { _implementation x; ss >> x; data = (_abstract_type)x; } \
00076   template<> void DataEvent<_abstract_type, -1>::sendDataToString(std::stringstream &ss) const { ss << (_implementation)data; }
00077 
00078 
00079 //**************** IMPLEMENTATION ****************
00080 
00081 template<class T, int TID>
00082 const EventBase::classTypeID_t DataEvent<T,TID>::autoRegisterDataEvent=DataEvent<T,TID>::registerDataType(makeClassTypeID("DATA")+(TID<0?static_cast<EventBase::classTypeID_t>(getTypeRegistry().getNumTypes()):static_cast<EventBase::classTypeID_t>(TID)));
00083 
00084 template<class T, int TID>
00085 unsigned int DataEvent<T,TID>::getBinSize() const {
00086   unsigned int used=EventBase::getBinSize();
00087   if(saveFormat==XML)
00088     return used; //if using XML, the XMLLoadSave::getBinSize (called by EventBase::getBinSize) is all we need
00089   //otherwise need to add our own fields
00090   used+=creatorSize("EventBase::DataEvent");
00091   used+=getSerializedSize(data);
00092   return used;
00093 }
00094 
00095 template<class T, int TID>
00096 unsigned int DataEvent<T,TID>::loadBinaryBuffer(const char buf[], unsigned int len) {
00097   unsigned int origlen=len;
00098   if(!checkInc(EventBase::loadBinaryBuffer(buf,len),buf,len)) return 0;
00099   if(!checkCreatorInc("EventBase::DataEvent",buf,len,true)) return 0;
00100   unsigned int used = decode(data,buf,len);
00101   if(used==0) return 0; else { buf+=used; len-=used; }
00102   return origlen-len; 
00103 }
00104 
00105 template<class T, int TID>
00106 unsigned int DataEvent<T,TID>::saveBinaryBuffer(char buf[], unsigned int len) const {
00107   unsigned int origlen=len;
00108   if(!checkInc(EventBase::saveBinaryBuffer(buf,len),buf,len)) return 0;
00109   if(!saveCreatorInc("EventBase::DataEvent",buf,len)) return 0;
00110   unsigned int used = encode(data,buf,len);
00111   if(used==0) return 0; else { buf+=used; len-=used; }
00112   return origlen-len;
00113 }
00114 
00115 template<class T, int TID>
00116 void DataEvent<T,TID>::loadXML(xmlNode* node) {
00117   if(node==NULL)
00118     return;
00119 
00120   EventBase::loadXML(node);
00121   
00122   for(xmlNode* cur = skipToElement(node->children); cur!=NULL; cur = skipToElement(cur->next)) {
00123     if(xmlStrcmp(cur->name, (const xmlChar *)"param"))
00124       continue;
00125     
00126     xmlChar * name = xmlGetProp(cur,(const xmlChar*)"name");
00127     if(name==NULL)
00128       throw bad_format(cur,"property missing name");
00129     
00130     xmlChar * val = xmlGetProp(cur,(const xmlChar*)"value");
00131     if(val==NULL)
00132       throw bad_format(cur,"property missing value");
00133     
00134     //cout << "loadXML: " << name << "=" << val << endl;
00135     
00136     if(xmlStrcmp(name, (const xmlChar *)"data")==0) {
00137       std::stringstream ss((const char*)val);
00138       DataEvent<T,-1>::getDataFromString(ss);
00139       xmlFree(val);
00140       xmlFree(name);
00141     }
00142   }
00143 }
00144 
00145 template<class T, int TID>
00146 void DataEvent<T,TID>::getDataFromString(std::stringstream&) {
00147   std::cout << "DataEvent failure: don't know how to read data of this type." << std::endl;
00148 }
00149 
00150 template<> void DataEvent<unsigned char, -1>::getDataFromString(std::stringstream &ss);
00151 template<> void DataEvent<unsigned short int, -1>::getDataFromString(std::stringstream &ss);
00152 template<> void DataEvent<unsigned int, -1>::getDataFromString(std::stringstream &ss);
00153 template<> void DataEvent<int, -1>::getDataFromString(std::stringstream &ss);
00154 template<> void DataEvent<float, -1>::getDataFromString(std::stringstream &ss);
00155 template<> void DataEvent<double, -1>::getDataFromString(std::stringstream &ss);
00156 
00157 template<class T, int TID>
00158 void DataEvent<T,TID>::sendDataToString(std::stringstream&) const {
00159   std::cout << "DataEvent failure: don't know how to encode data of this type as a string." << std::endl;
00160 }
00161 
00162 template<> void DataEvent<unsigned char, -1>::sendDataToString(std::stringstream &ss) const;
00163 template<> void DataEvent<unsigned short int, -1>::sendDataToString(std::stringstream &ss) const;
00164 template<> void DataEvent<unsigned int, -1>::sendDataToString(std::stringstream &ss) const;
00165 template<> void DataEvent<int, -1>::sendDataToString(std::stringstream &ss) const;
00166 template<> void DataEvent<float, -1>::sendDataToString(std::stringstream &ss) const;
00167 template<> void DataEvent<double, -1>::sendDataToString(std::stringstream &ss) const;
00168 
00169 template<class T, int TID>
00170 void DataEvent<T,TID>::saveXML(xmlNode* node) const {
00171   if(node==NULL)
00172     return;
00173   EventBase::saveXML(node);
00174   
00175   //clear old params first
00176   for(xmlNode* cur = skipToElement(node->children); cur!=NULL; ) {
00177     if(xmlStrcmp(cur->name, (const xmlChar *)"param")==0) {
00178       xmlUnlinkNode(cur);
00179       xmlFreeNode(cur);
00180       cur = skipToElement(node->children); //restart the search (boo)
00181     } else
00182       cur = skipToElement(cur->next);
00183   }
00184   
00185   // write new params
00186   xmlNode* cur=xmlNewChild(node,NULL,(const xmlChar*)"param",NULL); \
00187   if(cur==NULL)               \
00188     throw bad_format(node,"Error: DataEvent xml error on saving param"); \
00189   xmlSetProp(cur,(const xmlChar*)"name",(const xmlChar*)"data");    \
00190   std::stringstream ss;
00191   DataEvent<T,-1>::sendDataToString(ss);
00192   xmlSetProp(cur,(const xmlChar*)"value",(const xmlChar*)ss.str().c_str());
00193 }
00194 
00195 /*! @file
00196  * @brief Defines DataEvent, for passing around data (or pointers to data)
00197  * @author ejt (Creator)
00198  */
00199 
00200 #endif

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:37 2016 by Doxygen 1.6.3