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