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 

Generated on Thu Apr 30 15:53:49 2009 for CERTIDeveloperDocumentation by doxygen 1.5.5