API Documentation
Loading...
Searching...
No Matches
BinaryFile.h
Go to the documentation of this file.
1/*--------------------------------------------------------------------------------------------
2Copyright (c) 2019, NDEVR LLC
3tyler.parke@ndevr.org
4 __ __ ____ _____ __ __ _______
5 | \ | | | __ \ | ___|\ \ / / | __ \
6 | \ | | | | \ \ | |___ \ \ / / | |__) |
7 | . \| | | |__/ / | |___ \ V / | _ /
8 | |\ |_|_____/__|_____|___\_/____| | \ \
9 |__| \__________________________________| \__\
10
11Subject to the terms of the Enterprise+ Agreement, NDEVR hereby grants
12Licensee a limited, non-exclusive, non-transferable, royalty-free license
13(without the right to sublicense) to use the API solely for the purpose of
14Licensee's internal development efforts to develop applications for which
15the API was provided.
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25DEALINGS IN THE SOFTWARE.
26
27Library: Base
28File: BinaryFile
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include "DLLInfo.h"
34#include <NDEVR/File.h>
35#include <NDEVR/String.h>
36#include <NDEVR/Dictionary.h>
37#include <NDEVR/Bounds.h>
38#include <NDEVR/Compressor.h>
39#include <fstream>
40namespace NDEVR
41{
42 /**----------------------------------------------------------------------------
43 Converts an object from big endian to little endian. Does not consider structue
44 of object so will need to be called for each sub-part of a non-primitive type
45 ----------------------------------------------------------------------------*/
46 template <class t_type>
47 t_type ChangeEndian(t_type in)
48 {
49 char* const p = reinterpret_cast<char*>(&in);
50 for (size_t i = 0; i < sizeof(t_type) / 2; ++i)
51 std::swap(p[i], p[sizeof(t_type) - i - 1]);
52 return in;
53 }
54 /**----------------------------------------------------------------------------
55 \brief Logic for reading or writing to a binary file including logic for
56 compressing or decompressing the file
57 ----------------------------------------------------------------------------*/
59 {
60 public:
61
62 explicit BinaryFile(const File& file)
63 : m_file(file)
64 {}
66 {
67 close();
68 }
69 void open(bool read, bool safe)
70 {
71 m_is_read = read;
72 if (read)
73 m_file.open(safe ? File::e_binary_read_safe : File::e_binary_read);
74 else
75 m_file.open(safe ? File::e_binary_write_safe : File::e_binary_write);
76 }
77 void cachedOpen(bool read)
78 {
79 m_is_read = read;
80 m_using_cache = true;
81 m_cache_location = 0;
82 if (read)
83 {
84 m_file.open(File::e_binary_read);
85 m_file.invalidateCache();
86 uint08 size = m_file.fileSize();
87 m_cached_data.setSize(size);
88 fread(m_cached_data.begin(), 1, m_cached_data.size(), m_file.filePtr());
89 m_file.close();
90 }
91 else
92 {
93 m_cached_data.clear();
94 }
95
96 }
97 void close()
98 {
99 if (m_is_read)
100 {
101 if (!m_using_cache)
102 m_file.close();
103 else if (m_multitreaded_compression)
104 uncompressAll();
105 }
106 else
107 {
108 if (m_using_cache)
109 {
110 m_file.open(File::e_binary_write);
111 fwrite(m_cached_data.begin(), 1, m_cached_data.size(), m_file.filePtr());
112 m_file.close();
113 }
114 }
115
116 }
118 {
119 return m_cached_data;
120 }
121 //Data writing
122 template<class t_type>
123 void write(const t_type& data)
124 {
125 if (m_using_cache)
126 {
127
128 if (m_cache_location == m_cached_data.size())
129 m_cached_data.addAll((uint01*)&data, sizeof(data));
130 else
131 m_cached_data.setAll((uint01*)&data, m_cache_location, sizeof(data));
132 m_cache_location += sizeof(data);
133 }
134 else
135 {
136 fwrite(&data, sizeof(t_type), 1, m_file.filePtr());
137 }
138
139 }
140
141 template<class t_type, class t_index_type, class t_memory_allocator, class t_memory_manager>
142 typename std::enable_if<!ObjectInfo<t_type>::Buffer>::type write(const Buffer<t_type, t_index_type, t_memory_allocator, t_memory_manager>& data, CompressionMode compression_mode)
143 {
144 if (data.size() != 0)
145 {
146 BinaryCompressionObject binary = createCompressionObject();
147 binary.buffer_size = data.size();
148 binary.compression_mode = Compressor::PickCompressionMode<t_type>(compression_mode);
149 binary.uncompressed_data = (uint01*)data.ptr();
150 binary.uncompressed_size = data.memSize();
152 {
153 m_compressed_data.setSize(sizeof(Bounds<1, uint04>));
154 binary.compressed_size = sizeof(Bounds<1, uint04>);
155 }
156 else if (binary.compression_mode == e_string_reference)
157 {
158 m_compressed_data.clear();
159 binary.compressed_size = 0;
160 }
161 else
162 {
163 m_compressed_data.setSize(data.memSize());
164 binary.compressed_size = data.memSize();
165 }
166 binary.compressed_data = m_compressed_data.begin();
167 Compressor::CompressData(binary);
168 writeCompression(binary);
169 }
170 else
171 {
172 //lib_assert(m_large_compression || cast<uint08>(data.size()) < cast<uint08>(cast<uint04>::Max), "Bad Data write");
173 if (m_large_compression)
174 write(cast<uint08>(data.size()));
175 else
176 write(cast<uint04>(data.size()));
177 }
178 }
179 template<class t_type, class t_index_type, class t_memory_allocator, class t_memory_manager>
180 typename std::enable_if<ObjectInfo<t_type>::Buffer>::type write(const Buffer<t_type, t_index_type, t_memory_allocator, t_memory_manager>& data, CompressionMode compression_mode)
181 {
182 uint04 total_size = 0;
183 Buffer<uint04> sizes;
184 sizes.setSize(data.size());
185 for (uint04 i = 0; i < data.size(); i++)
186 {
187 uint04 size = data[i].size();;
188 sizes[i] = size;
189 total_size += size;
190 }
191 Buffer<decltype(t_type::Type())> combined_data(total_size);
192 for (uint04 i = 0; i < data.size(); i++)
193 {
194 combined_data.addAll(data[i]);
195 }
196 write(sizes, compression_mode);
197 write(combined_data, compression_mode);
198 }
199 void writeRawData(const String& data, uint04 size, char fill_space = '\0')
200 {
201 if (m_using_cache)
202 {
203
204 if (m_cache_location == m_cached_data.size())
205 m_cached_data.addAll((uint01*)data.begin(), getMin(data.size(), size));
206 else
207 m_cached_data.setAll((uint01*)data.begin(), m_cache_location, getMin(data.size(), size));
208 m_cache_location += getMin(data.size(), size);
209 if (size > data.size())
210 {
211 uint04 add_size = size - data.size();
212 if (m_cache_location == m_cached_data.size())
213 m_cached_data.setAllToValue(fill_space, m_cache_location, add_size);
214 else
215 m_cached_data.addAndFillSpace(add_size, fill_space);
216 m_cache_location += add_size;
217 }
218
219 }
220 else
221 {
222 fwrite(data.begin(), data.size(), 1, m_file.filePtr());
223 if (size > data.size())
224 {
225 uint04 add_size = size - data.size();
226 for(uint04 i = 0; i < add_size; i++)
227 fwrite(&fill_space, add_size, 1, m_file.filePtr());
228 }
229 }
230 }
231 //data reading
232 template<class t_type>
233 t_type read()
234 {
235 t_type data;
236 if (m_using_cache)
237 {
238 data = *((t_type*)(&m_cached_data[m_cache_location]));
239 m_cache_location += cast<uint08>(sizeof(t_type));
240 }
241 else
242 {
243 fread(&data, sizeof(t_type), 1, m_file.filePtr());
244 }
245 return data;
246 }
247 void readString(String& string, char terminator = '\0')
248 {
249 if (m_using_cache)
250 {
251 for (;;)
252 {
253 char c = *((char*)(&m_cached_data[m_cache_location++]));
254 if (c == terminator || m_cache_location >= m_cached_data.size())
255 return;
256 string.add(c);
257 }
258 }
259 else
260 {
261 for (;;)
262 {
263 char c = cast<char>(fgetc(m_file.filePtr()));
264 if (c == terminator || feof(m_file.filePtr()))
265 return;
266 string.add(c);
267 }
268 }
269 }
270 uint04 readString(char* string, char terminator = '\0')
271 {
272 uint04 size = 0;
273 if (m_using_cache)
274 {
275 for (;;)
276 {
277 char c = *((char*)(&m_cached_data[m_cache_location++]));
278 if (c == terminator || m_cache_location >= m_cached_data.size())
279 break;
280 string[size++] = c;
281 }
282 }
283 else
284 {
285 for (;;)
286 {
287 char c = cast<char>(fgetc(m_file.filePtr()));
288 if (c == terminator || feof(m_file.filePtr()))
289 break;
290 string[size++] = c;
291 }
292 }
293 string[size] = '\0';
294 return size;
295 }
297 {
298 String string;
299 string.setSize(max_size);
300 uint04 actual_size = readData(string.begin(), max_size);
301 string.setSize(actual_size);
302 return string;
303 }
304 uint04 readData(char* string, uint04 max_size)
305 {
306 if (m_using_cache)
307 {
308 for (uint04 i = 0; i < max_size; i++)
309 {
310 char c = *((char*)(&m_cached_data[m_cache_location++]));
311 if (m_cache_location >= m_cached_data.size())
312 return i;
313 string[i] = c;
314 }
315 }
316 else
317 {
318 for (uint04 i = 0; i < max_size; i++)
319 {
320 char c = cast<char>(fgetc(m_file.filePtr()));
321 if (feof(m_file.filePtr()))
322 return i;
323 string[i] = c;
324 }
325 }
326 return max_size;
327 }
328 template<class t_type, class t_index_type, class t_memory_allocator, class t_memory_manager>
330 {
331 bool allow_multithread = m_multitreaded_compression;
332 read(data, allow_multithread);
333 }
334 template<class t_type, class t_index_type, class t_memory_allocator, class t_memory_manager>
336 {
337 bool allow_multithread = false;
338 read(data, allow_multithread);
339 }
340
341 template<class t_type, class t_index_type, class t_memory_allocator, class t_memory_manager>
342 typename std::enable_if<ObjectInfo<t_type>::Buffer>::type read(Buffer<t_type, t_index_type, t_memory_allocator, t_memory_manager>& data, bool& allow_multithread)
343 {
344 Buffer<uint04> sizes;
345 Buffer<decltype(t_type::Type())> combined_data;
346 //if (ObjectInfo<t_type>::String)
347 allow_multithread = false;
348 read(sizes, allow_multithread);
349 read(combined_data, allow_multithread);
350 data.setSize(sizes.size());
351 uint04 current_offset = 0;
352 for (uint04 i = 0; i < sizes.size(); i++)
353 {
354 data[i].clear();
355 if (sizes[i] > 0)
356 data[i].addAll(&combined_data[0] + current_offset, sizes[i]);
357 current_offset += sizes[i];
358 }
359 }
360
361 template<class t_index_type, class t_memory_allocator, class t_memory_manager>
363 {
364 Buffer<uint04> indices;
365 //if (ObjectInfo<t_type>::String)
366 allow_multithread = false;
367 read(indices, allow_multithread);
368 data.setSize(indices.size());
369 for (uint04 i = 0; i < indices.size(); i++)
370 {
371 Bounds<1, uint04> bounds = m_string_size_info[indices[i]];
372 if (bounds.span() > 0U)
373 {
374 data[i] = m_strings.substr(bounds[MIN], bounds[MAX]);
375 }
376 else
377 {
378 data[i].clear();
379 }
380 }
381 }
382
383 template<class t_type, class t_index_type, class t_memory_allocator, class t_memory_manager>
384 typename std::enable_if<!ObjectInfo<t_type>::Buffer>::type read(Buffer<t_type, t_index_type, t_memory_allocator, t_memory_manager>& data, bool& allow_multithread)
385 {
386 BinaryCompressionObject binary = createCompressionObject();
387 if (m_large_compression)
388 binary.uncompressed_size = read<uint08>();
389 else
390 binary.uncompressed_size = read<uint04>();
391 //lib_assert(binary.uncompressed_size < Constant<sint04>::Max, "Large number read");
392 data.setSize(cast<t_index_type>(binary.uncompressed_size));
393 binary.uncompressed_size = data.memSize();
394 if (data.size() != 0)
395 {
396 binary.uncompressed_data = (uint01*)data.ptr();
397 if (m_large_compression)
398 binary.compressed_size = read<uint08>();
399 else
400 binary.compressed_size = read<uint04>();
401 if (m_using_cache)
402 {
403 binary.compression_mode = cast<CompressionMode>(m_cached_data[m_cache_location]);
404 binary.compressed_size -= 1;
405 if (binary.compression_mode != CompressionMode::e_string_reference)
406 {
407 binary.compressed_data = &m_cached_data[m_cache_location + 1];
408
409 allow_multithread &= binary.compression_mode != CompressionMode::e_string_compression;
410 allow_multithread &= binary.compression_mode != CompressionMode::e_no_compression;
411 if (m_multitreaded_compression && allow_multithread)
412 m_compressions.add(binary);
413 else
414 Compressor::DecompressData(binary);
415 m_cache_location += binary.compressed_size + 1;
416 }
417 else
418 {
419 Compressor::DecompressData(binary);
420 m_cache_location++;
421 }
422 }
423 else
424 {
425 if (binary.compression_mode != CompressionMode::e_string_reference)
426 {
427 m_compressed_data.setSize(binary.compressed_size);
428#ifdef USE_ASSERTIONS
429 size_t fsize = fread(&m_compressed_data[0], 1, m_compressed_data.size(), m_file.filePtr());
430 lib_assert(m_compressed_data.size() == cast<uint08>(fsize), "Bad read size");
431#else
432 fread(&m_compressed_data[0], 1, m_compressed_data.size(), m_file.filePtr());
433#endif
434 binary.compression_mode = cast<CompressionMode>(m_compressed_data[0]);
435 binary.compressed_data = &m_compressed_data[1];
436 binary.compressed_size -= 1;
437 Compressor::DecompressData(binary);
438 m_cache_location += binary.compressed_size + 1;
439 }
440 else
441 {
442 Compressor::DecompressData(binary);
443 m_cache_location++;
444 }
445 }
446 }
447 }
448#ifdef _WIN32
449#define ndevr_ftell _ftelli64
450#define ndevr_fseek _fseeki64
451#else
452#define ndevr_ftell ftell
453#define ndevr_fseek fseek
454#endif
456 {
457 if (m_using_cache)
458 return m_cache_location;
459 else
460 return cast<uint08>(ndevr_ftell(m_file.filePtr()));
461 }
463 {
464 if (m_using_cache)
465 {
466 return cast<fltp04>(m_cache_location) / cast<fltp04>(m_cached_data.size());
467 }
468 else
469 {
470 if (IsInvalid(m_file_size))
471 m_file_size = m_file.fileSize();
472 return cast<fltp04>(cast<uint08>(ndevr_ftell(m_file.filePtr()))) / cast<fltp04>(m_file_size);
473 }
474 }
475 void seek(uint08 location)
476 {
477 if (m_using_cache)
478 m_cache_location = location;
479 else
480 ndevr_fseek(m_file.filePtr(), cast<long long>(location), SEEK_SET);
481 }
483 void setUseLargeCompression(bool use_large_compression) { m_large_compression = use_large_compression; }
485 void writeCompression(BinaryCompressionObject& compression_object);
486 void writeStringData(CompressionMode compression_mode);
487 void readStringData(bool has_reference_table);
489 void uncompressSections(uint04 start, uint04 count);
491 {
492 if (m_using_cache)
493 return m_cached_data.size();
494 if (IsInvalid(m_file_size))
495 m_file_size = m_file.fileSize();
496 return m_file_size;
497 }
498 protected:
508 mutable uint08 m_file_size = Constant<uint08>::Invalid;
509 bool m_using_cache = false;
510 bool m_is_read = false;
511 bool m_large_compression = false;
512 bool m_multitreaded_compression = true;
513 };
515}
#define NDEVR_BASE_API
Definition DLLInfo.h:57
#define ndevr_fseek
Definition BinaryFile.h:450
#define ndevr_ftell
Definition BinaryFile.h:449
#define lib_assert(expression, message)
Definition LibAssert.h:61
Logic for reading or writing to a binary file including logic for.
Definition BinaryFile.h:59
uint04 readString(char *string, char terminator='\0')
Definition BinaryFile.h:270
void read(Buffer< t_type, t_index_type, t_memory_allocator, t_memory_manager > &data)
Definition BinaryFile.h:329
void setUseLargeCompression(bool use_large_compression)
Definition BinaryFile.h:483
std::enable_if<!ObjectInfo< t_type >::Buffer >::type read(Buffer< t_type, t_index_type, t_memory_allocator, t_memory_manager > &data, bool &allow_multithread)
Definition BinaryFile.h:384
Buffer< Bounds< 1, uint04 > > m_string_size_info
Definition BinaryFile.h:502
void write(const t_type &data)
Definition BinaryFile.h:123
fltp04 percent()
Definition BinaryFile.h:462
std::enable_if< ObjectInfo< t_type >::Buffer >::type write(const Buffer< t_type, t_index_type, t_memory_allocator, t_memory_manager > &data, CompressionMode compression_mode)
Definition BinaryFile.h:180
void writeCompression(BinaryCompressionObject &compression_object)
void seek(uint08 location)
Definition BinaryFile.h:475
std::enable_if<!ObjectInfo< t_type >::Buffer >::type write(const Buffer< t_type, t_index_type, t_memory_allocator, t_memory_manager > &data, CompressionMode compression_mode)
Definition BinaryFile.h:142
void close()
Definition BinaryFile.h:97
void writeStringData(CompressionMode compression_mode)
void open(bool read, bool safe)
Definition BinaryFile.h:69
Dictionary< String, uint04 > m_string_reference
Definition BinaryFile.h:501
String m_strings
Definition BinaryFile.h:500
void cachedOpen(bool read)
Definition BinaryFile.h:77
std::enable_if< ObjectInfo< t_type >::Buffer >::type read(Buffer< t_type, t_index_type, t_memory_allocator, t_memory_manager > &data, bool &allow_multithread)
Definition BinaryFile.h:342
void readNow(Buffer< t_type, t_index_type, t_memory_allocator, t_memory_manager > &data)
Definition BinaryFile.h:335
uint08 fileSize() const
Definition BinaryFile.h:490
void writeRawData(const String &data, uint04 size, char fill_space='\0')
Definition BinaryFile.h:199
void readStringData(bool has_reference_table)
uint08 position()
Definition BinaryFile.h:455
void readStringBuffer(Buffer< String, t_index_type, t_memory_allocator, t_memory_manager > &data, bool &allow_multithread)
Definition BinaryFile.h:362
File m_file
Definition BinaryFile.h:499
Buffer< BinaryCompressionObject > m_compressions
Definition BinaryFile.h:506
String readData(uint04 max_size)
Definition BinaryFile.h:296
BinaryCompressionObject createCompressionObject()
void uncompressSections(uint04 start, uint04 count)
~BinaryFile()
Definition BinaryFile.h:65
Buffer< uint01, uint08 > m_compressed_data
Definition BinaryFile.h:504
uint04 readData(char *string, uint04 max_size)
Definition BinaryFile.h:304
Buffer< uint01, uint08 > m_cached_data
Definition BinaryFile.h:505
BinaryFile(const File &file)
Definition BinaryFile.h:62
void readString(String &string, char terminator='\0')
Definition BinaryFile.h:247
t_type read()
Definition BinaryFile.h:233
const Buffer< uint01, uint08 > & cachedData() const
Definition BinaryFile.h:117
A specification of upper and lower bounds in N-dimensions.
Definition Bounds.hpp:52
constexpr Ray< t_dims, t_type > span() const
The side lengths of these bounds. For each dimension, the span is max - min.
Definition Bounds.hpp:111
The equivelent of std::vector but with a bit more control. The basic array unit of the library.
Definition Buffer.hpp:56
constexpr t_index_type size() const
Definition Buffer.hpp:823
decltype(auto) ptr()
Definition Buffer.hpp:387
void addAll(const Buffer< t_type, t_other_index_type, t_other_memory_allocator, t_other_memory_manager > &buffer)
Definition Buffer.hpp:243
void setSize(t_index_type new_size)
Definition Buffer.hpp:803
decltype(auto) begin()
Definition Buffer.hpp:402
t_index_type memSize() const
Definition Buffer.hpp:397
void clear()
Definition Buffer.hpp:422
A hash-based key-value store, useful for quick associative lookups. Key features include:
Definition Dictionary.h:61
Logic for reading or writing to a file as well as navigating filesystems.
Definition File.h:48
The core String class for the NDEVR API.
Definition String.h:69
Logic for reading or writing to a string or a user friendly, TranslatedString.
Definition StringStream.h:230
Definition ACIColor.h:37
constexpr bool IsInvalid(const t_type &value)
Query if 'value' is valid or invalid. Invalid values should return invalid if used for calculations o...
Definition BaseFunctions.hpp:170
@ MIN
Definition BaseValues.hpp:196
@ MAX
Definition BaseValues.hpp:197
float fltp04
Defines an alias representing a 4 byte floating-point number Bit layout is as follows: -Sign: 1 bit a...
Definition BaseValues.hpp:127
uint8_t uint01
-Defines an alias representing a 1 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:80
t_type ChangeEndian(t_type in)
Definition BinaryFile.h:47
CompressionMode
Logical information about the type of compression implemented or requested.
Definition Compressor.h:16
@ e_string_compression
Definition Compressor.h:20
@ e_string_reference
Definition Compressor.h:31
uint64_t uint08
-Defines an alias representing an 8 byte, unsigned integer
Definition BaseValues.hpp:106
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:96
double fltp08
Defines an alias representing an 8 byte floating-point number.
Definition BaseValues.hpp:149
constexpr t_type getMin(const t_type &left, const t_type &right)
Finds the minimum of the given arguments based on the < operator Author: Tyler Parke Date: 2017-11-05...
Definition BaseFunctions.hpp:56
A container for storing compressed data, typically used for File IO operations. Responsible for stori...
Definition Compressor.h:52
uint01 * compressed_data
Definition Compressor.h:56
uint08 compressed_size
Definition Compressor.h:57
uint01 * uncompressed_data
Definition Compressor.h:54
uint08 uncompressed_size
Definition Compressor.h:55
CompressionMode compression_mode
Definition Compressor.h:53
uint08 buffer_size
Definition Compressor.h:58
Defines for a given type (such as sint04, fltp08, UUID, etc) a maximum, minimum, and reserved 'invali...
Definition BaseValues.hpp:233