# HLAvariableArray.hh

Go to the documentation of this file.

    00001 // ----------------------------------------------------------------------------
    00002 // HLAvariableArray.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: HLAvariableArray.hh,v 1.3 2008/11/04 14:40:39 gotthardp Exp $
    00015 // ----------------------------------------------------------------------------
    00016
    00017 #ifndef _HLATYPES_VARIABLEARRAY_HH
    00018 #define _HLATYPES_VARIABLEARRAY_HH
    00019
    00020 #include <HLAbuffer.hh>
    00021 #include <HLAbasicType.hh>
    00022
    00023 namespace libhla {
    00024
    00025 /* HLAvariableArray<DATATYPE>
    00026  * defines an array of a variable number of DATATYPE elements.
    00027  *
    00028  * The size() member must be set before accessing the data. No data are moved
    00029  * when the size() is changed.
    00030  *
    00031  * For example:
    00032  * +-------------+----------------+-------------+-----------------+-----------+
    00033  * | Name        | Element type   | Cardinality | Encoding        | Semantics |
    00034  * +-------------+----------------+-------------+-----------------+-----------+
    00035  * | List        | HLAinteger32BE | Dynamic     | HLAvaribleArray |           |
    00036  * +-------------+----------------+-------------+-----------------+-----------+
    00037  *
    00038  * typedef HLAvariableArray<HLAinteger32BE> List;
    00039  * HLAdata<List> value;
    00040  *
    00041  * (*value).set_size(2);
    00042  * (*value)[0] = 100;
    00043  * (*value)[1] = 200;
    00044  */
    00045
    00047 template<class M, bool hasVariable = M::m_isVariable>
    00048 struct HLAvariableArray;
    00049
    00050 template<class M, bool hasVariable>
    00051 std::ostream& PrintBuffer(std::ostream& stream, HLAvariableArray<M,hasVariable>& buffer)
    00052 { return __print_buffer(stream, (void*)&buffer, buffer.__sizeof()); }
    00053
    00054 // Variable array optimized for fixed-size elements
    00055 template<class M>
    00056 struct HLAvariableArray<M, false>
    00057 {
    00059     /* This function assumes no data are stored in the buffer after this array.
    00060      * You may want to use set_size() instead.
    00061      */
    00062     HLAinteger32BE& size() const
    00063     { return (HLAinteger32BE&)*this; }
    00064
    00066     void set_size(long i)
    00067     {
    00068         if (i == size())
    00069             return; // no change
    00070
    00071         // as changing the array size may impact padding, the whole buffer needs to be reorganized
    00072         __HLAbuffer::shake(this, i,
    00073             (i-size())*(long)(M::__sizeof() + __padding(M::__sizeof(), M::m_octetBoundary)));
    00074     }
    00075
    00076     static const size_t offset(long i)
    00077     { return emptysizeof() + i*(M::__sizeof() + __padding(M::__sizeof(), M::m_octetBoundary)); }
    00078
    00079     M& operator[](long i) const
    00080     {
    00081         if (i >= size())
    00082             throw std::out_of_range("HLAvariableArray: index out of range");
    00083         return *(M*)((char*)this + offset(i));
    00084     }
    00085
    00086     static const size_t emptysizeof()
    00087     { return HLAinteger32BE::__sizeof() + __padding(HLAinteger32BE::__sizeof(), M::m_octetBoundary); }
    00088
    00089     // Padding shall not be added after the last element of the array.
    00090     const size_t __sizeof() const
    00091     {
    00092         if (size() > 0)
    00093             return offset(size()-1) + M::__sizeof();
    00094         else
    00095             return emptysizeof();
    00096     }
    00097
    00098     void copy(void* source)
    00099     {
    00100         int N = *(HLAinteger32BE*)source;
    00101         int toCopy;
    00102
    00103         __HLAbuffer& buffer = __HLAbuffer::__buffer(this);
    00104         if(source == buffer.mShakeThat) {
    00105             *(HLAinteger32BE*)this = buffer.mShakeValue;
    00106             toCopy = std::min(N, buffer.mShakeValue); // number of elements to copy
    00107         }
    00108         else {
    00109             *(HLAinteger32BE*)this = N;
    00110             toCopy = N; // copy all elements
    00111         }
    00112
    00113         size_t offs = emptysizeof();
    00114         // copy all elements of the structure, the elements may be variable-sized
    00115         for (int i = 0; i < toCopy; i++) {
    00116             ((M*)((char*)this + offs))->copy((char*)source + offs);
    00117             offs += M::__sizeof() + __padding(M::__sizeof(), M::m_octetBoundary);
    00118         }
    00119     }
    00120
    00121     static const size_t m_octetBoundary =
    00122         MAX(HLAinteger32BE::m_octetBoundary, M::m_octetBoundary);
    00123     static const bool m_isVariable = true; // variable-sized array
    00124 };
    00125
    00126 // Generic variable array, supports variable-size elements
    00127 // note: this is the less efficient data type
    00128 template<class M>
    00129 struct HLAvariableArray<M, true>
    00130 {
    00132     /* This function assumes no data are stored in the buffer after this array.
    00133      * You may want to use set_size() instead.
    00134      */
    00135     HLAinteger32BE& size() const
    00136     { return (HLAinteger32BE&)*this; }
    00137
    00139     void set_size(long i)
    00140     {
    00141         if (i == size())
    00142             return; // no change
    00143
    00144         // as changing the array size may impact padding, the whole buffer needs to be reorganized
    00145         __HLAbuffer::shake(this, i,
    00146             (i-size())*(long)(M::emptysizeof() + __padding(M::emptysizeof(), M::m_octetBoundary)));
    00147     }
    00148
    00149     const size_t offset(long i) const
    00150     {
    00151         size_t offs = emptysizeof();
    00152         // count every member, the elements may be variable-sized
    00153         for (long j=0; j<i; j++) {
    00154             offs += ((M*)((char*)this + offs))->__sizeof();
    00155             offs += __padding(offs, M::m_octetBoundary);
    00156         }
    00157         return offs;
    00158     }
    00159
    00160     M& operator[](long i) const
    00161     {
    00162         if (i >= size())
    00163             throw std::out_of_range("HLAvariableArray: index out of range");
    00164         return *(M*)((char*)this + offset(i));
    00165     }
    00166
    00167     static const size_t emptysizeof()
    00168     { return HLAinteger32BE::__sizeof() + __padding(HLAinteger32BE::__sizeof(), M::m_octetBoundary); }
    00169
    00170     // Padding shall not be added after the last element of the array.
    00171     const size_t __sizeof() const
    00172     {
    00173         if (size() > 0) {
    00174             size_t offs = offset(size()-1);
    00175             return offs + ((M*)((char*)this + offs))->__sizeof();
    00176         }
    00177         else
    00178             return emptysizeof();
    00179     }
    00180
    00181     void copy(void* source)
    00182     {
    00183         int N = *(HLAinteger32BE*)source;
    00184         int toCopy;
    00185
    00186         __HLAbuffer& buffer = __HLAbuffer::__buffer(this);
    00187         if(source == buffer.mShakeThat) {
    00188             *(HLAinteger32BE*)this = buffer.mShakeValue;
    00189             toCopy = std::min(N, buffer.mShakeValue); // number of elements to copy
    00190         }
    00191         else {
    00192             *(HLAinteger32BE*)this = N;
    00193             toCopy = N; // copy all elements
    00194         }
    00195
    00196         size_t offsD = emptysizeof();
    00197         size_t offsS = emptysizeof();
    00198         // copy all elements of the structure, the elements may be variable-sized
    00199         for (int i = 0; i < toCopy; i++) {
    00200             ((M*)((char*)this + offsD))->copy((char*)source + offsS);
    00201
    00202             offsD += ((M*)((char*)this + offsD))->__sizeof(); // may differ from source size
    00203             offsD += __padding(offsD, M::m_octetBoundary);
    00204             offsS += ((M*)((char*)source + offsS))->__sizeof();
    00205             offsS += __padding(offsS, M::m_octetBoundary);
    00206         }
    00207     }
    00208
    00209     static const size_t m_octetBoundary =
    00210         MAX(HLAinteger32BE::m_octetBoundary, M::m_octetBoundary);
    00211     static const bool m_isVariable = true; // variable-size array of variable-size elements
    00212 };
    00213
    00214 /* IEEE 1516.2, Table 29:
    00215  * Array datatype table
    00216  */
    00217 struct HLAASCIIstring : public HLAvariableArray<HLAASCIIchar>
    00218 {
    00219     HLAASCIIstring& operator = (const std::string& it)
    00220     {
    00221         __HLAbuffer& buffer = __HLAbuffer::__buffer(this);
    00222         size_t offset = (char*)this - buffer.mBegin;
    00223
    00224         set_size(it.size());
    00225         // note: set_size may have caused realloc()
    00226         memcpy(buffer.mBegin + offset + emptysizeof(), it.data(), it.size());
    00227
    00228         return *this;
    00229     }
    00230
    00231     operator std::string() const
    00232     {
    00233         return std::string((char*)this + emptysizeof(), size());
    00234     }
    00235 };
    00236
    00237 typedef HLAvariableArray<HLAunicodeChar> HLAunicodeString;
    00238 typedef HLAvariableArray<HLAbyte> HLAopaqueData;
    00239
    00240 } // namespace libhla
    00241
    00242 #endif // _HLATYPES_VARIABLEARRAY_HH
    00243
    00244 // $Id: HLAvariableArray.hh,v 1.3 2008/11/04 14:40:39 gotthardp Exp $
    00245