Branch data Line data Source code
1 : : #pragma once
2 : :
3 : : /*
4 : : MIT License
5 : :
6 : : Copyright (c) 2014-2024 Stephane Cuillerdier (aka aiekick)
7 : :
8 : : Permission is hereby granted, free of charge, to any person obtaining a copy
9 : : of this software and associated documentation files (the "Software"), to deal
10 : : in the Software without restriction, including without limitation the rights
11 : : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 : : copies of the Software, and to permit persons to whom the Software is
13 : : furnished to do so, subject to the following conditions:
14 : :
15 : : The above copyright notice and this permission notice shall be included in all
16 : : copies or substantial portions of the Software.
17 : :
18 : : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 : : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 : : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 : : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 : : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 : : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 : : SOFTWARE.
25 : : */
26 : :
27 : : // ezBinBuf is part of the ezLibs project : https://github.com/aiekick/ezLibs.git
28 : :
29 : : #include <vector>
30 : : #include <cstdint>
31 : : #include <cstring>
32 : : #include <stdexcept>
33 : : #include <type_traits>
34 : :
35 : : namespace ez {
36 : : class BinBuf {
37 : : public:
38 : : // pos is BYTES count
39 : :
40 : : ///////////////////////////////////////////////////
41 : : ////// LITTLE / BIG ENDIAN INTERFACE //////////////
42 : : ///////////////////////////////////////////////////
43 : :
44 : : template <typename T>
45 : 3 : size_t writeValueLE(const T& value) {
46 : 3 : return m_writeValue<T>(value, false);
47 : 3 : }
48 : :
49 : : template <typename T>
50 : 1 : size_t writeValueBE(const T& value) {
51 : 1 : return m_writeValue<T>(value, true);
52 : 1 : }
53 : :
54 : : template <typename T>
55 : 1 : size_t writeArrayLE(const T* data, size_t count) {
56 : 1 : return m_writeArray<T>(data, count, false);
57 : 1 : }
58 : :
59 : : template <typename T>
60 : 1 : size_t writeArrayBE(const T* data, size_t count) {
61 : 1 : return m_writeArray<T>(data, count, true);
62 : 1 : }
63 : :
64 : : template <typename T>
65 : 2 : T readValueLE(size_t& pos) const {
66 : 2 : return m_readValue<T>(pos, false);
67 : 2 : }
68 : :
69 : : template <typename T>
70 : 1 : T readValueBE(size_t& pos) const {
71 : 1 : return m_readValue<T>(pos, true);
72 : 1 : }
73 : :
74 : : template <typename T>
75 : 1 : void readArrayLE(size_t& pos, T* out, size_t count) const {
76 : 1 : m_readArray<T>(pos, out, count, false);
77 : 1 : }
78 : :
79 : : template <typename T>
80 : 1 : void readArrayBE(size_t& pos, T* out, size_t count) const {
81 : 1 : m_readArray<T>(pos, out, count, true);
82 : 1 : }
83 : :
84 : : ///////////////////////////////////////////////////
85 : : ////// GESTION DU BUFFER //////////////////////////
86 : : ///////////////////////////////////////////////////
87 : :
88 : 1 : void setDatas(const std::vector<uint8_t>& vDatas) { m_buffer = vDatas; }
89 : 1 : const std::vector<uint8_t>& getDatas() const { return m_buffer; }
90 : 1 : void clear() { m_buffer.clear(); }
91 : 2 : size_t size() const { return m_buffer.size(); }
92 : 1 : void reserve(size_t capacity) { m_buffer.reserve(capacity); }
93 : :
94 : 3 : uint8_t operator[](size_t index) const {
95 [ + + ]: 3 : if (index >= m_buffer.size()) {
96 : 1 : throw std::out_of_range("BinBuf index out of range");
97 : 1 : }
98 : 2 : return m_buffer[index];
99 : 3 : }
100 : :
101 : 3 : uint8_t& at(size_t index) {
102 [ + + ]: 3 : if (index >= m_buffer.size()) {
103 : 1 : throw std::out_of_range("BinBuf index out of range");
104 : 1 : }
105 : 2 : return m_buffer.at(index);
106 : 3 : }
107 : :
108 : : private:
109 : : std::vector<uint8_t> m_buffer;
110 : :
111 : : ///////////////////////////////////////////////////
112 : : ////// FONCTIONS INTERNES FACTORISÉES /////////////
113 : : ///////////////////////////////////////////////////
114 : :
115 [ + + ]: 49 : inline size_t m_endianIndex(size_t i, size_t size, bool bigEndian) const { return bigEndian ? (size - 1 - i) : i; }
116 : :
117 : : template <typename T>
118 : 9 : size_t m_writeValue(const T& value, bool bigEndian) {
119 : 9 : static_assert(std::is_arithmetic<T>::value, "Only arithmetic types supported");
120 : 9 : const uint8_t* ptr = reinterpret_cast<const uint8_t*>(&value);
121 [ + + ][ + + ]: 36 : for (size_t i = 0; i < sizeof(T); ++i) {
[ + + ][ + + ]
122 : 27 : m_buffer.push_back(ptr[m_endianIndex(i, sizeof(T), bigEndian)]);
123 : 27 : }
124 : 9 : return m_buffer.size();
125 : 9 : }
126 : :
127 : : template <typename T>
128 : 2 : size_t m_writeArray(const T* data, size_t count, bool bigEndian) {
129 [ + + ][ + + ]: 7 : for (size_t i = 0; i < count; ++i) {
130 : 5 : m_writeValue<T>(data[i], bigEndian);
131 : 5 : }
132 : 2 : return m_buffer.size();
133 : 2 : }
134 : :
135 : : template <typename T>
136 : 8 : T m_readValue(size_t& pos, bool bigEndian) const {
137 : 8 : static_assert(std::is_arithmetic<T>::value, "Only arithmetic types supported");
138 [ - + ][ + - ]: 8 : if (pos + sizeof(T) > m_buffer.size()) {
[ - + ][ - + ]
139 : 1 : throw std::out_of_range("Read position out of bounds");
140 : 1 : }
141 : :
142 : 7 : T result = 0;
143 : 7 : uint8_t* ptr = reinterpret_cast<uint8_t*>(&result);
144 [ + + ][ + + ]: 29 : for (size_t i = 0; i < sizeof(T); ++i) {
[ + + ][ # # ]
145 : 22 : ptr[i] = m_buffer[pos + m_endianIndex(i, sizeof(T), bigEndian)];
146 : 22 : }
147 : 7 : pos += sizeof(T);
148 : 7 : return result;
149 : 8 : }
150 : :
151 : : template <typename T>
152 : 2 : void m_readArray(size_t& pos, T* out, size_t count, bool bigEndian) const {
153 [ + + ][ + + ]: 7 : for (size_t i = 0; i < count; ++i) {
154 : 5 : out[i] = m_readValue<T>(pos, bigEndian);
155 : 5 : }
156 : 2 : }
157 : : };
158 : :
159 : :
160 : : } // namespace ez
|