1 /*********************************************************************
2 Copyright 2013 Karl Jones
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
8 1. Redistributions of source code must retain the above copyright notice, this
9 list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright notice,
11 this list of conditions and the following disclaimer in the documentation
12 and/or other materials provided with the distribution.
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 For Further Information Please Contact me at
27 http://p.sf.net/kdis/UserGuide
28 *********************************************************************/
30 #include "KDIS/DataTypes/VariableDatum.hpp"
34 //////////////////////////////////////////////////////////////////////////
38 using namespace DATA_TYPE
;
39 using namespace ENUMS
;
40 using namespace UTILS
;
42 //////////////////////////////////////////////////////////////////////////
44 //////////////////////////////////////////////////////////////////////////
46 VariableDatum::VariableDatum() : m_ui32DatumLength(0), m_ui32DatumID(0) {}
48 //////////////////////////////////////////////////////////////////////////
50 VariableDatum::VariableDatum(DatumID ID
, const KString
& Value
) {
56 //////////////////////////////////////////////////////////////////////////
58 VariableDatum::VariableDatum(DatumID ID
, const KOCTET
* data
,
62 SetDatumValue(data
, sizeInBits
);
65 //////////////////////////////////////////////////////////////////////////
67 VariableDatum::VariableDatum(KDataStream
& stream
) { Decode(stream
); }
69 //////////////////////////////////////////////////////////////////////////
71 VariableDatum::~VariableDatum() {}
73 //////////////////////////////////////////////////////////////////////////
75 void VariableDatum::SetDatumID(DatumID ID
) { m_ui32DatumID
= ID
; }
77 //////////////////////////////////////////////////////////////////////////
79 DatumID
VariableDatum::GetDatumID() const { return (DatumID
)m_ui32DatumID
; }
81 //////////////////////////////////////////////////////////////////////////
83 KUINT32
VariableDatum::GetDatumLength() const { return m_ui32DatumLength
; }
85 //////////////////////////////////////////////////////////////////////////
87 KUINT32
VariableDatum::GetPDULength() const {
88 return VARIABLE_DATUM_SIZE
+ (m_v8DatumValue
.size() * 8);
91 //////////////////////////////////////////////////////////////////////////
93 void VariableDatum::SetDatumValue(const KString
& s
) {
94 SetDatumValue(s
.c_str(),
95 (s
.length() + 1) * 8); // +1 to allow for terminating NULL ...
98 //////////////////////////////////////////////////////////////////////////
100 void VariableDatum::SetDatumValue(const KOCTET
* data
, KUINT32 sizeInBits
) {
101 m_v8DatumValue
.clear();
103 KUINT32 sizeInOctets
= ceil(sizeInBits
/ 8.0);
104 for (KUINT16 i
= 0; i
< sizeInOctets
;) {
107 for (KUINT16 j
= 0; j
< 8 && i
< sizeInOctets
; ++j
, ++i
) {
108 de
.Buffer
[j
] = data
[i
];
110 m_v8DatumValue
.push_back(de
);
113 m_ui32DatumLength
= sizeInBits
;
116 //////////////////////////////////////////////////////////////////////////
118 void VariableDatum::GetDatumValueCopyIntoBuffer(KOCTET
* Buffer
,
119 KUINT16 BufferSize
) const {
120 KUINT32 sizeInOctets
= ceil(m_ui32DatumLength
/ 8.0);
122 if (BufferSize
< sizeInOctets
)
123 throw KException(__FUNCTION__
, BUFFER_TOO_SMALL
);
125 // Copy the data into the buffer, octet by octet
126 vector
<DatumEntry
>::const_iterator citr
= m_v8DatumValue
.begin();
130 while (i
< sizeInOctets
) {
131 for (KUINT16 j
= 0; i
< sizeInOctets
&& j
< 8; ++j
, ++i
) {
132 Buffer
[i
] = citr
->Buffer
[j
];
138 //////////////////////////////////////////////////////////////////////////
140 KString
VariableDatum::GetDatumValueAsKString() const {
143 vector
<DatumEntry
>::const_iterator citr
= m_v8DatumValue
.begin();
144 vector
<DatumEntry
>::const_iterator citrEnd
= m_v8DatumValue
.end();
148 KUINT32 ui32LengthInOctets
= ceil(m_ui32DatumLength
/ 8.0);
150 while (citr
!= citrEnd
) {
151 for (KUINT16 j
= 0; i
< ui32LengthInOctets
&& j
< 8; ++j
, ++i
) {
152 ss
<< citr
->Buffer
[j
];
160 //////////////////////////////////////////////////////////////////////////
162 vector
<KUINT64
> VariableDatum::GetDatumValueAsKUINT64() const {
163 KBOOL bSwapBytes
= !IsMachineBigEndian();
165 vector
<DatumEntry
>::const_iterator citr
= m_v8DatumValue
.begin();
166 vector
<DatumEntry
>::const_iterator citrEnd
= m_v8DatumValue
.end();
168 vector
<KUINT64
> m_Return
;
170 KUINT32 ui32CurrentPos
= 0;
171 KUINT32 ui32LengthInOctets
= ceil(m_ui32DatumLength
/ 8.0);
173 while (citr
!= citrEnd
) {
174 if ((ui32LengthInOctets
- ui32CurrentPos
) < 8) break;
176 m_Return
.push_back(NetToKUINT64(citr
->Buffer
, bSwapBytes
).m_Value
);
184 //////////////////////////////////////////////////////////////////////////
186 vector
<KFLOAT64
> VariableDatum::GetDatumValueAsKFLOAT64() const {
187 KBOOL bSwapBytes
= !IsMachineBigEndian();
189 vector
<DatumEntry
>::const_iterator citr
= m_v8DatumValue
.begin();
190 vector
<DatumEntry
>::const_iterator citrEnd
= m_v8DatumValue
.end();
192 vector
<KFLOAT64
> m_Return
;
194 KUINT32 ui32CurrentPos
= 0;
195 KUINT32 ui32LengthInOctets
= ceil(m_ui32DatumLength
/ 8.0);
197 while (citr
!= citrEnd
) {
198 if ((ui32LengthInOctets
- ui32CurrentPos
) < 8) break;
200 m_Return
.push_back(NetToKFLOAT64(citr
->Buffer
, bSwapBytes
).m_Value
);
208 //////////////////////////////////////////////////////////////////////////
210 void VariableDatum::ClearDatumValue() {
211 m_v8DatumValue
.clear();
212 m_ui32DatumLength
= 0;
215 //////////////////////////////////////////////////////////////////////////
217 KString
VariableDatum::GetAsString() const {
220 // For now we return the datum value as a string.
221 ss
<< "Variable Datum:"
222 << "\n\tID: " << GetEnumAsStringDatumID(m_ui32DatumID
)
223 << "\n\tLength: " << m_ui32DatumLength
224 << "\n\tValue(S): " << GetDatumValueAsKString() << "\n";
229 //////////////////////////////////////////////////////////////////////////
231 void VariableDatum::Decode(KDataStream
& stream
) {
232 if (stream
.GetBufferSize() < VARIABLE_DATUM_SIZE
)
233 throw KException(__FUNCTION__
, NOT_ENOUGH_DATA_IN_BUFFER
);
235 m_v8DatumValue
.clear();
237 stream
>> m_ui32DatumID
>> m_ui32DatumLength
;
239 KUINT32 ui32LengthInOctets
= ceil(ceil(m_ui32DatumLength
/ 8.0) / 8.0) * 8;
241 // Datum length is returned in bits, so we need to convert to octets
242 for (KUINT16 i
= 0; i
< ui32LengthInOctets
;) {
245 for (KUINT16 j
= 0; i
< ui32LengthInOctets
&& j
< 8; ++j
, ++i
) {
250 m_v8DatumValue
.push_back(de
);
254 //////////////////////////////////////////////////////////////////////////
256 KDataStream
VariableDatum::Encode() const {
259 VariableDatum::Encode(stream
);
264 //////////////////////////////////////////////////////////////////////////
266 void VariableDatum::Encode(KDataStream
& stream
) const {
267 stream
<< m_ui32DatumID
<< m_ui32DatumLength
;
269 vector
<DatumEntry
>::const_iterator citr
= m_v8DatumValue
.begin();
270 vector
<DatumEntry
>::const_iterator citrEnd
= m_v8DatumValue
.end();
272 while (citr
!= citrEnd
) {
273 for (KUINT16 i
= 0; i
< 8; ++i
) {
274 stream
<< citr
->Buffer
[i
];
281 //////////////////////////////////////////////////////////////////////////
283 KBOOL
VariableDatum::operator==(const VariableDatum
& Value
) const {
284 if (m_ui32DatumID
!= Value
.m_ui32DatumID
) return false;
285 if (m_ui32DatumLength
!= Value
.m_ui32DatumLength
) return false;
287 vector
<DatumEntry
>::const_iterator citrThis
= m_v8DatumValue
.begin(),
288 citrOther
= Value
.m_v8DatumValue
.begin();
290 while (citrThis
!= m_v8DatumValue
.end() &&
291 citrOther
!= Value
.m_v8DatumValue
.end()) {
292 if (memcmp(citrThis
->Buffer
, citrOther
->Buffer
, 8) != 0) return false;
299 //////////////////////////////////////////////////////////////////////////
301 KBOOL
VariableDatum::operator!=(const VariableDatum
& Value
) const {
302 return !(*this == Value
);
305 //////////////////////////////////////////////////////////////////////////