00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef _HLATYPES_VARIANTRECORD_HH
00018 #define _HLATYPES_VARIANTRECORD_HH
00019
00020 #include <HLAbuffer.hh>
00021
00022 namespace libhla {
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00068 template<int DE, class DM, class R, bool hasVariable = R::m_isVariable>
00069 struct HLAvariantRecord;
00070
00071 template<int DE, class DM, class R, bool V>
00072 std::ostream& PrintBuffer(std::ostream& stream, HLAvariantRecord<DE,DM,R,V>& buffer)
00073 { return __print_buffer(stream, (void*)&buffer, buffer.__sizeof()); }
00074
00076 template<class R, int i> struct __FieldAt;
00077
00079 template<int DE, class DM, class R, int e>
00080 struct __DiscriminantOrFieldAt;
00081
00082
00083 template<int DE, class DM, class R>
00084 struct HLAvariantRecord<DE, DM, R, false>
00085 {
00087
00088
00089
00090 DM& discriminant() const
00091 { return *(DM*)this; }
00092
00094 void set_discriminant(int d)
00095 {
00096 if (d == (int)discriminant())
00097 return;
00098
00099
00100 __HLAbuffer::shake(this, d, (long)R::field_emptysizeof(d));
00101 }
00102
00103 template <int e>
00104 typename __DiscriminantOrFieldAt<DE,DM,R,e>::Type& field() const
00105 {
00106
00107 if (e == DE)
00108 return *(typename __DiscriminantOrFieldAt<DE,DM,R,e>::Type*)this;
00109
00110 if (e != R::get_field(discriminant()))
00111 throw std::out_of_range("HLAvariantRecord: wrong discriminant");
00112
00113 return *(typename __DiscriminantOrFieldAt<DE,DM,R,e>::Type*)((char*)this + emptysizeof());
00114 }
00115
00116 static const size_t emptysizeof()
00117 { return DM::__sizeof() + __padding(DM::__sizeof(), R::m_octetBoundary); }
00118
00119 const size_t __sizeof() const
00120 {
00121 if (R::has_field(discriminant()))
00122 return emptysizeof() + R::field_sizeof(discriminant());
00123 else
00124 return emptysizeof();
00125 }
00126
00127 void copy(void* source)
00128 {
00129 __HLAbuffer& buffer = __HLAbuffer::__buffer(this);
00130 if(source == buffer.mShakeThat) {
00131 *(DM*)this = buffer.mShakeValue;
00132
00133 }
00134 else {
00135 int d = *(DM*)source;
00136
00137 *(DM*)this = d;
00138 ((R*)this)->copy(d, (char*)source + emptysizeof());
00139 }
00140 }
00141
00142 static const size_t m_octetBoundary = MAX(DM::m_octetBoundary, R::m_octetBoundary);
00143 static const bool m_isVariable = true;
00144 };
00145
00146
00147 template<int DE, class DM, class R>
00148 struct HLAvariantRecord<DE, DM, R, true>
00149 {
00151
00152
00153
00154 DM& discriminant() const
00155 { return *(DM*)this; }
00156
00158 void set_discriminant(int d)
00159 {
00160 if (d == (int)discriminant())
00161 return;
00162
00163
00164 __HLAbuffer::shake(this, d, (long)R::field_emptysizeof(d));
00165 }
00166
00167 template <int e>
00168 typename __DiscriminantOrFieldAt<DE,DM,R,e>::Type& field() const
00169 {
00170
00171 if (e == DE)
00172 return *(typename __DiscriminantOrFieldAt<DE,DM,R,e>::Type*)this;
00173
00174 if (e != R::get_field(discriminant()))
00175 throw std::out_of_range("HLAvariantRecord: wrong discriminant");
00176
00177 return *(typename __DiscriminantOrFieldAt<DE,DM,R,e>::Type*)((char*)this + emptysizeof());
00178 }
00179
00180 static const size_t emptysizeof()
00181 { return DM::__sizeof() + __padding(DM::__sizeof(), R::m_octetBoundary); }
00182
00183 const size_t __sizeof() const
00184 {
00185 if (R::has_field(discriminant()))
00186 return emptysizeof() + ((R*)((char*)this + emptysizeof()))->field_sizeof(discriminant());
00187 else
00188 return emptysizeof();
00189 }
00190
00191 void copy(void* source)
00192 {
00193 __HLAbuffer& buffer = __HLAbuffer::__buffer(this);
00194 if(source == buffer.mShakeThat) {
00195 *(DM*)this = buffer.mShakeValue;
00196
00197 }
00198 else {
00199 int d = *(DM*)source;
00200
00201 *(DM*)this = d;
00202 ((R*)this)->copy(d, (char*)source + emptysizeof());
00203 }
00204 }
00205
00206 static const size_t m_octetBoundary = MAX(DM::m_octetBoundary, R::m_octetBoundary);
00207 static const bool m_isVariable = true;
00208 };
00209
00210 struct HLAsetEnd;
00211
00213 template<int e, class N = HLAsetEnd>
00214 struct HLAsetValue
00215 {
00216 static int includes(int i)
00217 {
00218 if (i == e)
00219 return 1;
00220 else
00221 return N::includes(i);
00222 }
00223 };
00224
00226 template<int e1, int e2, class N = HLAsetEnd>
00227 struct HLAsetRange
00228 {
00229 static int includes(int i)
00230 {
00231 if (e1 <= i && i <= e2)
00232 return 1;
00233 else
00234 return N::includes(i);
00235 }
00236 };
00237
00239 template<class N = HLAsetEnd>
00240 struct HLAsetOther
00241 {
00242 static int includes(int i)
00243 { return 1; }
00244 };
00245
00247 struct HLAsetEnd
00248 {
00249 static int includes(int i)
00250 { return 0; }
00251 };
00252
00253 struct HLAvariantEnd;
00254
00256
00257 template<class D, int E, class M, class N = HLAvariantEnd, bool hasVariable = M::m_isVariable || N::m_isVariable>
00258 struct HLAvariantField;
00259
00260
00261 template<class D, int E, class M, class N>
00262 struct HLAvariantField<D, E, M, N, false>
00263 {
00264 static bool has_field(int d)
00265 {
00266 if (D::includes(d))
00267 return true;
00268 else
00269 return N::has_field(d);
00270 }
00271
00272 static int get_field(int d)
00273 {
00274 if (D::includes(d))
00275 return E;
00276 else
00277 return N::get_field(d);
00278 }
00279
00280 static const size_t field_emptysizeof(int e)
00281 {
00282 if (e == E)
00283 return M::emptysizeof();
00284 else
00285 return N::field_emptysizeof(e);
00286 }
00287
00288 static const size_t field_sizeof(int e)
00289 {
00290 if (e == E)
00291 return M::__sizeof();
00292 else
00293 return N::field_sizeof(e);
00294 }
00295
00296 void copy(int e, void* source)
00297 {
00298 if (e == E)
00299 return ((M*)this)->copy(source);
00300 else
00301 return ((N*)this)->copy(e, source);
00302 }
00303
00304 static const size_t m_octetBoundary = MAX(M::m_octetBoundary, N::m_octetBoundary);
00305 static const bool m_isVariable = false;
00306 };
00307
00308
00309 template<class D, int E, class M, class N>
00310 struct HLAvariantField<D, E, M, N, true>
00311 {
00312 static bool has_field(int d)
00313 {
00314 if (D::includes(d))
00315 return true;
00316 else
00317 return N::has_field(d);
00318 }
00319
00320 static int get_field(int d)
00321 {
00322 if (D::includes(d))
00323 return E;
00324 else
00325 return N::get_field(d);
00326 }
00327
00328 static const size_t field_emptysizeof(int e)
00329 {
00330 if (e == E)
00331 return M::emptysizeof();
00332 else
00333 return N::field_emptysizeof(e);
00334 }
00335
00336 const size_t field_sizeof(int e) const
00337 {
00338 if (e == E)
00339 return ((M*)this)->__sizeof();
00340 else
00341 return ((N*)this)->field_sizeof(e);
00342 }
00343
00344 void copy(int e, void* source)
00345 {
00346 if (e == E)
00347 return ((M*)this)->copy(source);
00348 else
00349 return ((N*)this)->copy(e, source);
00350 }
00351
00352 static const size_t m_octetBoundary = MAX(M::m_octetBoundary, N::m_octetBoundary);
00353 static const bool m_isVariable = true;
00354 };
00355
00357 struct HLAvariantEnd
00358 {
00359 static bool has_field(int d)
00360 { return false; }
00361 static int get_field(int d)
00362 { throw std::out_of_range("HLAvariantRecord: unknown discriminant"); }
00363 static const size_t field_emptysizeof(int e)
00364 { return 0; }
00365 static const size_t field_sizeof(int e)
00366 { return 0; }
00367 void copy(int e, void* source)
00368 { }
00369
00370 static const size_t m_octetBoundary = 0;
00371 static const bool m_isVariable = false;
00372 };
00373
00374 template<bool C, class Then, class Else>
00375 struct __variantRecord_if
00376 { typedef Then X; };
00377
00378 template<class Then, class Else>
00379 struct __variantRecord_if<false, Then, Else>
00380 { typedef Else X; };
00381
00382 template<int DE, class DM, class R, int e>
00383 struct __DiscriminantOrFieldAt
00384 { typedef typename __variantRecord_if<e==DE, DM, typename __FieldAt<R,e>::Type>::X Type; };
00385
00386 template<class D, int E, class M, class N, bool V, int e>
00387 struct __FieldAt<HLAvariantField<D,E,M,N,V>, e>
00388 { typedef typename __variantRecord_if<e==E, M, typename __FieldAt<N,e>::Type>::X Type; };
00389
00390
00391 template<int e>
00392 struct __FieldAt<HLAvariantEnd, e>
00393 { typedef HLAvariantEnd Type; };
00394
00395 }
00396
00397 #endif // _HLATYPES_VARIANTRECORD_HH
00398
00399
00400