[trunk] Fix spelling. writting -> writing
[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  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "opj_includes.h"
33
34 /* ----------------------------------------------------------------------- */
35
36 opj_cio_t* OPJ_CALLCONV opj_cio_open(opj_common_ptr cinfo, unsigned char *buffer, int length) {
37         opj_cp_t *cp = NULL;
38         opj_cio_t *cio = (opj_cio_t*)opj_malloc(sizeof(opj_cio_t));
39         if(!cio) return NULL;
40         cio->cinfo = cinfo;
41         if(buffer && length) {
42                 /* wrap a user buffer containing the encoded image */
43                 cio->openmode = OPJ_STREAM_READ;
44                 cio->buffer = buffer;
45                 cio->length = length;
46         }
47         else if(!buffer && !length && cinfo) {
48                 /* allocate a buffer for the encoded image */
49                 cio->openmode = OPJ_STREAM_WRITE;
50                 switch(cinfo->codec_format) {
51                         case CODEC_J2K:
52                                 cp = ((opj_j2k_t*)cinfo->j2k_handle)->cp;
53                                 break;
54                         case CODEC_JP2:
55                                 cp = ((opj_jp2_t*)cinfo->jp2_handle)->j2k->cp;
56                                 break;
57                         default:
58                                 opj_free(cio);
59                                 return NULL;
60                 }
61                 cio->length = (int) (0.1625 * cp->img_size + 2000); /* 0.1625 = 1.3/8 and 2000 bytes as a minimum for headers */
62                 assert(cio->length >= 0);
63                 cio->buffer = (unsigned char *)opj_malloc((OPJ_SIZE_T)cio->length);
64                 if(!cio->buffer) {
65                         opj_event_msg(cio->cinfo, EVT_ERROR, "Error allocating memory for compressed bitstream\n");
66                         opj_free(cio);
67                         return NULL;
68                 }
69         }
70         else {
71                 opj_free(cio);
72                 return NULL;
73         }
74
75         /* Initialize byte IO */
76         cio->start = cio->buffer;
77         cio->end = cio->buffer + cio->length;
78         cio->bp = cio->buffer;
79
80         return cio;
81 }
82
83 void OPJ_CALLCONV opj_cio_close(opj_cio_t *cio) {
84         if(cio) {
85                 if(cio->openmode == OPJ_STREAM_WRITE) {
86                         /* destroy the allocated buffer */
87                         opj_free(cio->buffer);
88                 }
89                 /* destroy the cio */
90                 opj_free(cio);
91         }
92 }
93
94 /* ----------------------------------------------------------------------- */
95
96 /*
97  * Get position in byte stream.
98  */
99 OPJ_OFF_T OPJ_CALLCONV cio_tell(opj_cio_t *cio) {
100         return cio->bp - cio->start;
101 }
102
103 /*
104  * Set position in byte stream.
105  *
106  * pos : position, in number of bytes, from the beginning of the stream
107  */
108 void OPJ_CALLCONV cio_seek(opj_cio_t *cio, int pos) {
109         cio->bp = cio->start + pos;
110 }
111
112 /*
113  * Number of bytes left before the end of the stream.
114  */
115 OPJ_SIZE_T cio_numbytesleft(opj_cio_t *cio) {
116         const ptrdiff_t diff = cio->end - cio->bp;
117   assert( diff >= 0 );
118   return (OPJ_SIZE_T)diff;
119 }
120
121 /*
122  * Get pointer to the current position in the stream.
123  */
124 unsigned char *cio_getbp(opj_cio_t *cio) {
125         return cio->bp;
126 }
127
128 /*
129  * Write a byte.
130  */
131 opj_bool cio_byteout(opj_cio_t *cio, unsigned char v) {
132         if (cio->bp >= cio->end) {
133                 opj_event_msg(cio->cinfo, EVT_ERROR, "write error\n");
134                 return OPJ_FALSE;
135         }
136         *cio->bp++ = v;
137         return OPJ_TRUE;
138 }
139
140 /*
141  * Read a byte.
142  */
143 unsigned char cio_bytein(opj_cio_t *cio) {
144         if (cio->bp >= cio->end) {
145                 opj_event_msg(cio->cinfo, EVT_ERROR, "read error: passed the end of the codestream (start = %d, current = %d, end = %d\n", cio->start, cio->bp, cio->end);
146                 return 0;
147         }
148         return *cio->bp++;
149 }
150
151 /*
152  * Write some bytes.
153  *
154  * v : value to write
155  * n : number of bytes to write
156  */
157 unsigned int cio_write(opj_cio_t *cio, unsigned long long int v, int n) {
158         int i;
159         for (i = n - 1; i >= 0; i--) {
160                 if( !cio_byteout(cio, (unsigned char) ((v >> (i << 3)) & 0xff)) )
161                         return 0;
162         }
163   assert( n >= 0 );
164         return (unsigned int)n;
165 }
166
167 /*
168  * Read some bytes.
169  *
170  * n : number of bytes to read
171  *
172  * return : value of the n bytes read
173  */
174 unsigned int cio_read(opj_cio_t *cio, int n) {
175         int i;
176         unsigned int v = 0;
177         for (i = n - 1; i >= 0; i--) {
178     const unsigned int c = cio_bytein(cio);
179                 v += c << (i << 3);
180         }
181         return v;
182 }
183
184 /* 
185  * Skip some bytes.
186  *
187  * n : number of bytes to skip
188  */
189 void cio_skip(opj_cio_t *cio, int n) {
190         cio->bp += n;
191 }
192
193 /* ----------------------------------------------------------------------- */
194
195 void opj_write_bytes_BE (OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, OPJ_UINT32 p_nb_bytes)
196 {
197         const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + p_nb_bytes;
198
199         assert(p_nb_bytes > 0 && p_nb_bytes <=  sizeof(OPJ_UINT32));
200
201         memcpy(p_buffer,l_data_ptr,p_nb_bytes);
202 }
203
204 void opj_write_bytes_LE (OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, OPJ_UINT32 p_nb_bytes)
205 {
206         const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + p_nb_bytes - 1;
207         OPJ_UINT32 i;
208
209         assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32));
210
211         for     (i=0;i<p_nb_bytes;++i) {
212                 *(p_buffer++) = *(l_data_ptr--);
213         }
214 }
215
216 void opj_read_bytes_BE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, OPJ_UINT32 p_nb_bytes)
217 {
218         OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value);
219
220         assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32));
221
222         *p_value = 0;
223         memcpy(l_data_ptr+4-p_nb_bytes,p_buffer,p_nb_bytes);
224 }
225
226 void opj_read_bytes_LE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, OPJ_UINT32 p_nb_bytes)
227 {
228         OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + p_nb_bytes-1;
229         OPJ_UINT32 i;
230
231         assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32));
232
233         *p_value = 0;
234         for (i=0;i<p_nb_bytes;++i) {
235                 *(l_data_ptr--) = *(p_buffer++);
236         }
237 }
238
239 void opj_write_double_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT64 p_value)
240 {
241         const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value);
242         memcpy(p_buffer,l_data_ptr,sizeof(OPJ_FLOAT64));
243 }
244
245 void opj_write_double_LE(OPJ_BYTE * p_buffer, OPJ_FLOAT64 p_value)
246 {
247         const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + sizeof(OPJ_FLOAT64) - 1;
248         OPJ_UINT32 i;
249         for     (i=0;i<sizeof(OPJ_FLOAT64);++i) {
250                 *(p_buffer++) = *(l_data_ptr--);
251         }
252 }
253
254 void opj_read_double_BE(const OPJ_BYTE * p_buffer, OPJ_FLOAT64 * p_value)
255 {
256         OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value);
257         memcpy(l_data_ptr,p_buffer,sizeof(OPJ_FLOAT64));
258 }
259
260 void opj_read_double_LE(const OPJ_BYTE * p_buffer, OPJ_FLOAT64 * p_value)
261 {
262         OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + sizeof(OPJ_FLOAT64)-1;
263         OPJ_UINT32 i;
264         for (i=0;i<sizeof(OPJ_FLOAT64);++i) {
265                 *(l_data_ptr--) = *(p_buffer++);
266         }
267 }
268
269 void opj_write_float_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value)
270 {
271         const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value);
272         memcpy(p_buffer,l_data_ptr,sizeof(OPJ_FLOAT32));
273 }
274
275 void opj_write_float_LE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value)
276 {
277         const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + sizeof(OPJ_FLOAT32) - 1;
278         OPJ_UINT32 i;
279         for     (i=0;i<sizeof(OPJ_FLOAT32);++i) {
280                 *(p_buffer++) = *(l_data_ptr--);
281         }
282 }
283
284 void opj_read_float_BE(const OPJ_BYTE * p_buffer, OPJ_FLOAT32 * p_value)
285 {
286         OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value);
287         memcpy(l_data_ptr,p_buffer,sizeof(OPJ_FLOAT32));
288 }
289
290 void opj_read_float_LE(const OPJ_BYTE * p_buffer, OPJ_FLOAT32 * p_value)
291 {
292         OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + sizeof(OPJ_FLOAT32)-1;
293         OPJ_UINT32 i;
294         for     (i=0;i<sizeof(OPJ_FLOAT32);++i) {
295                 *(l_data_ptr--) = *(p_buffer++);
296         }
297 }
298
299 opj_stream_t* OPJ_CALLCONV opj_stream_create(OPJ_SIZE_T p_buffer_size,opj_bool l_is_input)
300 {
301         opj_stream_private_t * l_stream = 00;
302         l_stream = (opj_stream_private_t*) opj_malloc(sizeof(opj_stream_private_t));
303         if (! l_stream) {
304                 return 00;
305         }
306
307         memset(l_stream,0,sizeof(opj_stream_private_t));
308         l_stream->m_buffer_size = p_buffer_size;
309         l_stream->m_stored_data = (OPJ_BYTE *) opj_malloc(p_buffer_size);
310         if (! l_stream->m_stored_data) {
311                 opj_free(l_stream);
312                 return 00;
313         }
314
315         l_stream->m_current_data = l_stream->m_stored_data;
316
317         if (l_is_input) {
318                 l_stream->m_status |= opj_stream_e_input;
319                 l_stream->m_opj_skip = opj_stream_read_skip;
320                 l_stream->m_opj_seek = opj_stream_read_seek;
321         }
322         else {
323                 l_stream->m_status |= opj_stream_e_output;
324                 l_stream->m_opj_skip = opj_stream_write_skip;
325                 l_stream->m_opj_seek = opj_stream_write_seek;
326         }
327
328         l_stream->m_read_fn = opj_stream_default_read;
329         l_stream->m_write_fn = opj_stream_default_write;
330         l_stream->m_skip_fn = opj_stream_default_skip;
331         l_stream->m_seek_fn = opj_stream_default_seek;
332
333         return (opj_stream_t *) l_stream;
334 }
335
336 opj_stream_t* OPJ_CALLCONV opj_stream_default_create(opj_bool l_is_input)
337 {
338         return opj_stream_create(J2K_STREAM_CHUNK_SIZE,l_is_input);
339 }
340
341 OPJ_API void OPJ_CALLCONV opj_stream_destroy(opj_stream_t* p_stream)
342 {
343         opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
344         
345         if (l_stream) {
346                 opj_free(l_stream->m_stored_data);
347                 l_stream->m_stored_data = 00;
348                 opj_free(l_stream);
349         }
350 }
351
352 OPJ_API void OPJ_CALLCONV opj_stream_set_read_function(opj_stream_t* p_stream, opj_stream_read_fn p_function)
353 {
354         opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
355
356         if ((!l_stream) || (! (l_stream->m_status & opj_stream_e_input))) {
357                 return;
358         }
359
360         l_stream->m_read_fn = p_function;
361 }
362
363 OPJ_API void OPJ_CALLCONV opj_stream_set_seek_function(opj_stream_t* p_stream, opj_stream_seek_fn p_function)
364 {
365         opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
366         
367         if (!l_stream) {
368                 return;
369         }
370         l_stream->m_seek_fn = p_function;
371 }
372
373 OPJ_API void OPJ_CALLCONV opj_stream_set_write_function(opj_stream_t* p_stream, opj_stream_write_fn p_function)
374 {
375         opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
376         
377         if ((!l_stream )|| (! (l_stream->m_status & opj_stream_e_output))) {
378                 return;
379         }
380
381         l_stream->m_write_fn = p_function;
382 }
383
384 OPJ_API void OPJ_CALLCONV opj_stream_set_skip_function(opj_stream_t* p_stream, opj_stream_skip_fn p_function)
385 {
386         opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
387         
388         if (! l_stream) {
389                 return;
390         }
391
392         l_stream->m_skip_fn = p_function;
393 }
394
395 OPJ_API void OPJ_CALLCONV opj_stream_set_user_data(opj_stream_t* p_stream, void * p_data)
396 {
397         opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
398         l_stream->m_user_data = p_data;
399 }
400
401 OPJ_API void OPJ_CALLCONV opj_stream_set_user_data_length(opj_stream_t* p_stream, OPJ_UINT64 data_length)
402 {
403         opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
404         l_stream->m_user_data_length = data_length;
405 }
406
407 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)
408 {
409         OPJ_SIZE_T l_read_nb_bytes = 0;
410         if (p_stream->m_bytes_in_buffer >= p_size) {
411                 memcpy(p_buffer,p_stream->m_current_data,p_size);
412                 p_stream->m_current_data += p_size;
413                 p_stream->m_bytes_in_buffer -= p_size;
414                 l_read_nb_bytes += p_size;
415                 p_stream->m_byte_offset += (OPJ_OFF_T)p_size;
416                 return l_read_nb_bytes;
417         }
418
419         /* we are now in the case when the remaining data if not sufficient */
420         if (p_stream->m_status & opj_stream_e_end) {
421                 l_read_nb_bytes += p_stream->m_bytes_in_buffer;
422                 memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer);
423                 p_stream->m_current_data += p_stream->m_bytes_in_buffer;
424                 p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
425                 p_stream->m_bytes_in_buffer = 0;
426                 return l_read_nb_bytes ? l_read_nb_bytes : (OPJ_SIZE_T)-1;
427         }
428
429         /* the flag is not set, we copy data and then do an actual read on the stream */
430         if (p_stream->m_bytes_in_buffer) {
431                 l_read_nb_bytes += p_stream->m_bytes_in_buffer;
432                 memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer);
433                 p_stream->m_current_data = p_stream->m_stored_data;
434                 p_buffer += p_stream->m_bytes_in_buffer;
435                 p_size -= p_stream->m_bytes_in_buffer;
436                 p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
437                 p_stream->m_bytes_in_buffer = 0;
438         }
439         else {
440     /* case where we are already at the end of the buffer
441        so reset the m_current_data to point to the start of the
442        stored buffer to get ready to read from disk*/
443                 p_stream->m_current_data = p_stream->m_stored_data;
444         }
445
446         while(1){
447                 /* we should read less than a chunk -> read a chunk */
448                 if (p_size < p_stream->m_buffer_size) {
449                         /* we should do an actual read on the media */
450                         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);
451
452                         if (p_stream->m_bytes_in_buffer == (OPJ_SIZE_T)-1) {
453                                 /* end of stream */
454                                 opj_event_msg_v2(p_event_mgr, EVT_INFO, "Stream reached its end !\n");
455
456                                 p_stream->m_bytes_in_buffer = 0;
457                                 p_stream->m_status |= opj_stream_e_end;
458                                 /* end of stream */
459                                 return l_read_nb_bytes ? l_read_nb_bytes : (OPJ_SIZE_T)-1;
460                         }
461                         else if (p_stream->m_bytes_in_buffer < p_size) {
462                                 /* not enough data */
463                                 l_read_nb_bytes += p_stream->m_bytes_in_buffer;
464                                 memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer);
465                                 p_stream->m_current_data = p_stream->m_stored_data;
466                                 p_buffer += p_stream->m_bytes_in_buffer;
467                                 p_size -= p_stream->m_bytes_in_buffer;
468                                 p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
469                                 p_stream->m_bytes_in_buffer = 0;
470                         }
471                         else {
472                                 l_read_nb_bytes += p_size;
473                                 memcpy(p_buffer,p_stream->m_current_data,p_size);
474                                 p_stream->m_current_data += p_size;
475                                 p_stream->m_bytes_in_buffer -= p_size;
476                                 p_stream->m_byte_offset += (OPJ_OFF_T)p_size;
477                                 return l_read_nb_bytes;
478                         }
479                 }
480                 else {
481                         /* direct read on the dest buffer */
482                         p_stream->m_bytes_in_buffer = p_stream->m_read_fn(p_buffer,p_size,p_stream->m_user_data);
483
484                         if (p_stream->m_bytes_in_buffer == (OPJ_SIZE_T)-1) {
485                                 /*  end of stream */
486                                 opj_event_msg_v2(p_event_mgr, EVT_INFO, "Stream reached its end !\n");
487
488                                 p_stream->m_bytes_in_buffer = 0;
489                                 p_stream->m_status |= opj_stream_e_end;
490                                 /* end of stream */
491                                 return l_read_nb_bytes ? l_read_nb_bytes : (OPJ_SIZE_T)-1;
492                         }
493                         else if (p_stream->m_bytes_in_buffer < p_size) {
494                                 /* not enough data */
495                                 l_read_nb_bytes += p_stream->m_bytes_in_buffer;
496                                 p_stream->m_current_data = p_stream->m_stored_data;
497                                 p_buffer += p_stream->m_bytes_in_buffer;
498                                 p_size -= p_stream->m_bytes_in_buffer;
499                                 p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
500                                 p_stream->m_bytes_in_buffer = 0;
501                         }
502                         else {
503                                 /* we have read the exact size */
504                                 l_read_nb_bytes += p_stream->m_bytes_in_buffer;
505                                 p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
506                                 p_stream->m_current_data = p_stream->m_stored_data;
507                                 p_stream->m_bytes_in_buffer = 0;
508                                 return l_read_nb_bytes;
509                         }
510                 }
511         }
512 }
513
514 OPJ_SIZE_T opj_stream_write_data (opj_stream_private_t * p_stream,
515                                                                   const OPJ_BYTE * p_buffer,
516                                                                   OPJ_SIZE_T p_size, 
517                                                                   opj_event_mgr_t * p_event_mgr)
518 {
519         OPJ_SIZE_T l_remaining_bytes = 0;
520         OPJ_SIZE_T l_write_nb_bytes = 0;
521
522         if (p_stream->m_status & opj_stream_e_error) {
523                 return (OPJ_SIZE_T)-1;
524         }
525
526         while(1) {
527                 l_remaining_bytes = p_stream->m_buffer_size - p_stream->m_bytes_in_buffer;
528                 
529                 /* we have more memory than required */
530                 if (l_remaining_bytes >= p_size) {
531                         memcpy(p_stream->m_current_data, p_buffer, p_size);
532                         
533                         p_stream->m_current_data += p_size;
534                         p_stream->m_bytes_in_buffer += p_size;
535                         l_write_nb_bytes += p_size;
536                         p_stream->m_byte_offset += (OPJ_OFF_T)p_size;
537                         
538                         return l_write_nb_bytes;
539                 }
540
541                 /* we copy data and then do an actual read on the stream */
542                 if (l_remaining_bytes) {
543                         l_write_nb_bytes += l_remaining_bytes;
544                         
545                         memcpy(p_stream->m_current_data,p_buffer,l_remaining_bytes);
546                         
547                         p_stream->m_current_data = p_stream->m_stored_data;
548                         
549                         p_buffer += l_remaining_bytes;
550                         p_size -= l_remaining_bytes;
551                         p_stream->m_bytes_in_buffer += l_remaining_bytes;
552                         p_stream->m_byte_offset += (OPJ_OFF_T)l_remaining_bytes;
553                 }
554
555                 if (! opj_stream_flush(p_stream, p_event_mgr)) {
556                         return (OPJ_SIZE_T)-1;
557                 }
558         }
559
560 }
561
562 opj_bool opj_stream_flush (opj_stream_private_t * p_stream, opj_event_mgr_t * p_event_mgr)
563 {
564         /* the number of bytes written on the media. */
565         OPJ_SIZE_T l_current_write_nb_bytes = 0;
566
567         p_stream->m_current_data = p_stream->m_stored_data;
568
569         while (p_stream->m_bytes_in_buffer) {
570                 /* we should do an actual write on the media */
571                 l_current_write_nb_bytes = p_stream->m_write_fn(p_stream->m_current_data,
572                                                                                                                 p_stream->m_bytes_in_buffer,
573                                                                                                                 p_stream->m_user_data);
574                 
575                 if (l_current_write_nb_bytes == (OPJ_SIZE_T)-1) {
576                         p_stream->m_status |= opj_stream_e_error;
577                         opj_event_msg_v2(p_event_mgr, EVT_INFO, "Error on writing stream!\n");
578
579                         return OPJ_FALSE;
580                 }
581
582                 p_stream->m_current_data += l_current_write_nb_bytes;
583                 p_stream->m_bytes_in_buffer -= l_current_write_nb_bytes;
584         }
585
586         p_stream->m_current_data = p_stream->m_stored_data;
587         
588         return OPJ_TRUE;
589 }
590
591 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)
592 {
593         OPJ_OFF_T l_skip_nb_bytes = 0;
594         OPJ_OFF_T l_current_skip_nb_bytes = 0;
595         
596         assert( p_size >= 0 );
597         
598         if (p_stream->m_bytes_in_buffer >= (OPJ_SIZE_T)p_size) {
599                 p_stream->m_current_data += p_size;
600                 /* it is safe to cast p_size to OPJ_SIZE_T since it is <= m_bytes_in_buffer
601                 which is of type OPJ_SIZE_T */
602                 p_stream->m_bytes_in_buffer -= (OPJ_SIZE_T)p_size;
603                 l_skip_nb_bytes += p_size;
604                 p_stream->m_byte_offset += l_skip_nb_bytes;
605                 return l_skip_nb_bytes;
606         }
607
608         /* we are now in the case when the remaining data if not sufficient */
609         if (p_stream->m_status & opj_stream_e_end) {
610                 l_skip_nb_bytes += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
611                 p_stream->m_current_data += p_stream->m_bytes_in_buffer;
612                 p_stream->m_bytes_in_buffer = 0;
613                 p_stream->m_byte_offset += l_skip_nb_bytes;
614                 return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T) -1;
615         }
616
617         /* the flag is not set, we copy data and then do an actual skip on the stream */
618         if (p_stream->m_bytes_in_buffer) {
619                 l_skip_nb_bytes += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
620                 p_stream->m_current_data = p_stream->m_stored_data;
621                 p_size -= (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
622                 p_stream->m_bytes_in_buffer = 0;
623         }
624
625         while (p_size > 0) {
626                 /* we should do an actual skip on the media */
627                 l_current_skip_nb_bytes = p_stream->m_skip_fn(p_size, p_stream->m_user_data);
628                 if (l_current_skip_nb_bytes == (OPJ_OFF_T) -1) {
629                         opj_event_msg_v2(p_event_mgr, EVT_INFO, "Stream reached its end !\n");
630
631                         p_stream->m_status |= opj_stream_e_end;
632                         p_stream->m_byte_offset += l_skip_nb_bytes;
633                         /* end if stream */
634                         return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T) -1;
635                 }
636                 p_size -= l_current_skip_nb_bytes;
637                 l_skip_nb_bytes += l_current_skip_nb_bytes;
638         }
639
640         p_stream->m_byte_offset += l_skip_nb_bytes;
641         
642         return l_skip_nb_bytes;
643 }
644
645 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)
646 {
647         opj_bool l_is_written = 0;
648         OPJ_OFF_T l_current_skip_nb_bytes = 0;
649         OPJ_OFF_T l_skip_nb_bytes = 0;
650
651         if (p_stream->m_status & opj_stream_e_error) {
652                 return (OPJ_OFF_T) -1;
653         }
654
655         /* we should flush data */
656         l_is_written = opj_stream_flush (p_stream, p_event_mgr);
657         if (! l_is_written) {
658                 p_stream->m_status |= opj_stream_e_error;
659                 p_stream->m_bytes_in_buffer = 0;
660                 p_stream->m_current_data = p_stream->m_current_data;
661                 return (OPJ_OFF_T) -1;
662         }
663         /* then skip */
664
665         while (p_size > 0) {
666                 /* we should do an actual skip on the media */
667                 l_current_skip_nb_bytes = p_stream->m_skip_fn(p_size, p_stream->m_user_data);
668                 
669                 if (l_current_skip_nb_bytes == (OPJ_OFF_T)-1) {
670                         opj_event_msg_v2(p_event_mgr, EVT_INFO, "Stream error!\n");
671
672                         p_stream->m_status |= opj_stream_e_error;
673                         p_stream->m_byte_offset += l_skip_nb_bytes;
674                         /* end if stream */
675                         return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T)-1;
676                 }
677                 p_size -= l_current_skip_nb_bytes;
678                 l_skip_nb_bytes += l_current_skip_nb_bytes;
679         }
680
681         p_stream->m_byte_offset += l_skip_nb_bytes;
682         
683         return l_skip_nb_bytes;
684 }
685
686 OPJ_OFF_T opj_stream_tell (const opj_stream_private_t * p_stream)
687 {
688         return p_stream->m_byte_offset;
689 }
690
691 OPJ_OFF_T opj_stream_get_number_byte_left (const opj_stream_private_t * p_stream)
692 {
693   assert( p_stream->m_byte_offset >= 0 );
694   assert( p_stream->m_user_data_length >= (OPJ_UINT64)p_stream->m_byte_offset);
695   return p_stream->m_user_data_length ?
696                                 (OPJ_OFF_T)(p_stream->m_user_data_length) - p_stream->m_byte_offset :
697                                 0;
698 }
699
700 OPJ_OFF_T opj_stream_skip (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr)
701 {
702         assert(p_size >= 0);
703         return p_stream->m_opj_skip(p_stream,p_size,p_event_mgr);
704 }
705
706 opj_bool opj_stream_read_seek (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr)
707 {
708         OPJ_ARG_NOT_USED(p_event_mgr);
709         p_stream->m_current_data = p_stream->m_stored_data;
710         p_stream->m_bytes_in_buffer = 0;
711
712         if( !(p_stream->m_seek_fn(p_size,p_stream->m_user_data)) ) {
713                 p_stream->m_status |= opj_stream_e_end;
714                 return OPJ_FALSE;
715         }
716         else {
717                 /* reset stream status */
718                 p_stream->m_status &= (~opj_stream_e_end);
719                 p_stream->m_byte_offset = p_size;
720
721         }
722
723         return OPJ_TRUE;
724 }
725
726 opj_bool opj_stream_write_seek (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr)
727 {
728         if (! opj_stream_flush(p_stream,p_event_mgr)) {
729                 p_stream->m_status |= opj_stream_e_error;
730                 return OPJ_FALSE;
731         }
732
733         p_stream->m_current_data = p_stream->m_stored_data;
734         p_stream->m_bytes_in_buffer = 0;
735
736         if (! p_stream->m_seek_fn(p_size,p_stream->m_user_data)) {
737                 p_stream->m_status |= opj_stream_e_error;
738                 return OPJ_FALSE;
739         }
740         else {
741                 p_stream->m_byte_offset = p_size;
742         }
743
744         return OPJ_TRUE;
745 }
746
747 opj_bool opj_stream_seek (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr)
748 {
749         assert(p_size >= 0);
750         return p_stream->m_opj_seek(p_stream,p_size,p_event_mgr);
751 }
752
753 opj_bool opj_stream_has_seek (const opj_stream_private_t * p_stream)
754 {
755         return p_stream->m_seek_fn != opj_stream_default_seek;
756 }
757
758 OPJ_SIZE_T opj_stream_default_read (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data)
759 {
760         OPJ_ARG_NOT_USED(p_buffer);
761         OPJ_ARG_NOT_USED(p_nb_bytes);
762         OPJ_ARG_NOT_USED(p_user_data);
763         return (OPJ_SIZE_T) -1;
764 }
765
766 OPJ_SIZE_T opj_stream_default_write (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data)
767 {
768         OPJ_ARG_NOT_USED(p_buffer);
769         OPJ_ARG_NOT_USED(p_nb_bytes);
770         OPJ_ARG_NOT_USED(p_user_data);
771         return (OPJ_SIZE_T) -1;
772 }
773
774 OPJ_OFF_T opj_stream_default_skip (OPJ_OFF_T p_nb_bytes, void * p_user_data)
775 {
776         OPJ_ARG_NOT_USED(p_nb_bytes);
777         OPJ_ARG_NOT_USED(p_user_data);
778         return (OPJ_OFF_T) -1;
779 }
780
781 opj_bool opj_stream_default_seek (OPJ_OFF_T p_nb_bytes, void * p_user_data)
782 {
783         OPJ_ARG_NOT_USED(p_nb_bytes);
784         OPJ_ARG_NOT_USED(p_user_data);
785         return OPJ_FALSE;
786 }