OpenJPH
Open-source implementation of JPEG2000 Part-15
Loading...
Searching...
No Matches
ojph_file.cpp
Go to the documentation of this file.
1//***************************************************************************;
2// This software is released under the 2-Clause BSD license, included
3// below.
4//
5// Copyright (c) 2019, Aous Naman
6// Copyright (c) 2019, Kakadu Software Pty Ltd, Australia
7// Copyright (c) 2019, The University of New South Wales, Australia
8//
9// Redistribution and use in source and binary forms, with or without
10// modification, are permitted provided that the following conditions are
11// met:
12//
13// 1. Redistributions of source code must retain the above copyright
14// notice, this list of conditions and the following disclaimer.
15//
16// 2. Redistributions in binary form must reproduce the above copyright
17// notice, this list of conditions and the following disclaimer in the
18// documentation and/or other materials provided with the distribution.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
26// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31//***************************************************************************/
32// This file is part of the OpenJPH software implementation.
33// File: ojph_file.cpp
34// Author: Aous Naman
35// Date: 28 August 2019
36//***************************************************************************/
37
38
42
43#include <cassert>
44#include <cstddef>
45#include <utility>
46
47#include "ojph_mem.h"
48#include "ojph_file.h"
49#include "ojph_message.h"
50
51namespace ojph {
52
54 //
55 //
56 //
57 //
58 //
60
62 void j2c_outfile::open(const char *filename)
63 {
64 assert(fh == 0);
65 fh = fopen(filename, "wb");
66 if (fh == NULL)
67 OJPH_ERROR(0x00060001, "failed to open %s for writing", filename);
68 }
69
71 size_t j2c_outfile::write(const void *ptr, size_t size)
72 {
73 assert(fh);
74 return fwrite(ptr, 1, size, fh);
75 }
76
79 {
80 assert(fh);
81 return ojph_ftell(fh);
82 }
83
86 {
87 assert(fh);
88 fflush(fh);
89 }
90
93 {
94 assert(fh);
95 fclose(fh);
96 fh = NULL;
97 }
98
100 //
101 //
102 // mem_outfile
103 //
104 //
106
109 {
110 is_open = clear_mem = false;
111 buf_size = used_size = 0;
112 buf = cur_ptr = nullptr;
113 }
114
116 void mem_outfile::swap(mem_outfile& other) noexcept {
117 std::swap(this->is_open,other.is_open);
118 std::swap(this->clear_mem,other.clear_mem);
119 std::swap(this->buf_size,other.buf_size);
120 std::swap(this->used_size,other.used_size);
121 std::swap(this->buf,other.buf);
122 std::swap(this->cur_ptr,other.cur_ptr);
123 }
124
127 {
128 if (buf)
130 is_open = clear_mem = false;
131 buf_size = used_size = 0;
132 buf = cur_ptr = NULL;
133 }
134
137 {
138 this->swap(rhs);
139 }
140
143 {
144 if (this != &rhs) {
145 mem_outfile tmp(std::move(rhs));
146 this->swap(tmp);
147 }
148 return *this;
149 }
150
152 void mem_outfile::open(size_t initial_size, bool clear_mem)
153 {
154 assert(this->is_open == false);
155 assert(this->cur_ptr == this->buf);
156
157 // do initial buffer allocation or buffer expansion
158 this->is_open = true;
159 this->clear_mem = clear_mem;
160 expand_storage(initial_size, this->clear_mem);
161 this->used_size = 0;
162 this->cur_ptr = this->buf;
163 }
164
167 is_open = false;
168 cur_ptr = buf;
169 }
170
172
176 {
177 if (origin == OJPH_SEEK_SET)
178 ; // do nothing
179 else if (origin == OJPH_SEEK_CUR)
180 offset += tell();
181 else if (origin == OJPH_SEEK_END)
182 offset += (si64)used_size;
183 else {
184 assert(0);
185 return -1;
186 }
187
188 if (offset < 0) // offset before the start of file
189 return -1;
190
191 expand_storage((size_t)offset, false); // See if expansion is needed
192
193 cur_ptr = buf + offset;
194 return 0;
195 }
196
198
200 size_t mem_outfile::write(const void *ptr, size_t new_size)
201 {
202 assert(this->is_open);
203 assert(this->buf_size);
204 assert(this->buf);
205 assert(this->cur_ptr);
206
207 // expand buffer if needed to make sure it has room for this write
208 size_t needed_size = (size_t)tell() + new_size; //needed size
209 expand_storage(needed_size, false);
210
211 // copy bytes into buffer and adjust cur_ptr
212 memcpy(this->cur_ptr, ptr, new_size);
213 cur_ptr += new_size;
214 used_size = ojph_max(used_size, (size_t)tell());
215
216 return new_size;
217 }
218
220 void mem_outfile::write_to_file(const char *file_name) const
221 {
222 assert(is_open == false);
223 FILE *f = fopen(file_name, "wb");
224 if (f == NULL)
225 OJPH_ERROR(0x00060003, "failed to open %s for writing", file_name);
226 if (f != NULL)
227 if (fwrite(this->buf, 1, used_size, f) != used_size)
228 OJPH_ERROR(0x00060004, "failed writing to %s", file_name);
229 fclose(f);
230 }
231
233 void mem_outfile::expand_storage(size_t needed_size, bool clear_all)
234 {
235 if (needed_size > buf_size)
236 {
237 needed_size += (needed_size + 1) >> 1; // x1.5
238 // expand buffer to multiples of (ALIGNED_ALLOC_MASK + 1)
239 needed_size = (needed_size + ALIGNED_ALLOC_MASK) & (~ALIGNED_ALLOC_MASK);
240
241 ui8* new_buf;
242 new_buf = (ui8*)ojph_aligned_malloc(ALIGNED_ALLOC_MASK + 1, needed_size);
243 if (new_buf == NULL)
244 OJPH_ERROR(0x00060005, "failed to allocate memory (%zu bytes)",
245 needed_size);
246
247 if (this->buf != NULL)
248 {
249 if (!clear_all)
250 memcpy(new_buf, this->buf, used_size);
251 ojph_aligned_free(this->buf);
252 }
253 this->cur_ptr = new_buf + tell();
254 this->buf = new_buf;
255
256 if (clear_mem && !clear_all) // will be cleared later
257 memset(this->buf + buf_size, 0, needed_size - this->buf_size);
258 this->buf_size = needed_size;
259 }
260 if (clear_all)
261 memset(this->buf, 0, this->buf_size);
262 }
263
264
266 //
267 //
268 //
269 //
270 //
272
274 void j2c_infile::open(const char *filename)
275 {
276 assert(fh == NULL);
277 fh = fopen(filename, "rb");
278 if (fh == NULL)
279 OJPH_ERROR(0x00060002, "failed to open %s for reading", filename);
280 }
281
283 size_t j2c_infile::read(void *ptr, size_t size)
284 {
285 assert(fh);
286 return fread(ptr, 1, size, fh);
287 }
288
290 int j2c_infile::seek(si64 offset, enum infile_base::seek origin)
291 {
292 assert(fh);
293 return ojph_fseek(fh, offset, origin);
294 }
295
298 {
299 assert(fh);
300 return ojph_ftell(fh);
301 }
302
305 {
306 assert(fh);
307 fclose(fh);
308 fh = NULL;
309 }
310
311
313 //
314 //
315 //
316 //
317 //
319
322 {
323 this->swap(rhs);
324 }
325
328 {
329 if (this != &rhs) {
330 mem_infile tmp(std::move(rhs));
331 this->swap(tmp);
332 }
333 return *this;
334 }
335
337 void mem_infile::open(const ui8* data, size_t size)
338 {
339 assert(this->data == NULL);
340 cur_ptr = this->data = data;
341 this->size = size;
342 }
343
345 size_t mem_infile::read(void *ptr, size_t size)
346 {
347 std::ptrdiff_t bytes_left = (data + this->size) - cur_ptr;
348 if (bytes_left > 0)
349 {
350 size_t bytes_to_read = ojph_min(size, (size_t)bytes_left);
351 memcpy(ptr, cur_ptr, bytes_to_read);
352 cur_ptr += bytes_to_read;
353 return bytes_to_read;
354 }
355 else
356 return 0;
357 }
358
360 int mem_infile::seek(si64 offset, enum infile_base::seek origin)
361 {
362 int result = -1;
363 if (origin == OJPH_SEEK_SET)
364 {
365 if (offset >= 0 && (size_t)offset <= size)
366 {
367 cur_ptr = data + offset;
368 result = 0;
369 }
370 }
371 else if (origin == OJPH_SEEK_CUR)
372 {
373 si64 bytes_off = (si64)(cur_ptr - data) + offset;
374 if (bytes_off >= 0 && (size_t)bytes_off <= size)
375 {
376 cur_ptr = data + bytes_off;
377 result = 0;
378 }
379 }
380 else if (origin == OJPH_SEEK_END)
381 {
382 if (offset <= 0 && (std::ptrdiff_t)size + offset >= 0)
383 {
384 cur_ptr = data + size + offset;
385 result = 0;
386 }
387 }
388 else
389 assert(0);
390
391 return result;
392 }
393
395 void mem_infile::swap(mem_infile& other) noexcept
396 {
397 std::swap(this->data,other.data);
398 std::swap(this->cur_ptr,other.cur_ptr);
399 std::swap(this->size,other.size);
400 }
401
402}
void close() override
void open(const char *filename)
size_t read(void *ptr, size_t size) override
si64 tell() override
void flush() override
Definition ojph_file.cpp:85
void close() override
Definition ojph_file.cpp:92
si64 tell() override
Definition ojph_file.cpp:78
void open(const char *filename)
Definition ojph_file.cpp:62
size_t write(const void *ptr, size_t size) override
Definition ojph_file.cpp:71
const ui8 * cur_ptr
Definition ojph_file.h:342
size_t read(void *ptr, size_t size) override
mem_infile(mem_infile &&) noexcept
void open(const ui8 *data, size_t size)
void swap(mem_infile &) noexcept
mem_infile & operator=(mem_infile const &)=delete
const ui8 * data
Definition ojph_file.h:342
si64 tell() override
Call this function to know the file size (i.e., number of bytes used to store the file).
Definition ojph_file.h:177
static const size_t ALIGNED_ALLOC_MASK
Definition ojph_file.h:262
size_t write(const void *ptr, size_t size) override
Call this function to write data to the memory file.
void expand_storage(size_t new_size, bool clear_all)
This function expands storage by x1.5 needed space.
void open(size_t initial_size=65536, bool clear_mem=false)
Call this function to open a memory file.
~mem_outfile() override
mem_outfile & operator=(mem_outfile const &)=delete
void swap(mem_outfile &other) noexcept
A utility function to swap the contents of two instances.
void close() override
void write_to_file(const char *file_name) const
Call this function to write the memory file data to a file.
int ojph_fseek(FILE *stream, si64 offset, int origin)
Definition ojph_file.h:61
void * ojph_aligned_malloc(size_t alignment, size_t size)
si64 ojph_ftell(FILE *stream)
Definition ojph_file.h:66
int64_t si64
Definition ojph_defs.h:57
uint8_t ui8
Definition ojph_defs.h:50
void ojph_aligned_free(void *pointer)
#define ojph_max(a, b)
Definition ojph_defs.h:73
#define ojph_min(a, b)
Definition ojph_defs.h:76
#define OJPH_ERROR(t,...)