[2.0] Backport all changes from trunk
[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                 opj_free(l_stream->m_stored_data);
193                 l_stream->m_stored_data = 00;
194                 opj_free(l_stream);
195         }
196 }
197
198 void OPJ_CALLCONV opj_stream_set_read_function(opj_stream_t* p_stream, opj_stream_read_fn p_function)
199 {
200         opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
201
202         if ((!l_stream) || (! (l_stream->m_status & opj_stream_e_input))) {
203                 return;
204         }
205
206         l_stream->m_read_fn = p_function;
207 }
208
209 void OPJ_CALLCONV opj_stream_set_seek_function(opj_stream_t* p_stream, opj_stream_seek_fn p_function)
210 {
211         opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
212         
213         if (!l_stream) {
214                 return;
215         }
216         l_stream->m_seek_fn = p_function;
217 }
218
219 void OPJ_CALLCONV opj_stream_set_write_function(opj_stream_t* p_stream, opj_stream_write_fn p_function)
220 {
221         opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
222         
223         if ((!l_stream )|| (! (l_stream->m_status & opj_stream_e_output))) {
224                 return;
225         }
226
227         l_stream->m_write_fn = p_function;
228 }
229
230 void OPJ_CALLCONV opj_stream_set_skip_function(opj_stream_t* p_stream, opj_stream_skip_fn p_function)
231 {
232         opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
233         
234         if (! l_stream) {
235                 return;
236         }
237
238         l_stream->m_skip_fn = p_function;
239 }
240
241 void OPJ_CALLCONV opj_stream_set_user_data(opj_stream_t* p_stream, void * p_data)
242 {
243         opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
244         if (!l_stream)
245                 return;
246         l_stream->m_user_data = p_data;
247 }
248
249 void OPJ_CALLCONV opj_stream_set_user_data_length(opj_stream_t* p_stream, OPJ_UINT64 data_length)
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_length = data_length;
255 }
256
257 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)
258 {
259         OPJ_SIZE_T l_read_nb_bytes = 0;
260         if (p_stream->m_bytes_in_buffer >= p_size) {
261                 memcpy(p_buffer,p_stream->m_current_data,p_size);
262                 p_stream->m_current_data += p_size;
263                 p_stream->m_bytes_in_buffer -= p_size;
264                 l_read_nb_bytes += p_size;
265                 p_stream->m_byte_offset += (OPJ_OFF_T)p_size;
266                 return l_read_nb_bytes;
267         }
268
269         /* we are now in the case when the remaining data if not sufficient */
270         if (p_stream->m_status & opj_stream_e_end) {
271                 l_read_nb_bytes += p_stream->m_bytes_in_buffer;
272                 memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer);
273                 p_stream->m_current_data += p_stream->m_bytes_in_buffer;
274                 p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
275                 p_stream->m_bytes_in_buffer = 0;
276                 return l_read_nb_bytes ? l_read_nb_bytes : (OPJ_SIZE_T)-1;
277         }
278
279         /* the flag is not set, we copy data and then do an actual read on the stream */
280         if (p_stream->m_bytes_in_buffer) {
281                 l_read_nb_bytes += p_stream->m_bytes_in_buffer;
282                 memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer);
283                 p_stream->m_current_data = p_stream->m_stored_data;
284                 p_buffer += p_stream->m_bytes_in_buffer;
285                 p_size -= p_stream->m_bytes_in_buffer;
286                 p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
287                 p_stream->m_bytes_in_buffer = 0;
288         }
289         else {
290     /* case where we are already at the end of the buffer
291        so reset the m_current_data to point to the start of the
292        stored buffer to get ready to read from disk*/
293                 p_stream->m_current_data = p_stream->m_stored_data;
294         }
295
296         while(1){
297                 /* we should read less than a chunk -> read a chunk */
298                 if (p_size < p_stream->m_buffer_size) {
299                         /* we should do an actual read on the media */
300                         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);
301
302                         if (p_stream->m_bytes_in_buffer == (OPJ_SIZE_T)-1) {
303                                 /* end of stream */
304                                 opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n");
305
306                                 p_stream->m_bytes_in_buffer = 0;
307                                 p_stream->m_status |= opj_stream_e_end;
308                                 /* end of stream */
309                                 return l_read_nb_bytes ? l_read_nb_bytes : (OPJ_SIZE_T)-1;
310                         }
311                         else if (p_stream->m_bytes_in_buffer < p_size) {
312                                 /* not enough data */
313                                 l_read_nb_bytes += p_stream->m_bytes_in_buffer;
314                                 memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer);
315                                 p_stream->m_current_data = p_stream->m_stored_data;
316                                 p_buffer += p_stream->m_bytes_in_buffer;
317                                 p_size -= p_stream->m_bytes_in_buffer;
318                                 p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
319                                 p_stream->m_bytes_in_buffer = 0;
320                         }
321                         else {
322                                 l_read_nb_bytes += p_size;
323                                 memcpy(p_buffer,p_stream->m_current_data,p_size);
324                                 p_stream->m_current_data += p_size;
325                                 p_stream->m_bytes_in_buffer -= p_size;
326                                 p_stream->m_byte_offset += (OPJ_OFF_T)p_size;
327                                 return l_read_nb_bytes;
328                         }
329                 }
330                 else {
331                         /* direct read on the dest buffer */
332                         p_stream->m_bytes_in_buffer = p_stream->m_read_fn(p_buffer,p_size,p_stream->m_user_data);
333
334                         if (p_stream->m_bytes_in_buffer == (OPJ_SIZE_T)-1) {
335                                 /*  end of stream */
336                                 opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n");
337
338                                 p_stream->m_bytes_in_buffer = 0;
339                                 p_stream->m_status |= opj_stream_e_end;
340                                 /* end of stream */
341                                 return l_read_nb_bytes ? l_read_nb_bytes : (OPJ_SIZE_T)-1;
342                         }
343                         else if (p_stream->m_bytes_in_buffer < p_size) {
344                                 /* not enough data */
345                                 l_read_nb_bytes += p_stream->m_bytes_in_buffer;
346                                 p_stream->m_current_data = p_stream->m_stored_data;
347                                 p_buffer += p_stream->m_bytes_in_buffer;
348                                 p_size -= p_stream->m_bytes_in_buffer;
349                                 p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
350                                 p_stream->m_bytes_in_buffer = 0;
351                         }
352                         else {
353                                 /* we have read the exact size */
354                                 l_read_nb_bytes += p_stream->m_bytes_in_buffer;
355                                 p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
356                                 p_stream->m_current_data = p_stream->m_stored_data;
357                                 p_stream->m_bytes_in_buffer = 0;
358                                 return l_read_nb_bytes;
359                         }
360                 }
361         }
362 }
363
364 OPJ_SIZE_T opj_stream_write_data (opj_stream_private_t * p_stream,
365                                                                   const OPJ_BYTE * p_buffer,
366                                                                   OPJ_SIZE_T p_size, 
367                                                                   opj_event_mgr_t * p_event_mgr)
368 {
369         OPJ_SIZE_T l_remaining_bytes = 0;
370         OPJ_SIZE_T l_write_nb_bytes = 0;
371
372         if (p_stream->m_status & opj_stream_e_error) {
373                 return (OPJ_SIZE_T)-1;
374         }
375
376         while(1) {
377                 l_remaining_bytes = p_stream->m_buffer_size - p_stream->m_bytes_in_buffer;
378                 
379                 /* we have more memory than required */
380                 if (l_remaining_bytes >= p_size) {
381                         memcpy(p_stream->m_current_data, p_buffer, p_size);
382                         
383                         p_stream->m_current_data += p_size;
384                         p_stream->m_bytes_in_buffer += p_size;
385                         l_write_nb_bytes += p_size;
386                         p_stream->m_byte_offset += (OPJ_OFF_T)p_size;
387                         
388                         return l_write_nb_bytes;
389                 }
390
391                 /* we copy data and then do an actual read on the stream */
392                 if (l_remaining_bytes) {
393                         l_write_nb_bytes += l_remaining_bytes;
394                         
395                         memcpy(p_stream->m_current_data,p_buffer,l_remaining_bytes);
396                         
397                         p_stream->m_current_data = p_stream->m_stored_data;
398                         
399                         p_buffer += l_remaining_bytes;
400                         p_size -= l_remaining_bytes;
401                         p_stream->m_bytes_in_buffer += l_remaining_bytes;
402                         p_stream->m_byte_offset += (OPJ_OFF_T)l_remaining_bytes;
403                 }
404
405                 if (! opj_stream_flush(p_stream, p_event_mgr)) {
406                         return (OPJ_SIZE_T)-1;
407                 }
408         }
409
410 }
411
412 OPJ_BOOL opj_stream_flush (opj_stream_private_t * p_stream, opj_event_mgr_t * p_event_mgr)
413 {
414         /* the number of bytes written on the media. */
415         OPJ_SIZE_T l_current_write_nb_bytes = 0;
416
417         p_stream->m_current_data = p_stream->m_stored_data;
418
419         while (p_stream->m_bytes_in_buffer) {
420                 /* we should do an actual write on the media */
421                 l_current_write_nb_bytes = p_stream->m_write_fn(p_stream->m_current_data,
422                                                                                                                 p_stream->m_bytes_in_buffer,
423                                                                                                                 p_stream->m_user_data);
424                 
425                 if (l_current_write_nb_bytes == (OPJ_SIZE_T)-1) {
426                         p_stream->m_status |= opj_stream_e_error;
427                         opj_event_msg(p_event_mgr, EVT_INFO, "Error on writing stream!\n");
428
429                         return OPJ_FALSE;
430                 }
431
432                 p_stream->m_current_data += l_current_write_nb_bytes;
433                 p_stream->m_bytes_in_buffer -= l_current_write_nb_bytes;
434         }
435
436         p_stream->m_current_data = p_stream->m_stored_data;
437         
438         return OPJ_TRUE;
439 }
440
441 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)
442 {
443         OPJ_OFF_T l_skip_nb_bytes = 0;
444         OPJ_OFF_T l_current_skip_nb_bytes = 0;
445         
446         assert( p_size >= 0 );
447         
448         if (p_stream->m_bytes_in_buffer >= (OPJ_SIZE_T)p_size) {
449                 p_stream->m_current_data += p_size;
450                 /* it is safe to cast p_size to OPJ_SIZE_T since it is <= m_bytes_in_buffer
451                 which is of type OPJ_SIZE_T */
452                 p_stream->m_bytes_in_buffer -= (OPJ_SIZE_T)p_size;
453                 l_skip_nb_bytes += p_size;
454                 p_stream->m_byte_offset += l_skip_nb_bytes;
455                 return l_skip_nb_bytes;
456         }
457
458         /* we are now in the case when the remaining data if not sufficient */
459         if (p_stream->m_status & opj_stream_e_end) {
460                 l_skip_nb_bytes += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
461                 p_stream->m_current_data += p_stream->m_bytes_in_buffer;
462                 p_stream->m_bytes_in_buffer = 0;
463                 p_stream->m_byte_offset += l_skip_nb_bytes;
464                 return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T) -1;
465         }
466
467         /* the flag is not set, we copy data and then do an actual skip on the stream */
468         if (p_stream->m_bytes_in_buffer) {
469                 l_skip_nb_bytes += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
470                 p_stream->m_current_data = p_stream->m_stored_data;
471                 p_size -= (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
472                 p_stream->m_bytes_in_buffer = 0;
473         }
474
475         while (p_size > 0) {
476                 /* we should do an actual skip on the media */
477                 l_current_skip_nb_bytes = p_stream->m_skip_fn(p_size, p_stream->m_user_data);
478                 if (l_current_skip_nb_bytes == (OPJ_OFF_T) -1) {
479                         opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n");
480
481                         p_stream->m_status |= opj_stream_e_end;
482                         p_stream->m_byte_offset += l_skip_nb_bytes;
483                         /* end if stream */
484                         return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T) -1;
485                 }
486                 p_size -= l_current_skip_nb_bytes;
487                 l_skip_nb_bytes += l_current_skip_nb_bytes;
488         }
489
490         p_stream->m_byte_offset += l_skip_nb_bytes;
491         
492         return l_skip_nb_bytes;
493 }
494
495 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)
496 {
497         OPJ_BOOL l_is_written = 0;
498         OPJ_OFF_T l_current_skip_nb_bytes = 0;
499         OPJ_OFF_T l_skip_nb_bytes = 0;
500
501         if (p_stream->m_status & opj_stream_e_error) {
502                 return (OPJ_OFF_T) -1;
503         }
504
505         /* we should flush data */
506         l_is_written = opj_stream_flush (p_stream, p_event_mgr);
507         if (! l_is_written) {
508                 p_stream->m_status |= opj_stream_e_error;
509                 p_stream->m_bytes_in_buffer = 0;
510                 return (OPJ_OFF_T) -1;
511         }
512         /* then skip */
513
514         while (p_size > 0) {
515                 /* we should do an actual skip on the media */
516                 l_current_skip_nb_bytes = p_stream->m_skip_fn(p_size, p_stream->m_user_data);
517                 
518                 if (l_current_skip_nb_bytes == (OPJ_OFF_T)-1) {
519                         opj_event_msg(p_event_mgr, EVT_INFO, "Stream error!\n");
520
521                         p_stream->m_status |= opj_stream_e_error;
522                         p_stream->m_byte_offset += l_skip_nb_bytes;
523                         /* end if stream */
524                         return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T)-1;
525                 }
526                 p_size -= l_current_skip_nb_bytes;
527                 l_skip_nb_bytes += l_current_skip_nb_bytes;
528         }
529
530         p_stream->m_byte_offset += l_skip_nb_bytes;
531         
532         return l_skip_nb_bytes;
533 }
534
535 OPJ_OFF_T opj_stream_tell (const opj_stream_private_t * p_stream)
536 {
537         return p_stream->m_byte_offset;
538 }
539
540 OPJ_OFF_T opj_stream_get_number_byte_left (const opj_stream_private_t * p_stream)
541 {
542   assert( p_stream->m_byte_offset >= 0 );
543   assert( p_stream->m_user_data_length >= (OPJ_UINT64)p_stream->m_byte_offset);
544   return p_stream->m_user_data_length ?
545                                 (OPJ_OFF_T)(p_stream->m_user_data_length) - p_stream->m_byte_offset :
546                                 0;
547 }
548
549 OPJ_OFF_T opj_stream_skip (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr)
550 {
551         assert(p_size >= 0);
552         return p_stream->m_opj_skip(p_stream,p_size,p_event_mgr);
553 }
554
555 OPJ_BOOL opj_stream_read_seek (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr)
556 {
557         OPJ_ARG_NOT_USED(p_event_mgr);
558         p_stream->m_current_data = p_stream->m_stored_data;
559         p_stream->m_bytes_in_buffer = 0;
560
561         if( !(p_stream->m_seek_fn(p_size,p_stream->m_user_data)) ) {
562                 p_stream->m_status |= opj_stream_e_end;
563                 return OPJ_FALSE;
564         }
565         else {
566                 /* reset stream status */
567                 p_stream->m_status &= (~opj_stream_e_end);
568                 p_stream->m_byte_offset = p_size;
569
570         }
571
572         return OPJ_TRUE;
573 }
574
575 OPJ_BOOL opj_stream_write_seek (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr)
576 {
577         if (! opj_stream_flush(p_stream,p_event_mgr)) {
578                 p_stream->m_status |= opj_stream_e_error;
579                 return OPJ_FALSE;
580         }
581
582         p_stream->m_current_data = p_stream->m_stored_data;
583         p_stream->m_bytes_in_buffer = 0;
584
585         if (! p_stream->m_seek_fn(p_size,p_stream->m_user_data)) {
586                 p_stream->m_status |= opj_stream_e_error;
587                 return OPJ_FALSE;
588         }
589         else {
590                 p_stream->m_byte_offset = p_size;
591         }
592
593         return OPJ_TRUE;
594 }
595
596 OPJ_BOOL opj_stream_seek (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr)
597 {
598         assert(p_size >= 0);
599         return p_stream->m_opj_seek(p_stream,p_size,p_event_mgr);
600 }
601
602 OPJ_BOOL opj_stream_has_seek (const opj_stream_private_t * p_stream)
603 {
604         return p_stream->m_seek_fn != opj_stream_default_seek;
605 }
606
607 OPJ_SIZE_T opj_stream_default_read (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data)
608 {
609         OPJ_ARG_NOT_USED(p_buffer);
610         OPJ_ARG_NOT_USED(p_nb_bytes);
611         OPJ_ARG_NOT_USED(p_user_data);
612         return (OPJ_SIZE_T) -1;
613 }
614
615 OPJ_SIZE_T opj_stream_default_write (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data)
616 {
617         OPJ_ARG_NOT_USED(p_buffer);
618         OPJ_ARG_NOT_USED(p_nb_bytes);
619         OPJ_ARG_NOT_USED(p_user_data);
620         return (OPJ_SIZE_T) -1;
621 }
622
623 OPJ_OFF_T opj_stream_default_skip (OPJ_OFF_T p_nb_bytes, void * p_user_data)
624 {
625         OPJ_ARG_NOT_USED(p_nb_bytes);
626         OPJ_ARG_NOT_USED(p_user_data);
627         return (OPJ_OFF_T) -1;
628 }
629
630 OPJ_BOOL opj_stream_default_seek (OPJ_OFF_T p_nb_bytes, void * p_user_data)
631 {
632         OPJ_ARG_NOT_USED(p_nb_bytes);
633         OPJ_ARG_NOT_USED(p_user_data);
634         return OPJ_FALSE;
635 }