1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
https://github.com/kaitai-io/kaitai_struct_cpp_stl_runtime/commit/c01f5300159a698b6e706caba21e1965d5fc94a7.patch
diff --git a/lib/kaitai/kaitai/kaitaistream.cpp b/lib/kaitai/kaitai/kaitaistream.cpp
index bd914c3..d3b2fcd 100644
--- a/lib/kaitai/kaitai/kaitaistream.cpp
+++ b/lib/kaitai/kaitai/kaitaistream.cpp
@@ -32,10 +32,57 @@
#include <byteswap.h>
#endif
+#include <cstring> // std::memcpy
#include <iostream>
#include <vector>
#include <stdexcept>
+#ifdef KAITAI_STREAM_H_CPP11_SUPPORT
+#include <type_traits> // std::enable_if, std::is_trivially_copyable, std::is_trivially_constructible
+
+// Taken from https://en.cppreference.com/w/cpp/numeric/bit_cast#Possible_implementation
+// (only adjusted for C++11 compatibility)
+template<class To, class From>
+typename std::enable_if<
+ sizeof(To) == sizeof(From) &&
+ std::is_trivially_copyable<From>::value &&
+ std::is_trivially_copyable<To>::value,
+ To
+>::type
+// constexpr support needs compiler magic
+static bit_cast(const From &src) noexcept
+{
+ static_assert(std::is_trivially_constructible<To>::value,
+ "This implementation additionally requires "
+ "destination type to be trivially constructible");
+
+ To dst;
+ std::memcpy(&dst, &src, sizeof(To));
+ return dst;
+}
+#else
+// The following implementation of `StaticAssert` was inspired by https://stackoverflow.com/a/6765840
+
+// empty default template
+template <bool b>
+struct StaticAssert;
+
+// template specialized on true
+template <>
+struct StaticAssert<true> {};
+
+template<class To, class From>
+To
+static bit_cast(const From &src)
+{
+ StaticAssert<sizeof(To) == sizeof(From)>();
+
+ To dst;
+ std::memcpy(&dst, &src, sizeof(To));
+ return dst;
+}
+#endif
+
kaitai::kstream::kstream(std::istream *io) {
m_io = io;
init();
@@ -263,7 +310,7 @@ float kaitai::kstream::read_f4be() {
#if __BYTE_ORDER == __LITTLE_ENDIAN
t = bswap_32(t);
#endif
- return reinterpret_cast<float &>(t);
+ return bit_cast<float>(t);
}
double kaitai::kstream::read_f8be() {
@@ -272,7 +319,7 @@ double kaitai::kstream::read_f8be() {
#if __BYTE_ORDER == __LITTLE_ENDIAN
t = bswap_64(t);
#endif
- return reinterpret_cast<double &>(t);
+ return bit_cast<double>(t);
}
// ........................................................................
@@ -285,7 +332,7 @@ float kaitai::kstream::read_f4le() {
#if __BYTE_ORDER == __BIG_ENDIAN
t = bswap_32(t);
#endif
- return reinterpret_cast<float &>(t);
+ return bit_cast<float>(t);
}
double kaitai::kstream::read_f8le() {
@@ -294,7 +341,7 @@ double kaitai::kstream::read_f8le() {
#if __BYTE_ORDER == __BIG_ENDIAN
t = bswap_64(t);
#endif
- return reinterpret_cast<double &>(t);
+ return bit_cast<double>(t);
}
// ========================================================================
diff --git a/lib/kaitai/kaitai/kaitaistream.h b/lib/kaitai/kaitai/kaitaistream.h
index c8b5a3a..d58ae8e 100644
--- a/lib/kaitai/kaitai/kaitaistream.h
+++ b/lib/kaitai/kaitai/kaitaistream.h
@@ -4,6 +4,11 @@
// Kaitai Struct runtime API version: x.y.z = 'xxxyyyzzz' decimal
#define KAITAI_STRUCT_VERSION 11000L
+// check for C++11 support - https://stackoverflow.com/a/40512515
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
+#define KAITAI_STREAM_H_CPP11_SUPPORT
+#endif
+
#include <istream>
#include <sstream>
#include <stdint.h>
|