1414#include < libLCE.h>
1515
1616namespace lce ::io {
17- enum class ByteOrder { BIG, LITTLE };
18-
19- template <typename T> constexpr T swapOrder_f (const T input) {
20- uint8_t resultBytes[sizeof (T)];
21- const uint8_t *ib = reinterpret_cast <const uint8_t *>(&input);
22- uint8_t *r = resultBytes + (sizeof (T) - 1 );
23-
24- for (size_t i = 0 ; i < sizeof (T); ++i) {
25- *r-- = *ib++;
26- }
27-
28- T result;
29- memcpy (&result, resultBytes, sizeof (T));
30- return result;
31- }
32-
33- // this is a mess but theoretically will actually use the byteswap
34- // instruction
35- template <typename T> constexpr T swapOrder (const T input) {
36- if constexpr (std::is_integral_v<T>) {
37- if constexpr (sizeof (T) == 2 ) {
38- #if defined(__clang__) || defined(__GNUC__)
39- return static_cast <T>(
40- __builtin_bswap16 (static_cast <uint16_t >(input)));
41- #elif defined(_MSC_VER)
42- return static_cast <T>(
43- _byteswap_ushort (static_cast <unsigned short >(input)));
44- #else
45- return swapOrder_f (input);
46- #endif
47- } else if constexpr (sizeof (T) == 4 ) {
48- #if defined(__clang__) || defined(__GNUC__)
49- return static_cast <T>(
50- __builtin_bswap32 (static_cast <uint32_t >(input)));
51- #elif defined(_MSC_VER)
52- return static_cast <T>(
53- _byteswap_ulong (static_cast <unsigned long >(input)));
54- #else
55- return swapOrder_f (input);
56- #endif
57- } else if constexpr (sizeof (T) == 8 ) {
58- #if defined(__clang__) || defined(__GNUC__)
59- return static_cast <T>(
60- __builtin_bswap64 (static_cast <uint64_t >(input)));
61- #elif defined(_MSC_VER)
62- return static_cast <T>(
63- _byteswap_uint64 (static_cast <unsigned __int64>(input)));
64- #else
65- return swapOrder_f (input);
66- #endif
67- } else {
68- return swapOrder_f (input);
69- }
70- } else {
71- return swapOrder_f (input);
72- }
73- }
74-
75- template <typename T> constexpr T big2sys (const T a) {
76- #ifdef BR_BIG_ENDIAN
77- return a;
78- #else
79- return swapOrder (a);
80- #endif
81- }
82-
83- template <typename T>
84- constexpr T little2sys (const T a) { // also is working as sys2little
85- #ifdef BR_BIG_ENDIAN
86- return swapOrder (a);
87- #else
88- return a;
89- #endif
90- }
17+ /* * Byte Order/Endian dictates which way bytes are written */
18+ enum class ByteOrder {
19+ BIG, /* *< Big Endian | Writes 0xA1B2C3D4 */
20+ LITTLE /* *< Little Endian | Writes 0xD4C3B2A1 */
21+ };
9122
92- // todo: implement size shits
23+ /* * Unsized reader/writer for a byte array */
9324 class BinaryIO {
9425 public:
95- explicit BinaryIO (uint8_t *input, size_t size = 0 );
26+ explicit BinaryIO (uint8_t *input);
9627 explicit BinaryIO (size_t size);
9728
9829 // ~BinaryIO();
@@ -101,25 +32,70 @@ namespace lce::io {
10132 void seekRelative (size_t offset);
10233
10334 // reading
35+ /* * Reads an unsigned byte (uint8_t)
36+ *
37+ * @returns The byte
38+ *
39+ * @see readSignedByte() for reading a signed byte
40+ */
10441 uint8_t readByte ();
42+ /* * Reads a signed byte (int8_t)
43+ *
44+ * @returns The signed byte
45+ *
46+ * @see readByte() for reading an unsigned byte
47+ */
10548 int8_t readSignedByte ();
10649
50+ /* * Reads an unsigned 24-bit integer
51+ *
52+ * @returns The unsigned 24-bit integer
53+ *
54+ * @see readInt24() for reading a signed 24-bit integer
55+ */
10756 uint32_t readUint24 (io::ByteOrder endian);
10857
109- int32_t readInt24 (io::ByteOrder endian);
110-
58+ /* * Reads a signed 24-bit integer
59+ *
60+ * @returns The signed 24-bit integer
61+ *
62+ * @see readInt24() for reading an unsigned 24-bit integer
63+ */
64+ int32_t readInt24 (ByteOrder endian);
65+
66+ /* * Reads a value the size of the given type as Little Endian
67+ *
68+ * @returns The value
69+ *
70+ * @see readBE() for reading a Big Endian value
71+ */
11172 template <typename T> T readLE () {
11273 const T v = little2sys (*reinterpret_cast <const T *>(this ->mData ));
11374 this ->mData += sizeof (T);
11475 return v;
11576 }
11677
78+ /* * Reads a value the size of the given type as Big Endian
79+ *
80+ * @returns The value
81+ *
82+ * @see readLE() for reading a Little Endian value
83+ */
11784 template <typename T> T readBE () {
11885 const T v = big2sys (*reinterpret_cast <const T *>(this ->mData ));
11986 this ->mData += sizeof (T);
12087 return v;
12188 }
12289
90+ /* * Reads a value the size of the given type using the given endian/byte
91+ * order
92+ *
93+ * @param endian The byte order to read as
94+ * @returns The value
95+ *
96+ * @see readBE() for reading a Big Endian value
97+ * @see readLE() for reading a Little Endian value
98+ */
12399 template <typename T> T read (const io::ByteOrder endian) {
124100 T v;
125101 if (endian == io::ByteOrder::LITTLE)
@@ -210,10 +186,82 @@ namespace lce::io {
210186 static LIBLCE_API std::string wstringToString (const std::wstring &str);
211187 static LIBLCE_API std::wstring stringToWString (const std::string &str);
212188
189+ template <typename T> constexpr T swapOrder_f (const T input) {
190+ uint8_t resultBytes[sizeof (T)];
191+ const uint8_t *ib = reinterpret_cast <const uint8_t *>(&input);
192+ uint8_t *r = resultBytes + (sizeof (T) - 1 );
193+
194+ for (size_t i = 0 ; i < sizeof (T); ++i) {
195+ *r-- = *ib++;
196+ }
197+
198+ T result;
199+ memcpy (&result, resultBytes, sizeof (T));
200+ return result;
201+ }
202+
203+ // this is a mess but theoretically will actually use the byteswap
204+ // instruction
205+ template <typename T> constexpr T swapOrder (const T input) {
206+ if constexpr (std::is_integral_v<T>) {
207+ if constexpr (sizeof (T) == 2 ) {
208+ #if defined(__clang__) || defined(__GNUC__)
209+ return static_cast <T>(
210+ __builtin_bswap16 (static_cast <uint16_t >(input)));
211+ #elif defined(_MSC_VER)
212+ return static_cast <T>(
213+ _byteswap_ushort (static_cast <unsigned short >(input)));
214+ #else
215+ return swapOrder_f (input);
216+ #endif
217+ } else if constexpr (sizeof (T) == 4 ) {
218+ #if defined(__clang__) || defined(__GNUC__)
219+ return static_cast <T>(
220+ __builtin_bswap32 (static_cast <uint32_t >(input)));
221+ #elif defined(_MSC_VER)
222+ return static_cast <T>(
223+ _byteswap_ulong (static_cast <unsigned long >(input)));
224+ #else
225+ return swapOrder_f (input);
226+ #endif
227+ } else if constexpr (sizeof (T) == 8 ) {
228+ #if defined(__clang__) || defined(__GNUC__)
229+ return static_cast <T>(
230+ __builtin_bswap64 (static_cast <uint64_t >(input)));
231+ #elif defined(_MSC_VER)
232+ return static_cast <T>(
233+ _byteswap_uint64 (static_cast <unsigned __int64>(input)));
234+ #else
235+ return swapOrder_f (input);
236+ #endif
237+ } else {
238+ return swapOrder_f (input);
239+ }
240+ } else {
241+ return swapOrder_f (input);
242+ }
243+ }
244+
245+ template <typename T> constexpr T big2sys (const T a) {
246+ #ifdef BR_BIG_ENDIAN
247+ return a;
248+ #else
249+ return swapOrder (a);
250+ #endif
251+ }
252+
253+ template <typename T>
254+ constexpr T little2sys (const T a) { // also is working as sys2little
255+ #ifdef BR_BIG_ENDIAN
256+ return swapOrder (a);
257+ #else
258+ return a;
259+ #endif
260+ }
261+
213262 private:
214- uint8_t *mOrigin ;
215- uint8_t *mData ;
216- size_t mSize ;
263+ uint8_t *mOrigin ; /* *< Data origin */
264+ uint8_t *mData ; /* *< Data pointer, holds where we are in the array */
217265 };
218266} // namespace lce::io
219267
0 commit comments