[1.5][JPIP] added get_filesize()
[openjpeg.git] / applications / jpip / libopenjpip / box_manager.c
1 /*
2  * $Id: box_manager.c 44 2011-02-15 12:32:29Z kaori $
3  *
4  * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
5  * Copyright (c) 2002-2011, Professor Benoit Macq
6  * Copyright (c) 2010-2011, Kaori Hagihara
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <ctype.h>
35 #include "box_manager.h"
36
37 #ifdef SERVER
38 #include "fcgi_stdio.h"
39 #define logstream FCGI_stdout
40 #else
41 #define FCGI_stdout stdout
42 #define FCGI_stderr stderr
43 #define logstream stderr
44 #endif //SERVER
45
46 boxlist_param_t * gene_boxlist()
47 {
48   boxlist_param_t *boxlist;
49
50   boxlist = (boxlist_param_t *)malloc( sizeof(boxlist_param_t));
51   
52   boxlist->first = NULL;
53   boxlist->last  = NULL;
54
55   return boxlist;
56 }
57
58 boxlist_param_t * get_boxstructure( int fd, Byte8_t offset, Byte8_t length)
59 {
60   boxlist_param_t *boxlist;
61   box_param_t *box;
62   int pos;
63   
64   boxlist = NULL;
65   pos = offset;
66   do{
67     if(!(box = gene_boxbyOffset( fd, pos)))
68       break;
69     
70     pos += box->length;
71     
72     if( !boxlist)
73       boxlist = gene_boxlist();
74     insert_box_into_list( box, boxlist);
75   }while( pos < offset+length);
76
77   return boxlist;
78 }
79
80 box_param_t * gene_boxbyOffset( int fd, Byte8_t offset)
81 {
82   Byte_t *data;
83   Byte8_t boxlen, headlen;
84   char *boxtype;
85   box_param_t *box;
86
87   // read LBox and TBox
88   if(!(data = fetch_bytes( fd, offset, 8))){
89     fprintf( FCGI_stderr, "Error: error in gene_boxbyOffset( %d, %lld)\n", fd, offset);
90     return NULL;
91   }
92   
93   headlen = 8;
94   boxlen = (Byte8_t)big4(data);
95   boxtype = (char *)(data+4);  
96
97   // box type constraint
98   if( !isalpha(boxtype[0]) || !isalpha(boxtype[1]) ||
99       (!isalnum(boxtype[2])&&!isblank(boxtype[2])) ||
100       (!isalpha(boxtype[3])&&!isblank(boxtype[3]))){
101     free( data);
102     return NULL;
103   }
104   
105   if( boxlen == 1){
106     Byte_t *data2;
107     headlen = 16;
108     // read XLBox
109     if((data2 = fetch_bytes( fd, offset+8, 8))){
110       boxlen = big8(data2);
111       free(data2);
112     }
113     else{
114       fprintf( FCGI_stderr, "Error: error in gene_boxbyOffset( %d, %lld)\n", fd, offset);
115       free( data);
116       return NULL;
117     }
118   }
119   box = (box_param_t *)malloc( sizeof( box_param_t));
120   box->fd = fd;
121   box->offset = offset;
122   box->headlen = headlen;
123   box->length = boxlen;
124   strncpy( box->type, boxtype, 4);
125   box->next = NULL;
126   free( data);
127   return box;
128 }
129
130 box_param_t * gene_boxbyOffinStream( Byte_t *stream, Byte8_t offset)
131 {
132   Byte8_t boxlen, headlen;
133   char *boxtype;
134   box_param_t *box;
135
136   // read LBox and TBox
137   headlen = 8;
138   boxlen = (Byte8_t)big4( stream);
139   boxtype = (char *)( stream+4);  
140
141   // box type constraint
142   if( !isalpha(boxtype[0]) || !isalpha(boxtype[1]) ||
143       (!isalnum(boxtype[2])&&!isblank(boxtype[2])) ||
144       (!isalpha(boxtype[3])&&!isblank(boxtype[3]))){
145     return NULL;
146   }
147   
148   if( boxlen == 1){
149     headlen = 16;
150     boxlen = big8( stream+8); // read XLBox
151   }
152   box = (box_param_t *)malloc( sizeof( box_param_t));
153   box->fd = -1;
154   box->offset = offset;
155   box->headlen = headlen;
156   box->length = boxlen;
157   strncpy( box->type, boxtype, 4);
158   box->next = NULL;
159
160   return box;
161 }
162
163
164 box_param_t * gene_boxbyType( int fd, Byte8_t offset, Byte8_t length, char TBox[])
165 {
166   Byte8_t pos;
167   Byte_t *data;
168   Byte8_t boxlen, headlen;
169   char *boxtype;
170   box_param_t *foundbox;
171
172   
173   if( length==0){ // set the max length
174     if( (length = get_filesize( fd) - offset) <= 0)
175       return NULL;
176   }
177
178   pos = offset;
179   while( pos < offset+length-7){ // LBox+TBox-1=7
180     
181     // read LBox and TBox
182     if((data = fetch_bytes( fd, pos, 8))){
183       headlen = 8;
184       boxlen = (Byte8_t)big4(data);
185       boxtype = (char *)(data+4);
186
187       if( boxlen == 1){
188         Byte_t *data2;
189         headlen = 16;
190         // read XLBox
191         if((data2 = fetch_bytes( fd, pos+8, 8))){
192           boxlen = big8(data2);
193           free(data2);
194         }
195         else{
196           fprintf( FCGI_stderr, "Error: error in gene_boxbyType( %d, %lld, %lld, %s)\n", fd, offset, length, TBox);
197           return NULL;
198         }
199       }
200       if( strncmp ( boxtype, TBox, 4) == 0){
201         foundbox = (box_param_t *)malloc( sizeof( box_param_t));
202         foundbox->fd = fd;
203         foundbox->offset = pos;
204         foundbox->headlen = headlen;
205         foundbox->length = boxlen;
206         strncpy( foundbox->type, TBox, 4);
207         foundbox->next = NULL;
208         free( data);
209         return foundbox;
210       }
211       free( data);
212     }
213     else{
214       fprintf( FCGI_stderr, "Error: error in gene_boxbyType( %d, %lld, %lld, %s)\n", fd, offset, length, TBox);
215       return NULL;
216     }
217     pos+= boxlen;
218   }
219   fprintf( FCGI_stderr, "Error: Box %s not found\n", TBox);
220
221   return NULL;
222 }
223
224 box_param_t * gene_boxbyTypeinStream( Byte_t *stream, Byte8_t offset, Byte8_t length, char TBox[])
225 {
226   Byte8_t pos;
227   Byte_t *data;
228   Byte8_t boxlen, headlen;
229   char *boxtype;
230   box_param_t *foundbox;
231
232   
233   if( length<=0){ // set the max length
234     fprintf( FCGI_stderr, "func gene_boxbyTypeinStream(), max length must be more than 0\n");
235     return NULL;
236   }
237   
238   pos = offset;
239   while( pos < offset+length-7){ // LBox+TBox-1=7
240     
241     // read LBox and TBox
242     data = stream + pos;
243     headlen = 8;
244     boxlen = (Byte8_t)big4(data);
245     boxtype = (char *)(data+4);
246    
247     if( boxlen == 1){
248       // read XLBox
249       headlen = 16;
250       boxlen = big8( data+8);
251     }
252
253     if( strncmp ( boxtype, TBox, 4) == 0){
254       foundbox = (box_param_t *)malloc( sizeof( box_param_t));
255       foundbox->fd = -1;
256       foundbox->offset = pos;
257       foundbox->headlen = headlen;
258       foundbox->length = boxlen;
259       strncpy( foundbox->type, TBox, 4);
260       foundbox->next = NULL;
261       return foundbox;
262     }
263     pos+= boxlen;
264   }
265   fprintf( FCGI_stderr, "Error: Box %s not found\n", TBox);
266   
267   return NULL;
268 }
269
270 box_param_t * gene_childboxbyOffset( box_param_t *superbox, Byte8_t offset)
271 {
272   return gene_boxbyOffset( superbox->fd, get_DBoxoff( superbox)+offset);
273 }
274
275 box_param_t * gene_childboxbyType( box_param_t *superbox, Byte8_t offset, char TBox[])
276 {
277   return gene_boxbyType( superbox->fd, get_DBoxoff( superbox)+offset, get_DBoxlen( superbox)-offset, TBox);
278 }
279
280 Byte8_t get_DBoxoff( box_param_t *box)
281 {
282   return box->offset+box->headlen;
283 }
284
285 Byte8_t get_DBoxlen( box_param_t *box)
286 {
287   return box->length-box->headlen;
288 }
289
290 Byte_t * fetch_headbytes( box_param_t *box)
291 {
292   return fetch_bytes( box->fd, box->offset, box->headlen);
293 }
294
295 Byte_t * fetch_DBoxbytes( box_param_t *box, long offset, int size)
296 {
297   return fetch_bytes( box->fd, get_DBoxoff( box)+offset, size);
298 }
299
300 Byte_t fetch_DBox1byte( box_param_t *box, long offset)
301 {
302   return fetch_1byte( box->fd, get_DBoxoff( box)+offset);
303 }
304
305 Byte2_t fetch_DBox2bytebigendian( box_param_t *box, long offset)
306 {
307   return fetch_2bytebigendian( box->fd, get_DBoxoff( box)+offset);
308 }
309
310 Byte4_t fetch_DBox4bytebigendian( box_param_t *box, long offset)
311 {
312   return fetch_4bytebigendian( box->fd, get_DBoxoff( box)+offset);
313 }
314
315 Byte8_t fetch_DBox8bytebigendian( box_param_t *box, long offset)
316 {
317   return fetch_8bytebigendian( box->fd, get_DBoxoff( box)+offset);
318 }
319
320 box_param_t * search_box( char type[], boxlist_param_t *boxlist)
321 {
322   box_param_t *foundbox;
323
324   foundbox = boxlist->first;
325   
326   while( foundbox != NULL){
327     
328     if( strncmp( type, foundbox->type, 4) == 0)
329       return foundbox;
330       
331     foundbox = foundbox->next;
332   }
333   fprintf( FCGI_stderr, "Error: Box %s not found\n", type);
334
335   return NULL;
336 }
337
338 void print_box( box_param_t *box)
339 {
340   fprintf( logstream, "box info:\n"
341            "\t type: %.4s\n"
342            "\t offset: %lld %#llx\n" 
343            "\t header length: %d\n"
344            "\t length: %lld %#llx\n", box->type, box->offset, box->offset, box->headlen, box->length, box->length);
345 }
346
347 void print_allbox( boxlist_param_t *boxlist)
348 {
349   box_param_t *ptr;
350
351   if( !boxlist)
352     return;
353
354   ptr = boxlist->first;
355   if( !ptr)
356     fprintf( logstream, "no box\n");
357
358   fprintf( logstream, "all box info: \n");
359   while( ptr != NULL){
360     print_box( ptr);
361     ptr=ptr->next;
362   }
363 }
364
365 void delete_box_in_list( box_param_t **box, boxlist_param_t *boxlist)
366 {
367   box_param_t *ptr;
368
369   if( *box == boxlist->first)
370     boxlist->first = (*box)->next;
371   else{
372     ptr = boxlist->first;
373     while( ptr->next != *box){
374       ptr=ptr->next;
375     }
376     ptr->next = (*box)->next;
377     
378     if( *box == boxlist->last)
379       boxlist->last = ptr;
380   }
381   free( *box);
382 }
383
384 void delete_box_in_list_by_type( char type[], boxlist_param_t *boxlist)
385 {
386   box_param_t *box;
387
388   box = search_box( type, boxlist);
389   delete_box_in_list( &box, boxlist);
390 }
391
392 void delete_boxlist( boxlist_param_t **boxlist)
393 {
394   box_param_t *boxPtr, *boxNext;
395
396   if(!(*boxlist))
397     return;
398   
399   boxPtr = (*boxlist)->first;
400   while( boxPtr != NULL){
401     boxNext=boxPtr->next;
402     free( boxPtr);
403     boxPtr=boxNext;
404   }
405   free( *boxlist);
406 }
407
408 void insert_box_into_list( box_param_t *box, boxlist_param_t *boxlist)
409 {
410   if( boxlist->first)
411     boxlist->last->next = box;
412   else
413     boxlist->first = box;
414   boxlist->last = box;
415 }