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