Skip to content

Commit 4229d92

Browse files
committed
[C++] Fix OTF decoding for alignment and floating point numbers when requiring endian conversion. Issue #530 and #506.
1 parent d83374f commit 4229d92

File tree

1 file changed

+140
-54
lines changed

1 file changed

+140
-54
lines changed

sbe-tool/src/main/cpp/otf/Encoding.h

Lines changed: 140 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,20 @@ enum class ByteOrder : int
5757
SBE_BIG_ENDIAN = 1
5858
};
5959

60+
typedef union sbe_float_as_uint_u
61+
{
62+
float fp_value;
63+
std::uint32_t uint_value;
64+
}
65+
sbe_float_as_uint_t;
66+
67+
typedef union sbe_double_as_uint_u
68+
{
69+
double fp_value;
70+
std::uint64_t uint_value;
71+
}
72+
sbe_double_as_uint_t;
73+
6074
/// Constants used for representing primitive types
6175
enum class PrimitiveType : int
6276
{
@@ -102,53 +116,40 @@ inline std::size_t lengthOfType(PrimitiveType type)
102116
switch (type)
103117
{
104118
case PrimitiveType::CHAR:
105-
{
106119
return 1;
107-
}
120+
108121
case PrimitiveType::INT8:
109-
{
110122
return 1;
111-
}
123+
112124
case PrimitiveType::INT16:
113-
{
114125
return 2;
115-
}
126+
116127
case PrimitiveType::INT32:
117-
{
118128
return 4;
119-
}
129+
120130
case PrimitiveType::INT64:
121-
{
122131
return 8;
123-
}
132+
124133
case PrimitiveType::UINT8:
125-
{
126134
return 1;
127-
}
135+
128136
case PrimitiveType::UINT16:
129-
{
130137
return 2;
131-
}
138+
132139
case PrimitiveType::UINT32:
133-
{
134140
return 4;
135-
}
141+
136142
case PrimitiveType::UINT64:
137-
{
138143
return 8;
139-
}
144+
140145
case PrimitiveType::FLOAT:
141-
{
142146
return 4;
143-
}
147+
144148
case PrimitiveType::DOUBLE:
145-
{
146149
return 8;
147-
}
150+
148151
default:
149-
{
150152
return 0;
151-
}
152153
}
153154
}
154155

@@ -167,6 +168,7 @@ class PrimitiveValue
167168
switch (type)
168169
{
169170
case PrimitiveType::CHAR:
171+
{
170172
if (valueLength > 1)
171173
{
172174
m_arrayValue = std::string(value, valueLength);
@@ -178,60 +180,103 @@ class PrimitiveValue
178180
m_size = 1;
179181
}
180182
break;
183+
}
181184

182185
case PrimitiveType::INT8:
183-
m_value.asInt = *(std::int8_t *)value;
184-
m_size = 1;
186+
{
187+
std::int8_t temp;
188+
std::memcpy(&temp, value, sizeof(std::int8_t));
189+
m_value.asInt = temp;
190+
m_size = sizeof(std::int8_t);
185191
break;
192+
}
186193

187194
case PrimitiveType::INT16:
188-
m_value.asInt = *(std::int16_t *)value;
189-
m_size = 2;
195+
{
196+
std::int16_t temp;
197+
std::memcpy(&temp, value, sizeof(std::int16_t));
198+
m_value.asInt = temp;
199+
m_size = sizeof(std::int16_t);
190200
break;
201+
}
191202

192203
case PrimitiveType::INT32:
193-
m_value.asInt = *(std::int32_t *)value;
194-
m_size = 4;
204+
{
205+
std::int32_t temp;
206+
std::memcpy(&temp, value, sizeof(std::int32_t));
207+
m_value.asInt = temp;
208+
m_size = sizeof(std::int32_t);
195209
break;
210+
}
196211

197212
case PrimitiveType::INT64:
198-
m_value.asInt = *(std::int64_t *)value;
199-
m_size = 8;
213+
{
214+
std::int64_t temp;
215+
std::memcpy(&temp, value, sizeof(std::int64_t));
216+
m_value.asInt = temp;
217+
m_size = sizeof(std::int64_t);
200218
break;
219+
}
201220

202221
case PrimitiveType::UINT8:
203-
m_value.asUInt = *(std::uint8_t *)value;
204-
m_size = 1;
222+
{
223+
std::uint8_t temp;
224+
std::memcpy(&temp, value, sizeof(std::uint8_t));
225+
m_value.asInt = temp;
226+
m_size = sizeof(std::uint8_t);
205227
break;
228+
}
206229

207230
case PrimitiveType::UINT16:
208-
m_value.asUInt = *(std::uint16_t *)value;
209-
m_size = 2;
231+
{
232+
std::uint16_t temp;
233+
std::memcpy(&temp, value, sizeof(std::uint16_t));
234+
m_value.asInt = temp;
235+
m_size = sizeof(std::uint16_t);
210236
break;
237+
}
211238

212239
case PrimitiveType::UINT32:
213-
m_value.asUInt = *(std::uint32_t *)value;
214-
m_size = 4;
240+
{
241+
std::uint32_t temp;
242+
std::memcpy(&temp, value, sizeof(std::uint32_t));
243+
m_value.asInt = temp;
244+
m_size = sizeof(std::uint32_t);
215245
break;
246+
}
216247

217248
case PrimitiveType::UINT64:
218-
m_value.asUInt = *(std::uint64_t *)value;
219-
m_size = 8;
249+
{
250+
std::uint64_t temp;
251+
std::memcpy(&temp, value, sizeof(std::uint64_t));
252+
m_value.asInt = temp;
253+
m_size = sizeof(std::uint64_t);
220254
break;
255+
}
221256

222257
case PrimitiveType::FLOAT:
223-
m_value.asDouble = *(float *)value;
224-
m_size = 4;
258+
{
259+
float temp;
260+
std::memcpy(&temp, value, sizeof(float));
261+
m_value.asDouble = temp;
262+
m_size = sizeof(float);
225263
break;
264+
}
226265

227266
case PrimitiveType::DOUBLE:
228-
m_value.asDouble = *(double *)value;
229-
m_size = 8;
267+
{
268+
double temp;
269+
std::memcpy(&temp, value, sizeof(double));
270+
m_value.asDouble = temp;
271+
m_size = sizeof(double);
230272
break;
273+
}
231274

232275
default:
276+
{
233277
m_type = PrimitiveType::NONE;
234278
break;
279+
}
235280
}
236281
}
237282

@@ -314,52 +359,84 @@ class Encoding
314359

315360
static inline std::int8_t getInt8(const char *buffer)
316361
{
317-
return *(std::int8_t *)buffer;
362+
std::int8_t value;
363+
std::memcpy(&value, buffer, sizeof(std::int8_t));
364+
365+
return value;
318366
}
319367

320368
static inline std::int16_t getInt16(const char *buffer, const ByteOrder byteOrder)
321369
{
322-
return SBE_OTF_BYTE_ORDER_16(byteOrder, *(std::int16_t *)buffer);
370+
std::int16_t value;
371+
std::memcpy(&value, buffer, sizeof(std::int16_t));
372+
373+
return SBE_OTF_BYTE_ORDER_16(byteOrder, value);
323374
}
324375

325376
static inline std::int32_t getInt32(const char *buffer, const ByteOrder byteOrder)
326377
{
327-
return SBE_OTF_BYTE_ORDER_32(byteOrder, *(std::int32_t *)buffer);
378+
std::int32_t value;
379+
std::memcpy(&value, buffer, sizeof(std::int32_t));
380+
381+
return SBE_OTF_BYTE_ORDER_32(byteOrder, value);
328382
}
329383

330384
static inline std::int64_t getInt64(const char *buffer, const ByteOrder byteOrder)
331385
{
332-
return SBE_OTF_BYTE_ORDER_64(byteOrder, *(std::int64_t *)buffer);
386+
std::int64_t value;
387+
std::memcpy(&value, buffer, sizeof(std::int64_t));
388+
389+
return SBE_OTF_BYTE_ORDER_64(byteOrder, value);
333390
}
334391

335392
static inline std::uint8_t getUInt8(const char *buffer)
336393
{
337-
return *(std::uint8_t *)buffer;
394+
std::uint8_t value;
395+
std::memcpy(&value, buffer, sizeof(std::uint8_t));
396+
397+
return value;
338398
}
339399

340400
static inline std::uint16_t getUInt16(const char *buffer, const ByteOrder byteOrder)
341401
{
342-
return SBE_OTF_BYTE_ORDER_16(byteOrder, *(std::uint16_t *)buffer);
402+
std::uint16_t value;
403+
std::memcpy(&value, buffer, sizeof(std::uint16_t));
404+
405+
return SBE_OTF_BYTE_ORDER_16(byteOrder, value);
343406
}
344407

345408
static inline std::uint32_t getUInt32(const char *buffer, const ByteOrder byteOrder)
346409
{
347-
return SBE_OTF_BYTE_ORDER_32(byteOrder, *(std::uint32_t *)buffer);
410+
std::uint32_t value;
411+
std::memcpy(&value, buffer, sizeof(std::uint32_t));
412+
413+
return SBE_OTF_BYTE_ORDER_32(byteOrder, value);
348414
}
349415

350416
static inline std::uint64_t getUInt64(const char *buffer, const ByteOrder byteOrder)
351417
{
352-
return SBE_OTF_BYTE_ORDER_64(byteOrder, *(std::uint64_t *)buffer);
418+
std::uint64_t value;
419+
std::memcpy(&value, buffer, sizeof(std::uint64_t));
420+
421+
return SBE_OTF_BYTE_ORDER_64(byteOrder, value);
353422
}
354423

355424
static inline float getFloat(const char *buffer, const ByteOrder byteOrder)
356425
{
357-
return SBE_OTF_BYTE_ORDER_32(byteOrder, *(float *)buffer);
426+
sbe_float_as_uint_t value;
427+
std::memcpy(&value, buffer, sizeof(float));
428+
value.uint_value = SBE_OTF_BYTE_ORDER_32(byteOrder, value.uint_value);
429+
430+
return value.fp_value;
358431
}
359432

360433
static inline double getDouble(const char *buffer, const ByteOrder byteOrder)
361434
{
362-
return SBE_OTF_BYTE_ORDER_64(byteOrder, *(double *)buffer);
435+
sbe_double_as_uint_t value;
436+
std::memcpy(&value, buffer, sizeof(double));
437+
value.uint_value = SBE_OTF_BYTE_ORDER_64(byteOrder, value.uint_value);
438+
439+
return value.fp_value;
363440
}
364441

365442
static inline std::int64_t getInt(const PrimitiveType type, const ByteOrder byteOrder, const char *buffer)
@@ -368,14 +445,19 @@ class Encoding
368445
{
369446
case PrimitiveType::CHAR:
370447
return getChar(buffer);
448+
371449
case PrimitiveType::INT8:
372450
return getInt8(buffer);
451+
373452
case PrimitiveType::INT16:
374453
return getInt16(buffer, byteOrder);
454+
375455
case PrimitiveType::INT32:
376456
return getInt32(buffer, byteOrder);
457+
377458
case PrimitiveType::INT64:
378459
return getInt64(buffer, byteOrder);
460+
379461
default:
380462
throw std::runtime_error("incorrect type for Encoding::getInt");
381463
}
@@ -387,12 +469,16 @@ class Encoding
387469
{
388470
case PrimitiveType::UINT8:
389471
return getUInt8(buffer);
472+
390473
case PrimitiveType::UINT16:
391474
return getUInt16(buffer, byteOrder);
475+
392476
case PrimitiveType::UINT32:
393477
return getUInt32(buffer, byteOrder);
478+
394479
case PrimitiveType::UINT64:
395480
return getUInt64(buffer, byteOrder);
481+
396482
default:
397483
throw std::runtime_error("incorrect type for Encoding::getUInt");
398484
}

0 commit comments

Comments
 (0)