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