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