# HLAfixedRecord.hh

Go to the documentation of this file.

    00001 // ----------------------------------------------------------------------------
    00002 // HLAfixedRecord.hh - IEEE 1516.2 compliant datatypes
    00003 // Copyright (C) 2008  Petr Gotthard <petr.gotthard@centrum.cz>
    00004 //
    00005 // This library is free software; you can redistribute it and/or
    00006 // modify it under the terms of the GNU Lesser General Public
    00007 // License version 2.1, as published by the Free Software Foundation.
    00008 //
    00009 // This library is distributed in the hope that it will be useful,
    00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00012 // Lesser General Public License for more details.
    00013 //
    00014 // $Id: HLAfixedRecord.hh,v 1.2 2008/10/11 09:35:51 gotthardp Exp $
    00015 // ----------------------------------------------------------------------------
    00016
    00017 #ifndef _HLATYPES_FIXEDRECORD_HH
    00018 #define _HLATYPES_FIXEDRECORD_HH
    00019
    00020 #include <HLAbuffer.hh>
    00021
    00022 namespace libhla {
    00023
    00024 /* HLAfixedRecord<
    00025  *   HLAfixedField<INDEX1, DATATYPE1,
    00026  *   HLAfixedField<INDEX2, DATATYPE2,
    00027  *   ...
    00028  *   > ... > TYPENAME;
    00029  * defines an ordered sequence of DATATYPE entries.
    00030  *
    00031  * The data can be accessed using the field<INDEX>() function. The INDEX is a logical
    00032  * identifier only. The data are stored in the declaration order.
    00033  *
    00034  * For example:
    00035  * +-------------+------------------------------------+----------------+-----------+
    00036  * |             | Field                              |                |           |
    00037  * | Record name +---------+--------------+-----------+ Encoding       | Semantics |
    00038  * |             | Name    | Type         | Semantics |                |           |
    00039  * +-------------+---------+--------------+-----------+----------------+-----------+
    00040  * |             | FIELD_X | HLAfloat32LE |           |                |           |
    00041  * |             +---------+--------------+-----------+                |           |
    00042  * | Coordinates | FIELD_Y | HLAfloat32LE |           | HLAfixedRecord |           |
    00043  * |             +---------+--------------+-----------+                |           |
    00044  * |             | FIELD_Z | HLAfloat32LE |           |                |           |
    00045  * +-------------+---------+--------------+-----------+----------------+-----------+
    00046  *
    00047  * enum {
    00048  *   FIELD_X = 0,
    00049  *   FIELD_Y,
    00050  *   FIELD_Z
    00051  * };
    00052  * typedef HLAfixedRecord<
    00053  *   HLAfixedField<FIELD_X, HLAfloat32LE,
    00054  *   HLAfixedField<FIELD_Y, HLAfloat32LE,
    00055  *   HLAfixedField<FIELD_Z, HLAfloat32LE
    00056  *   > > > > Coordinates;
    00057  * HLAdata<Coordinates> value;
    00058  *
    00059  * value->field<FIELD_X>() = 3.14;
    00060  * value->field<FIELD_Y>() = 6.28;
    00061  * value->field<FIELD_Z>() = 9.42;
    00062  */
    00063
    00065 template<class R, bool hasVariable = R::m_isVariable>
    00066 struct HLAfixedRecord;
    00067
    00068 template<class R, bool V>
    00069 std::ostream& PrintBuffer(std::ostream& stream, HLAfixedRecord<R,V>& buffer)
    00070 { return __print_buffer(stream, (void*)&buffer, buffer.__sizeof()); }
    00071
    00073 template<class R, int i> struct __FieldAt;
    00074
    00075 // Fixed record optimized for fixed-size fields
    00076 template<class R>
    00077 struct HLAfixedRecord<R, false>
    00078 {
    00079     template <int i>
    00080     typename __FieldAt<R,i>::Type& field() const
    00081     { return *(typename __FieldAt<R,i>::Type*)((char*)this + R::field_offsetof(i)); }
    00082
    00083     static const size_t emptysizeof()
    00084     { return R::emptysizeof(); }
    00085
    00086     static const size_t __sizeof()
    00087     { return R::__sizeof(); }
    00088
    00089     void copy(void* source)
    00090     { ((R*)this)->copy(source); }
    00091
    00092     static const size_t m_octetBoundary = R::m_octetBoundary;
    00093     static const bool m_isVariable = false; // fixed-sized fields
    00094 };
    00095
    00096 // Generic fixed record, supports variable-size fields
    00097 template<class R>
    00098 struct HLAfixedRecord<R, true>
    00099 {
    00100     template <int i>
    00101     typename __FieldAt<R,i>::Type& field() const
    00102     { return *(typename __FieldAt<R,i>::Type*)((char*)this + ((R*)this)->field_offsetof(i)); }
    00103
    00104     static const size_t emptysizeof()
    00105     { return R::emptysizeof(); }
    00106
    00107     const size_t __sizeof()
    00108     { return ((R*)this)->__sizeof(); }
    00109
    00110     void copy(void* source)
    00111     { ((R*)this)->copy(source); }
    00112
    00113     static const size_t m_octetBoundary = R::m_octetBoundary;
    00114     static const bool m_isVariable = true; // variable-sized fields
    00115 };
    00116
    00117 struct HLAfixedEnd;
    00118
    00120 // note: <E> must be "int" to enable implicit conversion from/to enum types
    00121 template<int E, class M, class N = HLAfixedEnd, bool hasVariable = M::m_isVariable || N::m_isVariable>
    00122 struct HLAfixedField;
    00123
    00124 // List of fixed-size fields
    00125 template<int E, class M, class N>
    00126 struct HLAfixedField<E, M, N, false>
    00127 {
    00128     static const size_t field_offsetof(int d, size_t offs = 0)
    00129     {
    00130         if (d != E) {
    00131             size_t size = M::__sizeof();
    00132             size += __padding(offs+size, N::memberBoundary);
    00133             return N::field_offsetof(d, offs+size);
    00134         }
    00135         else
    00136             return offs;
    00137     }
    00138
    00139     static const size_t memberBoundary = M::m_octetBoundary;
    00140
    00141     static const size_t emptysizeof(size_t offs = 0)
    00142     { return __sizeof(offs); }
    00143
    00144     // Padding shall not be added after the last element of the array.
    00145     static const size_t __sizeof(size_t offs = 0)
    00146     {
    00147         size_t size = M::__sizeof();
    00148         // if not reached HLAvariantEnd
    00149         if (N::memberBoundary) {
    00150             size += __padding(offs+size, N::memberBoundary);
    00151             return N::__sizeof(offs+size);
    00152         }
    00153         else
    00154             return offs+size;
    00155     }
    00156
    00157     void copy(void* source, size_t offsD = 0, size_t offsS = 0)
    00158     {
    00159         ((M*)this)->copy(source);
    00160         if (N::memberBoundary) {
    00161             offsD += M::__sizeof();
    00162             offsD += __padding(offsD, N::memberBoundary);
    00163             offsS += M::__sizeof();
    00164             offsS += __padding(offsS, N::memberBoundary);
    00165             ((N*)((char*)this + M::__sizeof()))->copy((char*)source + M::__sizeof(), offsD, offsS);
    00166         }
    00167     }
    00168
    00169     static const size_t m_octetBoundary = MAX(M::m_octetBoundary, N::m_octetBoundary);
    00170     static const bool m_isVariable = false; // fixed-sized fields
    00171 };
    00172
    00173 // List containg variable-size fields
    00174 template<int E, class M, class N>
    00175 struct HLAfixedField<E, M, N, true>
    00176 {
    00177     const size_t field_offsetof(int d, size_t offs = 0) const
    00178     {
    00179         if (d != E) {
    00180             size_t size = ((M*)this)->__sizeof();
    00181             size += __padding(offs+size, N::memberBoundary);
    00182             return ((N*)((char*)this + size))->field_offsetof(d, offs+size);
    00183         }
    00184         else
    00185             return offs;
    00186     }
    00187
    00188     static const size_t memberBoundary = M::m_octetBoundary;
    00189
    00190     static const size_t emptysizeof(size_t offs = 0)
    00191     {
    00192         size_t size = M::emptysizeof();
    00193         // if not reached HLAvariantEnd
    00194         if (N::memberBoundary) {
    00195             size += __padding(offs+size, N::memberBoundary);
    00196             return N::emptysizeof(offs+size);
    00197         }
    00198         else
    00199             return offs+size;
    00200     }
    00201
    00202     // Padding shall not be added after the last element of the array.
    00203     const size_t __sizeof(size_t offs = 0) const
    00204     {
    00205       size_t size = ((M*)this)->__sizeof();
    00206       // if not reached HLAvariantEnd
    00207       if (N::memberBoundary) {
    00208           size += __padding(offs+size, N::memberBoundary);
    00209           return ((N*)((char*)this + size))->__sizeof(offs+size);
    00210       }
    00211       else
    00212           return offs+size;
    00213     }
    00214
    00215     void copy(void* source, size_t offsD = 0, size_t offsS = 0)
    00216     {
    00217         ((M*)this)->copy(source);
    00218         if (N::memberBoundary) {
    00219             size_t sizeD = ((M*)this)->__sizeof(); // may differ from source size
    00220             sizeD += __padding(offsD+sizeD, N::memberBoundary);
    00221             size_t sizeS = ((M*)source)->__sizeof();
    00222             sizeS += __padding(offsS+sizeS, N::memberBoundary);
    00223             ((N*)((char*)this + sizeD))->copy((char*)source + sizeS, offsD+sizeD, offsS+sizeS);
    00224         }
    00225     }
    00226
    00227     static const size_t m_octetBoundary = MAX(M::m_octetBoundary, N::m_octetBoundary);
    00228     static const bool m_isVariable = true; // variable-sized fields
    00229 };
    00230
    00232 struct HLAfixedEnd
    00233 {
    00234     static const size_t field_offsetof(int d, size_t offs = 0)
    00235     { return offs; }
    00236
    00237     static const size_t memberBoundary = 0;
    00238     static const size_t emptysizeof(size_t offs = 0)
    00239     { return offs; }
    00240     static const size_t __sizeof(size_t offs = 0)
    00241     { return offs; }
    00242     void copy(void* source, size_t offsD = 0, size_t offsS = 0)
    00243     { /* nop */ }
    00244
    00245     static const size_t m_octetBoundary = 0;
    00246     static const bool m_isVariable = false;
    00247 };
    00248
    00249 template<bool C, class Then, class Else>
    00250 struct __fixedRecord_if
    00251 { typedef Then X; };
    00252
    00253 template<class Then, class Else>
    00254 struct __fixedRecord_if<false, Then, Else>
    00255 { typedef Else X; };
    00256
    00257 template<int E, class M, class N, bool V, int d>
    00258 struct __FieldAt<HLAfixedField<E, M, N, V>, d>
    00259 { typedef typename __fixedRecord_if<d==E, M, typename __FieldAt<N,d>::Type>::X Type; };
    00260
    00261 // returned when no HLAfixedField has a given index(i)
    00262 template<int d>
    00263 struct __FieldAt<HLAfixedEnd, d>
    00264 { typedef HLAfixedEnd Type; };
    00265
    00266 } // namespace libhla
    00267
    00268 #endif // _HLATYPES_FIXEDRECORD_HH
    00269
    00270 // $Id: HLAfixedRecord.hh,v 1.2 2008/10/11 09:35:51 gotthardp Exp $
    00271