00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef ACEDIA_TUPLE_H
00031 #define ACEDIA_TUPLE_H
00032
00033 #include "any.hpp"
00034 #include "anyarray.hpp"
00035 #include "metaclass.hpp"
00036 #include "metaclassimpl.hpp"
00037 #include "acedia_details.hpp"
00038 #include "referencecounted.hpp"
00039 #include "rulebuilder.hpp"
00040 #include "actorref.hpp"
00041
00042 #include <boost/archive/text_oarchive.hpp>
00043 #include <boost/archive/text_iarchive.hpp>
00044
00045 #include "acedia_preprocessor.hpp"
00046
00047 #define ACEDIA_TUPLE_DATA_NAME(num) BOOST_PP_CAT(Tuple,BOOST_PP_CAT(num, Data))
00048 #define ACEDIA_DECL_TUPLE_MEMBER(z, i, unused) const Any BOOST_PP_CAT(_, BOOST_PP_ADD(1, i));
00049
00050 #define ACEDIA_INIT_TUPLE_MEMBER_X(x) BOOST_PP_CAT(_,x) ( new details::AnyValImpl< BOOST_PP_CAT(T,x) > ( BOOST_PP_CAT(v,x) ) )
00051 #define ACEDIA_INIT_TUPLE_MEMBER(z, i, unused) BOOST_PP_COMMA_IF(i) ACEDIA_INIT_TUPLE_MEMBER_X(BOOST_PP_ADD(1,i))
00052
00053 #define ACEDIA_DEFAULT_INIT_MEMBER(z, i, unused) , BOOST_PP_CAT(_, BOOST_PP_ADD(1, i)) ( Any::from(BOOST_PP_CAT(T, BOOST_PP_ADD(1, i)) () ) )
00054
00055 #define ACEDIA_COPY_TUPLE_MEMBER_X(x) BOOST_PP_CAT(_,x) ( other.BOOST_PP_CAT(_,x) )
00056 #define ACEDIA_COPY_TUPLE_MEMBER(z, i, unused) BOOST_PP_COMMA_IF(i) ACEDIA_COPY_TUPLE_MEMBER_X(BOOST_PP_ADD(1,i))
00057
00058 #define ACEDIA_SERIALIZE_MEBER(z, i, where) where << BOOST_PP_CAT(_,BOOST_PP_ADD(1,i)) . uncheckedValue< BOOST_PP_CAT(T,BOOST_PP_ADD(1,i)) >();
00059
00060 #define ACEDIA_DESERIALIZE_VAL(z, i, from) BOOST_PP_CAT(T,BOOST_PP_ADD(1,i)) BOOST_PP_CAT(val, i) ; from >> BOOST_PP_CAT(val, i) ;
00061 #define ACEDIA_GET_DESERIALIZED_VAL(z, i, unused) BOOST_PP_COMMA_IF(i) BOOST_PP_CAT(val, i)
00062
00063 #define ACEDIA_CHECK_MEMBER(z, i, unused) BOOST_PP_IF(i, &&, BOOST_PP_EMPTY()) BOOST_PP_CAT(_,BOOST_PP_ADD(1,i)) == other.BOOST_PP_CAT(_,BOOST_PP_ADD(1,i))
00064 #define ACEDIA_ADD_ANY_GETTER(z, i, unused) case i : return BOOST_PP_CAT(_,BOOST_PP_ADD(1,i)) ;
00065
00066 #define ACEDIA_DECL_TUPLE_DATA_CLASS(num) \
00067 template< ACEDIA_DEF_T1_TO_TX(num) > \
00068 struct ACEDIA_TUPLE_DATA_NAME(num) : public TupleDataBase { \
00069 BOOST_PP_REPEAT(num, ACEDIA_DECL_TUPLE_MEMBER, _) \
00070 ACEDIA_TUPLE_DATA_NAME(num) ( ACEDIA_GET_T1_TO_TX_ARG_LIST(num) ) : \
00071 TupleDataBase(), \
00072 BOOST_PP_REPEAT(num, ACEDIA_INIT_TUPLE_MEMBER, _) { } \
00073 ACEDIA_TUPLE_DATA_NAME(num) ( const ACEDIA_TUPLE_DATA_NAME(num) &other) : \
00074 TupleDataBase(), \
00075 BOOST_PP_REPEAT(num, ACEDIA_COPY_TUPLE_MEMBER, _) { } \
00076 ACEDIA_TUPLE_DATA_NAME(num) (): TupleDataBase() \
00077 BOOST_PP_REPEAT(num, ACEDIA_DEFAULT_INIT_MEMBER, _) { } \
00078 static ACEDIA_TUPLE_DATA_NAME(num) *dummy() { \
00079 static ACEDIA_TUPLE_DATA_NAME(num) stupid_dummy; \
00080 return &stupid_dummy; \
00081 } \
00082 void serialize(boost::archive::text_oarchive &ar,const unsigned int) const{\
00083 BOOST_PP_REPEAT(num, ACEDIA_SERIALIZE_MEBER, ar) \
00084 } \
00085 static ACEDIA_TUPLE_DATA_NAME(num) *deserialize( \
00086 boost::archive::text_iarchive &ar, const unsigned int) \
00087 { \
00088 BOOST_PP_REPEAT(num, ACEDIA_DESERIALIZE_VAL, ar) \
00089 return new ACEDIA_TUPLE_DATA_NAME(num) ( \
00090 BOOST_PP_REPEAT(num, ACEDIA_GET_DESERIALIZED_VAL, _) \
00091 ); \
00092 } \
00093 bool operator==(const ACEDIA_TUPLE_DATA_NAME(num) &other) const { \
00094 return BOOST_PP_REPEAT(num, ACEDIA_CHECK_MEMBER, _); \
00095 } \
00096 virtual unsigned int length() const { return num ; } \
00097 virtual const Any &at(unsigned int pos) const \
00098 { \
00099 switch (pos) { BOOST_PP_REPEAT(num, ACEDIA_ADD_ANY_GETTER, _) } \
00100 throw IndexOutOfBoundsException("Tuple out of bounds"); \
00101 } \
00102 }
00103
00104 #define ACEDIA_DECL_TUPLE_GETTER(num) \
00105 template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I> \
00106 class Getter< num ,A,B,C,D,E,F,G,H,I> { public: \
00107 template<typename T> inline static const typename util::ResultOf< num ,A,B,C,D,E,F,G,H,I>::type &get(const T *t) { const Any &any = t -> BOOST_PP_CAT(_,BOOST_PP_ADD(1,num)) ; return any.uncheckedValue<typename util::ResultOf< num ,A,B,C,D,E,F,G,H,I>::type>(); } \
00108 }
00109
00110 namespace acedia
00111 {
00112 namespace details
00113 {
00114 template<int N, typename A, typename B = void, typename C = void,
00115 typename D = void, typename E = void, typename F = void,
00116 typename G = void, typename H = void, typename I = void>
00117 class Getter { };
00118
00119 ACEDIA_DECL_TUPLE_GETTER(0);
00120 ACEDIA_DECL_TUPLE_GETTER(1);
00121 ACEDIA_DECL_TUPLE_GETTER(2);
00122 ACEDIA_DECL_TUPLE_GETTER(3);
00123 ACEDIA_DECL_TUPLE_GETTER(4);
00124 ACEDIA_DECL_TUPLE_GETTER(5);
00125 ACEDIA_DECL_TUPLE_GETTER(6);
00126 ACEDIA_DECL_TUPLE_GETTER(7);
00127 ACEDIA_DECL_TUPLE_GETTER(8);
00128
00129 struct TupleDataBase : public ReferenceCounted
00130 {
00131 TupleDataBase();
00132
00133 virtual ~TupleDataBase();
00134
00135 MetaClass *metaClassAt(unsigned int pos) const;
00136
00137 virtual unsigned int length() const = 0;
00138
00139 virtual const Any &at(unsigned int pos) const = 0;
00140 };
00141
00142 ACEDIA_DECL_TUPLE_DATA_CLASS(1);
00143 ACEDIA_DECL_TUPLE_DATA_CLASS(2);
00144 ACEDIA_DECL_TUPLE_DATA_CLASS(3);
00145 ACEDIA_DECL_TUPLE_DATA_CLASS(4);
00146 ACEDIA_DECL_TUPLE_DATA_CLASS(5);
00147 ACEDIA_DECL_TUPLE_DATA_CLASS(6);
00148 ACEDIA_DECL_TUPLE_DATA_CLASS(7);
00149 ACEDIA_DECL_TUPLE_DATA_CLASS(8);
00150 ACEDIA_DECL_TUPLE_DATA_CLASS(9);
00151
00152 }
00153
00160 class Tuple : public AnyArray
00161 {
00162
00163 protected:
00164
00165 details::TupleDataBase *m_data;
00166
00167 public:
00168
00169 Tuple(details::TupleDataBase *data);
00170
00171 virtual ~Tuple();
00172
00173 inline const details::TupleDataBase *dataBasePointer() const { return m_data; }
00174
00180 virtual const Any &at(boost::uint32_t pos) const;
00181
00186 virtual boost::uint32_t length() const;
00187
00188 virtual bool isTuple() const;
00189
00190 virtual const char *elementNameAt(int i) const = 0;
00191
00192 virtual const Any asAny() const = 0;
00193
00194 inline operator Any() const { return asAny(); }
00195
00196 };
00197
00198
00199
00200
00201 template<int N, typename T1, typename T2 = void, typename T3 = void, typename T4 = void, typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void, typename T9 = void>
00202 struct TupleBase : public Tuple
00203 {
00204
00205 typedef typename util::ResultOf
00206 <N,
00207 Unit,
00208 details::Tuple1Data<T1>,
00209 details::Tuple2Data<T1,T2>,
00210 details::Tuple3Data<T1,T2,T3>,
00211 details::Tuple4Data<T1,T2,T3,T4>,
00212 details::Tuple5Data<T1,T2,T3,T4,T5>,
00213 details::Tuple6Data<T1,T2,T3,T4,T5,T6>,
00214 details::Tuple7Data<T1,T2,T3,T4,T5,T6,T7>,
00215 details::Tuple8Data<T1,T2,T3,T4,T5,T6,T7,T8>,
00216 details::Tuple9Data<T1,T2,T3,T4,T5,T6,T7,T8,T9>
00217 >::type
00218 Data;
00219
00220 inline const Data *m_d() const { return reinterpret_cast<const Data*>(m_data); }
00221
00222 TupleBase() : Tuple(Data::dummy()) { this->m_data->ref(); }
00223
00224 TupleBase(Data *data) : Tuple(data) { }
00225
00226 template<int GET_N>
00227 inline const typename util::ResultOf<GET_N,T1,T2,T3,T4,T5,T6,T7,T8,T9>::type &get() const
00228 {
00229 return details::Getter<GET_N,T1,T2,T3,T4,T5,T6,T7,T8,T9>::get(this->m_d());
00230 }
00231
00232 void serialize(boost::archive::text_iarchive &ar, const unsigned int unused)
00233 {
00234 Data *nd = Data::deserialize(ar, unused);
00235 if (!m_data->deref()) delete m_data;
00236 m_data = nd;
00237 }
00238
00239 void serialize(boost::archive::text_oarchive &ar, const unsigned int version)
00240 {
00241 m_d()->serialize(ar, version);
00242 }
00243
00244 };
00245
00246 namespace details
00247 {
00248
00249
00250
00251 template<int N, class TTuple, ACEDIA_DEF_WITH_DEFAULT_T1_TO_T9()>
00252 struct Unboxer : public AnyArrayProcessor
00253 {
00254
00255 typedef typename util::ResultOf
00256 <N,
00257 Unit,
00258 TupleBase<1,T1>,
00259 TupleBase<2,T1,T2>,
00260 TupleBase<3,T1,T2,T3>,
00261 TupleBase<4,T1,T2,T3,T4>,
00262 TupleBase<5,T1,T2,T3,T4,T5>,
00263 TupleBase<6,T1,T2,T3,T4,T5,T6>,
00264 TupleBase<7,T1,T2,T3,T4,T5,T6,T7>,
00265 TupleBase<8,T1,T2,T3,T4,T5,T6,T7,T8>,
00266 TupleBase<9,T1,T2,T3,T4,T5,T6,T7,T8,T9>
00267 >::type
00268 TTupleBase;
00269
00270 Unboxer() { }
00271
00272 explicit Unboxer(AnyArrayProcessor *next) { setNext(next); }
00273
00274 virtual bool operator()(const AnyArray &arr)
00275 {
00276 const TTupleBase &inner = arr.uncheckedValueAt<TTuple>(0);
00277 return hasNext() && (*next)(inner);
00278 }
00279
00280 virtual ContinuationInvoker *matchingInvoker(const AnyArray &arr)
00281 {
00282 if (hasNext())
00283 {
00284 const TTupleBase &inner = arr.uncheckedValueAt<TTuple>(0);
00285 return next->matchingInvoker(inner);
00286 }
00287 return NULL;
00288 }
00289 };
00290 }
00291
00292 }
00293
00294
00295
00296 #define ACEDIA_DECLARE_CASE_TUPLEX(seq, x, mt1, mt2, mt3, mt4, mt5, mt6, mt7, mt8, mt9, an1, an2, an3, an4, an5, an6, an7, an8, an9) \
00297 ACEDIA_OPEN_NAMESPACES_BY(seq) \
00298 struct ACEDIA_SEQ_LAST(seq) : \
00299 public acedia::TupleBase \
00300 <x, ACEDIA_FIRST_N(x,mt1,mt2,mt3,mt4,mt5,mt6,mt7,mt8,mt9) > \
00301 { \
00302 typedef acedia::TupleBase \
00303 <x, ACEDIA_FIRST_N(x,mt1,mt2,mt3,mt4,mt5,mt6,mt7,mt8,mt9) > Base; \
00304 inline ACEDIA_SEQ_LAST(seq) () : Base() { } \
00305 ACEDIA_SEQ_LAST(seq) ( const ACEDIA_SEQ_LAST(seq) &other ) : \
00306 Base(reinterpret_cast<Base::Data*>(other.m_data)) { m_data->ref();}\
00307 inline ACEDIA_SEQ_LAST(seq) \
00308 ( ACEDIA_ARG_LIST_FIRST_N(x,mt1,mt2,mt3,mt4,mt5,mt6,mt7,mt8,mt9) ) \
00309 : Base ( new Base::Data ( ACEDIA_GET_V1_TO_VX(x) ) ) { } \
00310 ACEDIA_NAMED_GETTER_IF(x, 0, mt1, an1) \
00311 ACEDIA_NAMED_GETTER_IF(x, 1, mt2, an2) \
00312 ACEDIA_NAMED_GETTER_IF(x, 2, mt3, an3) \
00313 ACEDIA_NAMED_GETTER_IF(x, 3, mt4, an4) \
00314 ACEDIA_NAMED_GETTER_IF(x, 4, mt5, an5) \
00315 ACEDIA_NAMED_GETTER_IF(x, 5, mt6, an6) \
00316 ACEDIA_NAMED_GETTER_IF(x, 6, mt7, an7) \
00317 ACEDIA_NAMED_GETTER_IF(x, 7, mt8, an8) \
00318 ACEDIA_NAMED_GETTER_IF(x, 8, mt9, an9) \
00319 virtual const char *elementNameAt(int i) const { \
00320 switch (i) { \
00321 case 0: return #an1 ; case 1: return #an2 ; case 2: return #an3 ; \
00322 case 3: return #an4 ; case 4: return #an5 ; case 5: return #an6 ; \
00323 case 6: return #an7 ; case 7: return #an8 ; case 8: return #an9 ; \
00324 default: return ""; \
00325 } } \
00326 virtual const ::acedia::Any asAny() const { \
00327 return ::acedia::Any::from(*this); \
00328 } \
00329 ACEDIA_SEQ_LAST(seq) &operator=(const ACEDIA_SEQ_LAST(seq) &other) { \
00330 if (!m_data->deref()) delete m_data; \
00331 m_data = other.m_data; \
00332 m_data->ref(); \
00333 return *this; \
00334 } \
00335 bool operator==(const ACEDIA_SEQ_LAST(seq) &other) const { \
00336 const Data &d1 = *(m_d()); \
00337 const Data &d2 = *(other.m_d()); \
00338 return d1 == d2; \
00339 } \
00340 }; \
00341 ACEDIA_CLOSE_NAMESPACES(BOOST_PP_SEQ_POP_BACK(seq)) \
00342 ACEDIA_ANNOUNCE_IMPL( seq, x ) \
00343 namespace acedia { namespace util { \
00344 template<> struct UnboxUtil< ACEDIA_REDUCE_SEQ(ACEDIA_PUSH_DDOTS,seq) > \
00345 { \
00346 typedef RuleBuilder< x ,0, \
00347 ACEDIA_FIRST_N(x,mt1,mt2,mt3,mt4,mt5,mt6,mt7,mt8,mt9) > \
00348 UnboxedRuleBuilder; \
00349 static UnboxedRuleBuilder doUnbox(details::AnyArrayProcessor *pc) \
00350 { \
00351 pc->passThrough(new details::Unboxer \
00352 < x , ACEDIA_REDUCE_SEQ(ACEDIA_PUSH_DDOTS,seq) , \
00353 ACEDIA_FIRST_N(x,mt1,mt2,mt3,mt4,mt5,mt6,mt7,mt8,mt9) >); \
00354 return UnboxedRuleBuilder(pc); \
00355 } \
00356 }; \
00357 } }
00358
00382 #define ACEDIA_DECLARE_CASE_TUPLE1(name_seq, Name1, T1) ACEDIA_DECLARE_CASE_TUPLEX(name_seq, 1, T1, _, _, _, _, _, _, _, _, Name1, _, _, _, _, _, _, _, _)
00383
00389 #define ACEDIA_DECLARE_CASE_TUPLE2(name_seq, Name1, T1, Name2, T2) ACEDIA_DECLARE_CASE_TUPLEX(name_seq, 2, T1, T2, _, _, _, _, _, _, _, Name1, Name2, _, _, _, _, _, _, _)
00390
00396 #define ACEDIA_DECLARE_CASE_TUPLE3(name_seq, Name1, T1, Name2, T2, Name3, T3) ACEDIA_DECLARE_CASE_TUPLEX(name_seq, 3, T1, T2, T3, _, _, _, _, _, _, Name1, Name2, Name3, _, _, _, _, _, _)
00397
00403 #define ACEDIA_DECLARE_CASE_TUPLE4(name_seq, Name1, T1, Name2, T2, Name3, T3, Name4, T4) ACEDIA_DECLARE_CASE_TUPLEX(name_seq, 4, T1, T2, T3, T4, _, _, _, _, _, Name1, Name2, Name3, Name4, _, _, _, _, _)
00404
00410 #define ACEDIA_DECLARE_CASE_TUPLE5(name_seq, Name1, T1, Name2, T2, Name3, T3, Name4, T4, Name5, T5) ACEDIA_DECLARE_CASE_TUPLEX(name_seq, 5, T1, T2, T3, T4, T5, _, _, _, _, Name1, Name2, Name3, Name4, Name5, _, _, _, _)
00411
00417 #define ACEDIA_DECLARE_CASE_TUPLE6(name_seq, Name1, T1, Name2, T2, Name3, T3, Name4, T4, Name5, T5, Name6, T6) ACEDIA_DECLARE_CASE_TUPLEX(name_seq, 6, T1, T2, T3, T4, T5, T6, _, _, _, Name1, Name2, Name3, Name4, Name5, Name6, _, _, _)
00418
00424 #define ACEDIA_DECLARE_CASE_TUPLE7(name_seq, Name1, T1, Name2, T2, Name3, T3, Name4, T4, Name5, T5, Name6, T6, Name7, T7) ACEDIA_DECLARE_CASE_TUPLEX(name_seq, 7, T1, T2, T3, T4, T5, T6, T7, _, _, Name1, Name2, Name3, Name4, Name5, Name6, Name7, _, _)
00425
00431 #define ACEDIA_DECLARE_CASE_TUPLE8(name_seq, Name1, T1, Name2, T2, Name3, T3, Name4, T4, Name5, T5, Name6, T6, Name7, T7, Name8, T8) ACEDIA_DECLARE_CASE_TUPLEX(name_seq, 8, T1, T2, T3, T4, T5, T6, T7, T8, _, Name1, Name2, Name3, Name4, Name5, Name6, Name7, Name8, _)
00432
00438 #define ACEDIA_DECLARE_CASE_TUPLE9(name_seq, Name1, T1, Name2, T2, Name3, T3, Name4, T4, Name5, T5, Name6, T6, Name7, T7, Name8, T8, Name9, T9) ACEDIA_DECLARE_CASE_TUPLEX(name_seq, 9, T1, T2, T3, T4, T5, T6, T7, T8, T9, Name1, Name2, Name3, Name4, Name5, Name6, Name7, Name8, Name9)
00439
00440 #endif