Branch data TLA Line data Source code
1 : : // Copyright (c) 2014-2022 Thomas Fussell
2 : : // Copyright (c) 2024-2025 xlnt-community
3 : : //
4 : : // Permission is hereby granted, free of charge, to any person obtaining a copy
5 : : // of this software and associated documentation files (the "Software"), to deal
6 : : // in the Software without restriction, including without limitation the rights
7 : : // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : : // copies of the Software, and to permit persons to whom the Software is
9 : : // furnished to do so, subject to the following conditions:
10 : : //
11 : : // The above copyright notice and this permission notice shall be included in
12 : : // all copies or substantial portions of the Software.
13 : : //
14 : : // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : : // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : : // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : : // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : : // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : : // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : : // THE SOFTWARE
21 : : //
22 : : // @license: http://www.opensource.org/licenses/mit-license.php
23 : : // @author: see AUTHORS file
24 : :
25 : : #pragma once
26 : :
27 : : #include <cstdint>
28 : : #include <cstring>
29 : : #include <iostream>
30 : : #include <vector>
31 : :
32 : : #include <xlnt/utils/exceptions.hpp>
33 : :
34 : : namespace xlnt {
35 : : namespace detail {
36 : :
37 : : using byte = std::uint8_t;
38 : :
39 : : template<typename T>
40 : : class binary_reader
41 : : {
42 : : public:
43 : : binary_reader() = delete;
44 : :
45 :CBC 6002 : binary_reader(const std::vector<T> &vector)
46 : 6002 : : vector_(&vector),
47 : 6002 : data_(nullptr),
48 : 6002 : size_(0)
49 : : {
50 : 6002 : }
51 : :
52 : : binary_reader(const T *source_data, std::size_t size)
53 : : : vector_(nullptr),
54 : : data_(source_data),
55 : : size_(size)
56 : : {
57 : : }
58 : :
59 : : binary_reader(const binary_reader &other) = default;
60 : :
61 : : binary_reader &operator=(const binary_reader &other)
62 : : {
63 : : vector_ = other.vector_;
64 : : offset_ = other.offset_;
65 : : data_ = other.data_;
66 : :
67 : : return *this;
68 : : }
69 : :
70 : 6002 : ~binary_reader()
71 : : {
72 : 6002 : }
73 : :
74 : 13516 : const T *data() const
75 : : {
76 [ - + ]: 13516 : return vector_ == nullptr ? data_ : vector_->data();
77 : : }
78 : :
79 : 297 : void offset(std::size_t offset)
80 : : {
81 : 297 : offset_ = offset;
82 : 297 : }
83 : :
84 : 27140 : std::size_t offset() const
85 : : {
86 : 27140 : return offset_;
87 : : }
88 : :
89 : 986 : void reset()
90 : : {
91 : 986 : offset_ = 0;
92 : 986 : }
93 : :
94 : : template<typename U>
95 : : U read()
96 : : {
97 : : return read_reference<U>();
98 : : }
99 : :
100 : : template<typename U>
101 : : const U *read_pointer()
102 : : {
103 : : const auto result = reinterpret_cast<const U *>(data() + offset_);
104 : : offset_ += sizeof(U) / sizeof(T);
105 : :
106 : : return result;
107 : : }
108 : :
109 : : template<typename U>
110 : : const U &read_reference()
111 : : {
112 : : return *read_pointer<U>();
113 : : }
114 : :
115 : : template<typename U>
116 : : std::vector<U> as_vector() const
117 : : {
118 : : auto result = std::vector<T>(bytes() / sizeof(U), U());
119 : : std::memcpy(result.data(), data(), bytes());
120 : :
121 : : return result;
122 : : }
123 : :
124 : : template<typename U>
125 : : std::vector<U> read_vector(std::size_t count)
126 : : {
127 : : auto result = std::vector<U>(count, U());
128 : : std::memcpy(result.data(), data() + offset_, count * sizeof(U));
129 : : offset_ += count * sizeof(T) / sizeof(U);
130 : :
131 : : return result;
132 : : }
133 : :
134 : 13516 : std::size_t count() const
135 : : {
136 [ + - ]: 13516 : return vector_ != nullptr ? vector_->size() : size_;
137 : : }
138 : :
139 : 13516 : std::size_t bytes() const
140 : : {
141 : 13516 : return count() * sizeof(T);
142 : : }
143 : :
144 : : private:
145 : : std::size_t offset_ = 0;
146 : : const std::vector<T> *vector_ = nullptr;
147 : : const T *data_ = nullptr;
148 : : const std::size_t size_ = 0;
149 : : };
150 : :
151 : : template<typename T>
152 : : class binary_writer
153 : : {
154 : : public:
155 : 304 : binary_writer(std::vector<T> &bytes)
156 : 304 : : data_(&bytes)
157 : : {
158 : 304 : }
159 : :
160 : : binary_writer(const binary_writer &other)
161 : : {
162 : : *this = other;
163 : : }
164 : :
165 : 304 : ~binary_writer()
166 : : {
167 : 304 : }
168 : :
169 : : binary_writer &operator=(const binary_writer &other)
170 : : {
171 : : data_ = other.data_;
172 : : offset_ = other.offset_;
173 : :
174 : : return *this;
175 : : }
176 : :
177 : : std::vector<T> &data()
178 : : {
179 : : return *data_;
180 : : }
181 : :
182 : : // Make the bytes of the data pointed to by this writer equivalent to those in the given vector
183 : : // sizeof(U) should be a multiple of sizeof(T)
184 : : template<typename U>
185 : : void assign(const std::vector<U> &ints)
186 : : {
187 : : resize(ints.size() * sizeof(U));
188 : : std::memcpy(data_->data(), ints.data(), bytes());
189 : : }
190 : :
191 : : // Make the bytes of the data pointed to by this writer equivalent to those in the given string
192 : : // sizeof(U) should be a multiple of sizeof(T)
193 : : template<typename U>
194 : 25 : void assign(const std::basic_string<U> &string)
195 : : {
196 : 25 : resize(string.size() * sizeof(U));
197 : 25 : std::memcpy(data_->data(), string.data(), bytes());
198 : 25 : }
199 : :
200 : : void offset(std::size_t new_offset)
201 : : {
202 : : offset_ = new_offset;
203 : : }
204 : :
205 : 2957 : std::size_t offset() const
206 : : {
207 : 2957 : return offset_;
208 : : }
209 : :
210 : 2264 : void reset()
211 : : {
212 : 2264 : offset_ = 0;
213 : 2264 : data_->clear();
214 : 2264 : }
215 : :
216 : : template<typename U>
217 : 48 : void write(U value)
218 : : {
219 : 48 : const auto num_bytes = sizeof(U);
220 : 48 : const auto remaining_bytes = bytes() - offset() * sizeof(T);
221 : :
222 [ + - ]: 48 : if (remaining_bytes < num_bytes)
223 : : {
224 : 48 : extend((num_bytes - remaining_bytes) / sizeof(T));
225 : : }
226 : :
227 : 48 : std::memcpy(data_->data() + offset(), &value, num_bytes);
228 : 48 : offset_ += num_bytes / sizeof(T);
229 : 48 : }
230 : :
231 : 5843 : std::size_t count() const
232 : : {
233 : 5843 : return data_->size();
234 : : }
235 : :
236 : 2934 : std::size_t bytes() const
237 : : {
238 : 2934 : return count() * sizeof(T);
239 : : }
240 : :
241 : 25 : void resize(std::size_t new_size, byte fill = 0)
242 : : {
243 : 25 : data_->resize(new_size, fill);
244 : 25 : }
245 : :
246 : 2909 : void extend(std::size_t amount, byte fill = 0)
247 : : {
248 [ + ]: 2909 : data_->resize(count() + amount, fill);
249 : 2909 : }
250 : :
251 : : std::vector<byte>::iterator iterator()
252 : : {
253 : : return data_->begin() + static_cast<std::ptrdiff_t>(offset());
254 : : }
255 : :
256 : : template<typename U>
257 : 2687 : void append(const std::vector<U> &data)
258 : : {
259 : 2687 : binary_reader<U> reader(data);
260 [ + ]: 2687 : append(reader, data.size() * sizeof(U));
261 : 2687 : }
262 : :
263 : : template<typename U>
264 : 2861 : void append(binary_reader<U> &reader, std::size_t reader_element_count)
265 : : {
266 : 2861 : const auto num_bytes = sizeof(U) * reader_element_count;
267 : 2861 : const auto remaining_bytes = bytes() - offset() * sizeof(T);
268 : :
269 [ + - ]: 2861 : if (remaining_bytes < num_bytes)
270 : : {
271 : 2861 : extend((num_bytes - remaining_bytes) / sizeof(T));
272 : : }
273 : :
274 [ - + ]: 2861 : if ((reader.offset() + reader_element_count) * sizeof(U) > reader.bytes())
275 : : {
276 [ # # ]:UBC 0 : throw xlnt::exception("reading past end");
277 : : }
278 : :
279 :CBC 2861 : std::memcpy(data_->data() + offset_, reader.data() + reader.offset(), reader_element_count * sizeof(U));
280 : 2861 : offset_ += reader_element_count * sizeof(U) / sizeof(T);
281 : 2861 : }
282 : :
283 : : private:
284 : : std::vector<T> *data_ = nullptr;
285 : : std::size_t offset_ = 0;
286 : : };
287 : :
288 : : template<typename T>
289 : 25 : std::vector<byte> string_to_bytes(const std::basic_string<T> &string)
290 : : {
291 : 25 : std::vector<byte> bytes;
292 : 25 : binary_writer<byte> writer(bytes);
293 [ + ]: 25 : writer.assign(string);
294 : :
295 : 25 : return bytes;
296 : 25 : }
297 : :
298 : : template<typename T>
299 : 244 : T read(std::istream &in)
300 : : {
301 : : T result;
302 [ + ]: 244 : in.read(reinterpret_cast<char *>(&result), sizeof(T));
303 : :
304 : 244 : return result;
305 : : }
306 : :
307 : : template<typename T>
308 : 45 : std::vector<T> read_vector(std::istream &in, std::size_t count)
309 : : {
310 [ + ]: 45 : std::vector<T> result(count, T());
311 [ + ]: 45 : in.read(reinterpret_cast<char *>(&result[0]),
312 : : static_cast<std::streamsize>(sizeof(T) * count));
313 : :
314 : 45 : return result;
315 :UBC 0 : }
316 : :
317 : : template<typename T>
318 :CBC 15 : std::basic_string<T> read_string(std::istream &in, std::size_t count)
319 : : {
320 [ + ]: 15 : std::basic_string<T> result(count, T());
321 [ + ]: 15 : in.read(reinterpret_cast<char *>(&result[0]),
322 : 15 : static_cast<std::streamsize>(sizeof(T) * count));
323 : :
324 : 15 : return result;
325 :UBC 0 : }
326 : :
327 : : } // namespace detail
328 : : } // namespace xlnt
|