1/*
2 * The copyright in this software is being made available under the 2-clauses
3 * BSD License, included below. This software may be subject to other third
4 * party and contributor rights, including patent rights, and no such rights
5 * are granted under this license.
6 *
7 * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
8 * Copyright (c) 2002-2014, Professor Benoit Macq
9 * Copyright (c) 2001-2003, David Janssens
10 * Copyright (c) 2002-2003, Yannick Verschueren
11 * Copyright (c) 2003-2007, Francois-Olivier Devaux
12 * Copyright (c) 2003-2014, Antonin Descampe
13 * Copyright (c) 2005, Herve Drolon, FreeImage Team
14 * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR
15 * Copyright (c) 2012, CS Systemes d'Information, France
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40#include "opj_includes.h"
41
42/* ----------------------------------------------------------------------- */
43
44
45/* ----------------------------------------------------------------------- */
46
47void opj_write_bytes_BE(OPJ_BYTE * p_buffer, OPJ_UINT32 p_value,
48 OPJ_UINT32 p_nb_bytes)
49{
50 const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + sizeof(
51 OPJ_UINT32) - p_nb_bytes;
52
53 assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32));
54
55 memcpy(p_buffer, l_data_ptr, p_nb_bytes);
56}
57
58void opj_write_bytes_LE(OPJ_BYTE * p_buffer, OPJ_UINT32 p_value,
59 OPJ_UINT32 p_nb_bytes)
60{
61 const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + p_nb_bytes - 1;
62 OPJ_UINT32 i;
63
64 assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32));
65
66 for (i = 0; i < p_nb_bytes; ++i) {
67 *(p_buffer++) = *(l_data_ptr--);
68 }
69}
70
71void opj_read_bytes_BE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value,
72 OPJ_UINT32 p_nb_bytes)
73{
74 OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value);
75
76 assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32));
77
78 *p_value = 0;
79 memcpy(l_data_ptr + sizeof(OPJ_UINT32) - p_nb_bytes, p_buffer, p_nb_bytes);
80}
81
82void opj_read_bytes_LE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value,
83 OPJ_UINT32 p_nb_bytes)
84{
85 OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + p_nb_bytes - 1;
86 OPJ_UINT32 i;
87
88 assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32));
89
90 *p_value = 0;
91 for (i = 0; i < p_nb_bytes; ++i) {
92 *(l_data_ptr--) = *(p_buffer++);
93 }
94}
95
96void opj_write_double_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT64 p_value)
97{
98 const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value);
99 memcpy(p_buffer, l_data_ptr, sizeof(OPJ_FLOAT64));
100}
101
102void opj_write_double_LE(OPJ_BYTE * p_buffer, OPJ_FLOAT64 p_value)
103{
104 const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + sizeof(
105 OPJ_FLOAT64) - 1;
106 OPJ_UINT32 i;
107 for (i = 0; i < sizeof(OPJ_FLOAT64); ++i) {
108 *(p_buffer++) = *(l_data_ptr--);
109 }
110}
111
112void opj_read_double_BE(const OPJ_BYTE * p_buffer, OPJ_FLOAT64 * p_value)
113{
114 OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value);
115 memcpy(l_data_ptr, p_buffer, sizeof(OPJ_FLOAT64));
116}
117
118void opj_read_double_LE(const OPJ_BYTE * p_buffer, OPJ_FLOAT64 * p_value)
119{
120 OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + sizeof(OPJ_FLOAT64) - 1;
121 OPJ_UINT32 i;
122 for (i = 0; i < sizeof(OPJ_FLOAT64); ++i) {
123 *(l_data_ptr--) = *(p_buffer++);
124 }
125}
126
127void opj_write_float_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value)
128{
129 const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value);
130 memcpy(p_buffer, l_data_ptr, sizeof(OPJ_FLOAT32));
131}
132
133void opj_write_float_LE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value)
134{
135 const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + sizeof(
136 OPJ_FLOAT32) - 1;
137 OPJ_UINT32 i;
138 for (i = 0; i < sizeof(OPJ_FLOAT32); ++i) {
139 *(p_buffer++) = *(l_data_ptr--);
140 }
141}
142
143void opj_read_float_BE(const OPJ_BYTE * p_buffer, OPJ_FLOAT32 * p_value)
144{
145 OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value);
146 memcpy(l_data_ptr, p_buffer, sizeof(OPJ_FLOAT32));
147}
148
149void opj_read_float_LE(const OPJ_BYTE * p_buffer, OPJ_FLOAT32 * p_value)
150{
151 OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + sizeof(OPJ_FLOAT32) - 1;
152 OPJ_UINT32 i;
153 for (i = 0; i < sizeof(OPJ_FLOAT32); ++i) {
154 *(l_data_ptr--) = *(p_buffer++);
155 }
156}
157
158opj_stream_t* OPJ_CALLCONV opj_stream_create(OPJ_SIZE_T p_buffer_size,
159 OPJ_BOOL l_is_input)
160{
161 opj_stream_private_t * l_stream = 00;
162 l_stream = (opj_stream_private_t*) opj_calloc(1, sizeof(opj_stream_private_t));
163 if (! l_stream) {
164 return 00;
165 }
166
167 l_stream->m_buffer_size = p_buffer_size;
168 l_stream->m_stored_data = (OPJ_BYTE *) opj_malloc(p_buffer_size);
169 if (! l_stream->m_stored_data) {
170 opj_free(l_stream);
171 return 00;
172 }
173
174 l_stream->m_current_data = l_stream->m_stored_data;
175
176 if (l_is_input) {
177 l_stream->m_status |= OPJ_STREAM_STATUS_INPUT;
178 l_stream->m_opj_skip = opj_stream_read_skip;
179 l_stream->m_opj_seek = opj_stream_read_seek;
180 } else {
181 l_stream->m_status |= OPJ_STREAM_STATUS_OUTPUT;
182 l_stream->m_opj_skip = opj_stream_write_skip;
183 l_stream->m_opj_seek = opj_stream_write_seek;
184 }
185
186 l_stream->m_read_fn = opj_stream_default_read;
187 l_stream->m_write_fn = opj_stream_default_write;
188 l_stream->m_skip_fn = opj_stream_default_skip;
189 l_stream->m_seek_fn = opj_stream_default_seek;
190
191 return (opj_stream_t *) l_stream;
192}
193
194opj_stream_t* OPJ_CALLCONV opj_stream_default_create(OPJ_BOOL l_is_input)
195{
196 return opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE, l_is_input);
197}
198
199void OPJ_CALLCONV opj_stream_destroy(opj_stream_t* p_stream)
200{
201 opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
202
203 if (l_stream) {
204 if (l_stream->m_free_user_data_fn) {
205 l_stream->m_free_user_data_fn(l_stream->m_user_data);
206 }
207 opj_free(l_stream->m_stored_data);
208 l_stream->m_stored_data = 00;
209 opj_free(l_stream);
210 }
211}
212
213void OPJ_CALLCONV opj_stream_set_read_function(opj_stream_t* p_stream,
214 opj_stream_read_fn p_function)
215{
216 opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
217
218 if ((!l_stream) || (!(l_stream->m_status & OPJ_STREAM_STATUS_INPUT))) {
219 return;
220 }
221
222 l_stream->m_read_fn = p_function;
223}
224
225void OPJ_CALLCONV opj_stream_set_seek_function(opj_stream_t* p_stream,
226 opj_stream_seek_fn p_function)
227{
228 opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
229
230 if (!l_stream) {
231 return;
232 }
233 l_stream->m_seek_fn = p_function;
234}
235
236void OPJ_CALLCONV opj_stream_set_write_function(opj_stream_t* p_stream,
237 opj_stream_write_fn p_function)
238{
239 opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
240
241 if ((!l_stream) || (!(l_stream->m_status & OPJ_STREAM_STATUS_OUTPUT))) {
242 return;
243 }
244
245 l_stream->m_write_fn = p_function;
246}
247
248void OPJ_CALLCONV opj_stream_set_skip_function(opj_stream_t* p_stream,
249 opj_stream_skip_fn p_function)
250{
251 opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
252
253 if (! l_stream) {
254 return;
255 }
256
257 l_stream->m_skip_fn = p_function;
258}
259
260void OPJ_CALLCONV opj_stream_set_user_data(opj_stream_t* p_stream,
261 void * p_data, opj_stream_free_user_data_fn p_function)
262{
263 opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
264 if (!l_stream) {
265 return;
266 }
267 l_stream->m_user_data = p_data;
268 l_stream->m_free_user_data_fn = p_function;
269}
270
271void OPJ_CALLCONV opj_stream_set_user_data_length(opj_stream_t* p_stream,
272 OPJ_UINT64 data_length)
273{
274 opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
275 if (!l_stream) {
276 return;
277 }
278 l_stream->m_user_data_length = data_length;
279}
280
281OPJ_SIZE_T opj_stream_read_data(opj_stream_private_t * p_stream,
282 OPJ_BYTE * p_buffer, OPJ_SIZE_T p_size, opj_event_mgr_t * p_event_mgr)
283{
284 OPJ_SIZE_T l_read_nb_bytes = 0;
285 if (p_stream->m_bytes_in_buffer >= p_size) {
286 memcpy(p_buffer, p_stream->m_current_data, p_size);
287 p_stream->m_current_data += p_size;
288 p_stream->m_bytes_in_buffer -= p_size;
289 l_read_nb_bytes += p_size;
290 p_stream->m_byte_offset += (OPJ_OFF_T)p_size;
291 return l_read_nb_bytes;
292 }
293
294 /* we are now in the case when the remaining data if not sufficient */
295 if (p_stream->m_status & OPJ_STREAM_STATUS_END) {
296 l_read_nb_bytes += p_stream->m_bytes_in_buffer;
297 memcpy(p_buffer, p_stream->m_current_data, p_stream->m_bytes_in_buffer);
298 p_stream->m_current_data += p_stream->m_bytes_in_buffer;
299 p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
300 p_stream->m_bytes_in_buffer = 0;
301 return l_read_nb_bytes ? l_read_nb_bytes : (OPJ_SIZE_T) - 1;
302 }
303
304 /* the flag is not set, we copy data and then do an actual read on the stream */
305 if (p_stream->m_bytes_in_buffer) {
306 l_read_nb_bytes += p_stream->m_bytes_in_buffer;
307 memcpy(p_buffer, p_stream->m_current_data, p_stream->m_bytes_in_buffer);
308 p_stream->m_current_data = p_stream->m_stored_data;
309 p_buffer += p_stream->m_bytes_in_buffer;
310 p_size -= p_stream->m_bytes_in_buffer;
311 p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
312 p_stream->m_bytes_in_buffer = 0;
313 } else {
314 /* case where we are already at the end of the buffer
315 so reset the m_current_data to point to the start of the
316 stored buffer to get ready to read from disk*/
317 p_stream->m_current_data = p_stream->m_stored_data;
318 }
319
320 for (;;) {
321 /* we should read less than a chunk -> read a chunk */
322 if (p_size < p_stream->m_buffer_size) {
323 /* we should do an actual read on the media */
324 p_stream->m_bytes_in_buffer = p_stream->m_read_fn(p_stream->m_stored_data,
325 p_stream->m_buffer_size, p_stream->m_user_data);
326
327 if (p_stream->m_bytes_in_buffer == (OPJ_SIZE_T) - 1) {
328 /* end of stream */
329 opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n");
330
331 p_stream->m_bytes_in_buffer = 0;
332 p_stream->m_status |= OPJ_STREAM_STATUS_END;
333 /* end of stream */
334 return l_read_nb_bytes ? l_read_nb_bytes : (OPJ_SIZE_T) - 1;
335 } else if (p_stream->m_bytes_in_buffer < p_size) {
336 /* not enough data */
337 l_read_nb_bytes += p_stream->m_bytes_in_buffer;
338 memcpy(p_buffer, p_stream->m_current_data, p_stream->m_bytes_in_buffer);
339 p_stream->m_current_data = p_stream->m_stored_data;
340 p_buffer += p_stream->m_bytes_in_buffer;
341 p_size -= p_stream->m_bytes_in_buffer;
342 p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
343 p_stream->m_bytes_in_buffer = 0;
344 } else {
345 l_read_nb_bytes += p_size;
346 memcpy(p_buffer, p_stream->m_current_data, p_size);
347 p_stream->m_current_data += p_size;
348 p_stream->m_bytes_in_buffer -= p_size;
349 p_stream->m_byte_offset += (OPJ_OFF_T)p_size;
350 return l_read_nb_bytes;
351 }
352 } else {
353 /* direct read on the dest buffer */
354 p_stream->m_bytes_in_buffer = p_stream->m_read_fn(p_buffer, p_size,
355 p_stream->m_user_data);
356
357 if (p_stream->m_bytes_in_buffer == (OPJ_SIZE_T) - 1) {
358 /* end of stream */
359 opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n");
360
361 p_stream->m_bytes_in_buffer = 0;
362 p_stream->m_status |= OPJ_STREAM_STATUS_END;
363 /* end of stream */
364 return l_read_nb_bytes ? l_read_nb_bytes : (OPJ_SIZE_T) - 1;
365 } else if (p_stream->m_bytes_in_buffer < p_size) {
366 /* not enough data */
367 l_read_nb_bytes += p_stream->m_bytes_in_buffer;
368 p_stream->m_current_data = p_stream->m_stored_data;
369 p_buffer += p_stream->m_bytes_in_buffer;
370 p_size -= p_stream->m_bytes_in_buffer;
371 p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
372 p_stream->m_bytes_in_buffer = 0;
373 } else {
374 /* we have read the exact size */
375 l_read_nb_bytes += p_stream->m_bytes_in_buffer;
376 p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
377 p_stream->m_current_data = p_stream->m_stored_data;
378 p_stream->m_bytes_in_buffer = 0;
379 return l_read_nb_bytes;
380 }
381 }
382 }
383}
384
385OPJ_SIZE_T opj_stream_write_data(opj_stream_private_t * p_stream,
386 const OPJ_BYTE * p_buffer,
387 OPJ_SIZE_T p_size,
388 opj_event_mgr_t * p_event_mgr)
389{
390 OPJ_SIZE_T l_remaining_bytes = 0;
391 OPJ_SIZE_T l_write_nb_bytes = 0;
392
393 if (p_stream->m_status & OPJ_STREAM_STATUS_ERROR) {
394 return (OPJ_SIZE_T) - 1;
395 }
396
397 for (;;) {
398 l_remaining_bytes = p_stream->m_buffer_size - p_stream->m_bytes_in_buffer;
399
400 /* we have more memory than required */
401 if (l_remaining_bytes >= p_size) {
402 memcpy(p_stream->m_current_data, p_buffer, p_size);
403
404 p_stream->m_current_data += p_size;
405 p_stream->m_bytes_in_buffer += p_size;
406 l_write_nb_bytes += p_size;
407 p_stream->m_byte_offset += (OPJ_OFF_T)p_size;
408
409 return l_write_nb_bytes;
410 }
411
412 /* we copy data and then do an actual read on the stream */
413 if (l_remaining_bytes) {
414 l_write_nb_bytes += l_remaining_bytes;
415
416 memcpy(p_stream->m_current_data, p_buffer, l_remaining_bytes);
417
418 p_stream->m_current_data = p_stream->m_stored_data;
419
420 p_buffer += l_remaining_bytes;
421 p_size -= l_remaining_bytes;
422 p_stream->m_bytes_in_buffer += l_remaining_bytes;
423 p_stream->m_byte_offset += (OPJ_OFF_T)l_remaining_bytes;
424 }
425
426 if (! opj_stream_flush(p_stream, p_event_mgr)) {
427 return (OPJ_SIZE_T) - 1;
428 }
429 }
430
431}
432
433OPJ_BOOL opj_stream_flush(opj_stream_private_t * p_stream,
434 opj_event_mgr_t * p_event_mgr)
435{
436 /* the number of bytes written on the media. */
437 OPJ_SIZE_T l_current_write_nb_bytes = 0;
438
439 p_stream->m_current_data = p_stream->m_stored_data;
440
441 while (p_stream->m_bytes_in_buffer) {
442 /* we should do an actual write on the media */
443 l_current_write_nb_bytes = p_stream->m_write_fn(p_stream->m_current_data,
444 p_stream->m_bytes_in_buffer,
445 p_stream->m_user_data);
446
447 if (l_current_write_nb_bytes == (OPJ_SIZE_T) - 1) {
448 p_stream->m_status |= OPJ_STREAM_STATUS_ERROR;
449 opj_event_msg(p_event_mgr, EVT_INFO, "Error on writing stream!\n");
450
451 return OPJ_FALSE;
452 }
453
454 p_stream->m_current_data += l_current_write_nb_bytes;
455 p_stream->m_bytes_in_buffer -= l_current_write_nb_bytes;
456 }
457
458 p_stream->m_current_data = p_stream->m_stored_data;
459
460 return OPJ_TRUE;
461}
462
463OPJ_OFF_T opj_stream_read_skip(opj_stream_private_t * p_stream,
464 OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr)
465{
466 OPJ_OFF_T l_skip_nb_bytes = 0;
467 OPJ_OFF_T l_current_skip_nb_bytes = 0;
468
469 assert(p_size >= 0);
470
471 if (p_stream->m_bytes_in_buffer >= (OPJ_SIZE_T)p_size) {
472 p_stream->m_current_data += p_size;
473 /* it is safe to cast p_size to OPJ_SIZE_T since it is <= m_bytes_in_buffer
474 which is of type OPJ_SIZE_T */
475 p_stream->m_bytes_in_buffer -= (OPJ_SIZE_T)p_size;
476 l_skip_nb_bytes += p_size;
477 p_stream->m_byte_offset += l_skip_nb_bytes;
478 return l_skip_nb_bytes;
479 }
480
481 /* we are now in the case when the remaining data if not sufficient */
482 if (p_stream->m_status & OPJ_STREAM_STATUS_END) {
483 l_skip_nb_bytes += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
484 p_stream->m_current_data += p_stream->m_bytes_in_buffer;
485 p_stream->m_bytes_in_buffer = 0;
486 p_stream->m_byte_offset += l_skip_nb_bytes;
487 return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T) - 1;
488 }
489
490 /* the flag is not set, we copy data and then do an actual skip on the stream */
491 if (p_stream->m_bytes_in_buffer) {
492 l_skip_nb_bytes += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
493 p_stream->m_current_data = p_stream->m_stored_data;
494 p_size -= (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
495 p_stream->m_bytes_in_buffer = 0;
496 }
497
498 while (p_size > 0) {
499 /* Check if we are going beyond the end of file. Most skip_fn do not */
500 /* check that, but we must be careful not to advance m_byte_offset */
501 /* beyond m_user_data_length, otherwise */
502 /* opj_stream_get_number_byte_left() will assert. */
503 if ((OPJ_UINT64)(p_stream->m_byte_offset + l_skip_nb_bytes + p_size) >
504 p_stream->m_user_data_length) {
505 opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n");
506
507 p_stream->m_byte_offset += l_skip_nb_bytes;
508 l_skip_nb_bytes = (OPJ_OFF_T)(p_stream->m_user_data_length -
509 (OPJ_UINT64)p_stream->m_byte_offset);
510
511 opj_stream_read_seek(p_stream, (OPJ_OFF_T)p_stream->m_user_data_length,
512 p_event_mgr);
513 p_stream->m_status |= OPJ_STREAM_STATUS_END;
514
515 /* end if stream */
516 return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T) - 1;
517 }
518
519 /* we should do an actual skip on the media */
520 l_current_skip_nb_bytes = p_stream->m_skip_fn(p_size, p_stream->m_user_data);
521 if (l_current_skip_nb_bytes == (OPJ_OFF_T) - 1) {
522 opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n");
523
524 p_stream->m_status |= OPJ_STREAM_STATUS_END;
525 p_stream->m_byte_offset += l_skip_nb_bytes;
526 /* end if stream */
527 return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T) - 1;
528 }
529 p_size -= l_current_skip_nb_bytes;
530 l_skip_nb_bytes += l_current_skip_nb_bytes;
531 }
532
533 p_stream->m_byte_offset += l_skip_nb_bytes;
534
535 return l_skip_nb_bytes;
536}
537
538OPJ_OFF_T opj_stream_write_skip(opj_stream_private_t * p_stream,
539 OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr)
540{
541 OPJ_BOOL l_is_written = 0;
542 OPJ_OFF_T l_current_skip_nb_bytes = 0;
543 OPJ_OFF_T l_skip_nb_bytes = 0;
544
545 if (p_stream->m_status & OPJ_STREAM_STATUS_ERROR) {
546 return (OPJ_OFF_T) - 1;
547 }
548
549 /* we should flush data */
550 l_is_written = opj_stream_flush(p_stream, p_event_mgr);
551 if (! l_is_written) {
552 p_stream->m_status |= OPJ_STREAM_STATUS_ERROR;
553 p_stream->m_bytes_in_buffer = 0;
554 return (OPJ_OFF_T) - 1;
555 }
556 /* then skip */
557
558 while (p_size > 0) {
559 /* we should do an actual skip on the media */
560 l_current_skip_nb_bytes = p_stream->m_skip_fn(p_size, p_stream->m_user_data);
561
562 if (l_current_skip_nb_bytes == (OPJ_OFF_T) - 1) {
563 opj_event_msg(p_event_mgr, EVT_INFO, "Stream error!\n");
564
565 p_stream->m_status |= OPJ_STREAM_STATUS_ERROR;
566 p_stream->m_byte_offset += l_skip_nb_bytes;
567 /* end if stream */
568 return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T) - 1;
569 }
570 p_size -= l_current_skip_nb_bytes;
571 l_skip_nb_bytes += l_current_skip_nb_bytes;
572 }
573
574 p_stream->m_byte_offset += l_skip_nb_bytes;
575
576 return l_skip_nb_bytes;
577}
578
579OPJ_OFF_T opj_stream_tell(const opj_stream_private_t * p_stream)
580{
581 return p_stream->m_byte_offset;
582}
583
584OPJ_OFF_T opj_stream_get_number_byte_left(const opj_stream_private_t * p_stream)
585{
586 assert(p_stream->m_byte_offset >= 0);
587 assert(p_stream->m_user_data_length >= (OPJ_UINT64)p_stream->m_byte_offset);
588 return p_stream->m_user_data_length ?
589 (OPJ_OFF_T)(p_stream->m_user_data_length) - p_stream->m_byte_offset :
590 0;
591}
592
593OPJ_OFF_T opj_stream_skip(opj_stream_private_t * p_stream, OPJ_OFF_T p_size,
594 opj_event_mgr_t * p_event_mgr)
595{
596 assert(p_size >= 0);
597 return p_stream->m_opj_skip(p_stream, p_size, p_event_mgr);
598}
599
600OPJ_BOOL opj_stream_read_seek(opj_stream_private_t * p_stream, OPJ_OFF_T p_size,
601 opj_event_mgr_t * p_event_mgr)
602{
603 OPJ_ARG_NOT_USED(p_event_mgr);
604 p_stream->m_current_data = p_stream->m_stored_data;
605 p_stream->m_bytes_in_buffer = 0;
606
607 if (!(p_stream->m_seek_fn(p_size, p_stream->m_user_data))) {
608 p_stream->m_status |= OPJ_STREAM_STATUS_END;
609 return OPJ_FALSE;
610 } else {
611 /* reset stream status */
612 p_stream->m_status &= (~OPJ_STREAM_STATUS_END);
613 p_stream->m_byte_offset = p_size;
614
615 }
616
617 return OPJ_TRUE;
618}
619
620OPJ_BOOL opj_stream_write_seek(opj_stream_private_t * p_stream,
621 OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr)
622{
623 if (! opj_stream_flush(p_stream, p_event_mgr)) {
624 p_stream->m_status |= OPJ_STREAM_STATUS_ERROR;
625 return OPJ_FALSE;
626 }
627
628 p_stream->m_current_data = p_stream->m_stored_data;
629 p_stream->m_bytes_in_buffer = 0;
630
631 if (! p_stream->m_seek_fn(p_size, p_stream->m_user_data)) {
632 p_stream->m_status |= OPJ_STREAM_STATUS_ERROR;
633 return OPJ_FALSE;
634 } else {
635 p_stream->m_byte_offset = p_size;
636 }
637
638 return OPJ_TRUE;
639}
640
641OPJ_BOOL opj_stream_seek(opj_stream_private_t * p_stream, OPJ_OFF_T p_size,
642 struct opj_event_mgr * p_event_mgr)
643{
644 assert(p_size >= 0);
645 return p_stream->m_opj_seek(p_stream, p_size, p_event_mgr);
646}
647
648OPJ_BOOL opj_stream_has_seek(const opj_stream_private_t * p_stream)
649{
650 return p_stream->m_seek_fn != opj_stream_default_seek;
651}
652
653OPJ_SIZE_T opj_stream_default_read(void * p_buffer, OPJ_SIZE_T p_nb_bytes,
654 void * p_user_data)
655{
656 OPJ_ARG_NOT_USED(p_buffer);
657 OPJ_ARG_NOT_USED(p_nb_bytes);
658 OPJ_ARG_NOT_USED(p_user_data);
659 return (OPJ_SIZE_T) - 1;
660}
661
662OPJ_SIZE_T opj_stream_default_write(void * p_buffer, OPJ_SIZE_T p_nb_bytes,
663 void * p_user_data)
664{
665 OPJ_ARG_NOT_USED(p_buffer);
666 OPJ_ARG_NOT_USED(p_nb_bytes);
667 OPJ_ARG_NOT_USED(p_user_data);
668 return (OPJ_SIZE_T) - 1;
669}
670
671OPJ_OFF_T opj_stream_default_skip(OPJ_OFF_T p_nb_bytes, void * p_user_data)
672{
673 OPJ_ARG_NOT_USED(p_nb_bytes);
674 OPJ_ARG_NOT_USED(p_user_data);
675 return (OPJ_OFF_T) - 1;
676}
677
678OPJ_BOOL opj_stream_default_seek(OPJ_OFF_T p_nb_bytes, void * p_user_data)
679{
680 OPJ_ARG_NOT_USED(p_nb_bytes);
681 OPJ_ARG_NOT_USED(p_user_data);
682 return OPJ_FALSE;
683}
684