Remove unistd.h include
[openjpeg.git] / applications / jpip / libopenjpip / msgqueue_manager.c
1 /*
2  * $Id: msgqueue_manager.c 53 2011-05-09 16:55:39Z 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  * Copyright (c) 2011,      Lucian Corlaciu, GSoC
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 <stdio.h>
33 #include <stdlib.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "msgqueue_manager.h"
39 #include "metadata_manager.h"
40 #include "index_manager.h"
41
42 #ifdef SERVER
43 #include "fcgi_stdio.h"
44 #define logstream FCGI_stdout
45 #else
46 #define FCGI_stdout stdout
47 #define FCGI_stderr stderr
48 #define logstream stderr
49 #endif //SERVER
50
51 msgqueue_param_t * gene_msgqueue( bool stateless, cachemodel_param_t *cachemodel)
52 {
53   msgqueue_param_t *msgqueue;
54
55   msgqueue = (msgqueue_param_t *)malloc( sizeof(msgqueue_param_t));
56
57   msgqueue->first = NULL;
58   msgqueue->last  = NULL;
59
60   msgqueue->stateless = stateless;
61   msgqueue->cachemodel = cachemodel;
62   
63   return msgqueue;
64 }
65
66 void delete_msgqueue( msgqueue_param_t **msgqueue)
67 {
68   message_param_t *ptr, *next;
69
70   if( !(*msgqueue))
71     return;
72   
73   ptr = (*msgqueue)->first;
74
75   while( ptr){
76     next = ptr->next;
77     free( ptr);
78     ptr = next;
79   }
80   if( (*msgqueue)->stateless && (*msgqueue)->cachemodel)
81     delete_cachemodel( &((*msgqueue)->cachemodel));
82
83   free(*msgqueue); 
84 }
85
86 void print_msgqueue( msgqueue_param_t *msgqueue)
87 {
88   message_param_t *ptr;
89   char *message_class[] = { "Precinct", "Ext-Prec", "TileHead", "non", "Tile", "Ext-Tile", "Main", "non", "Meta"};
90
91   if( !msgqueue)
92     return;
93
94   fprintf( logstream, "message queue:\n");
95   ptr = msgqueue->first;
96
97   while( ptr){
98     fprintf( logstream, "\t class_id: %lld %s\n", ptr->class_id, message_class[ptr->class_id]);
99     fprintf( logstream, "\t in_class_id: %lld\n", ptr->in_class_id );
100     fprintf( logstream, "\t csn: %lld\n", ptr->csn );
101     fprintf( logstream, "\t bin_offset: %#llx\n", ptr->bin_offset );
102     fprintf( logstream, "\t length: %#llx\n", ptr->length );
103     if( ptr->class_id%2)
104       fprintf( logstream, "\t aux: %lld\n", ptr->aux );
105     fprintf( logstream, "\t last_byte: %d\n", ptr->last_byte );
106     if( ptr->phld)
107       print_placeholder( ptr->phld);
108     else
109       fprintf( logstream, "\t res_offset: %#llx\n", ptr->res_offset );
110     fprintf( logstream, "\n");
111
112     ptr = ptr->next;
113   }
114 }
115
116 void enqueue_message( message_param_t *msg, msgqueue_param_t *msgqueue);
117
118 void enqueue_mainheader( msgqueue_param_t *msgqueue)
119 {
120   cachemodel_param_t *cachemodel;
121   target_param_t *target;
122   index_param_t *codeidx;
123   message_param_t *msg;
124
125   cachemodel = msgqueue->cachemodel;
126   target = cachemodel->target;
127   codeidx = target->codeidx;
128   
129   msg = (message_param_t *)malloc( sizeof(message_param_t));
130
131   msg->last_byte = true;
132   msg->in_class_id = 0;
133   msg->class_id = MAINHEADER_MSG;
134   msg->csn = target->csn;
135   msg->bin_offset = 0;
136   msg->length = codeidx->mhead_length;
137   msg->aux = 0; // non exist
138   msg->res_offset = codeidx->offset;
139   msg->phld = NULL;
140   msg->next = NULL;
141
142   enqueue_message( msg, msgqueue);
143
144   cachemodel->mhead_model = true;
145 }
146
147 void enqueue_tileheader( int tile_id, msgqueue_param_t *msgqueue)
148 {
149   cachemodel_param_t *cachemodel;
150   target_param_t *target;
151   index_param_t *codeidx;
152   message_param_t *msg;
153
154   cachemodel = msgqueue->cachemodel;
155   target = cachemodel->target;
156   codeidx = target->codeidx;
157
158   if( !cachemodel->th_model[ tile_id]){
159     msg = (message_param_t *)malloc( sizeof(message_param_t));
160     msg->last_byte = true;
161     msg->in_class_id = tile_id;
162     msg->class_id = TILE_HEADER_MSG;
163     msg->csn = target->csn;
164     msg->bin_offset = 0;
165     msg->length = codeidx->tileheader[tile_id]->tlen-2; // SOT marker segment is removed
166     msg->aux = 0; // non exist
167     msg->res_offset = codeidx->offset + get_elemOff( codeidx->tilepart, 0, tile_id) + 2; // skip SOT marker seg
168     msg->phld = NULL;
169     msg->next = NULL;
170     
171     enqueue_message( msg, msgqueue);
172     cachemodel->th_model[ tile_id] = true;
173   }
174 }
175
176 void enqueue_tile( int tile_id, int level, msgqueue_param_t *msgqueue)
177 {
178   cachemodel_param_t *cachemodel;
179   target_param_t *target;
180   bool *tp_model;
181   Byte8_t numOftparts; // num of tile parts par tile
182   Byte8_t numOftiles;
183   index_param_t *codeidx;
184   faixbox_param_t *tilepart;
185   message_param_t *msg;
186   Byte8_t binOffset, binLength, class_id;
187   int i;
188
189   cachemodel = msgqueue->cachemodel;
190   target = cachemodel->target;
191   codeidx  = target->codeidx;
192   tilepart = codeidx->tilepart;
193   
194   numOftparts = get_nmax( tilepart);
195   numOftiles  = get_m( tilepart);
196
197   class_id = (numOftparts==1) ? TILE_MSG : EXT_TILE_MSG;
198   
199   if( tile_id < 0 || numOftiles <= tile_id){
200     fprintf( FCGI_stderr, "Error, Invalid tile-id %d\n", tile_id);
201     return;
202   }
203   
204   tp_model = &cachemodel->tp_model[ tile_id*numOftparts];
205
206   binOffset=0;
207   for( i=0; i<numOftparts-level; i++){
208     binLength = get_elemLen( tilepart, i, tile_id);
209     
210     if( !tp_model[i]){
211       msg = (message_param_t *)malloc( sizeof(message_param_t));
212       
213       msg->last_byte = (i==numOftparts-1);
214       msg->in_class_id = tile_id;
215       msg->class_id = class_id;
216       msg->csn = target->csn;
217       msg->bin_offset = binOffset;
218       msg->length = binLength;
219       msg->aux = numOftparts-i;
220       msg->res_offset = codeidx->offset+get_elemOff( tilepart, i, tile_id)/*-1*/;
221       msg->phld = NULL;
222       msg->next = NULL;
223
224       enqueue_message( msg, msgqueue);
225
226       tp_model[i] = true;
227     }
228     binOffset += binLength;
229   }
230 }
231
232 void enqueue_precinct( int seq_id, int tile_id, int comp_id, int layers, msgqueue_param_t *msgqueue)
233 {
234   cachemodel_param_t *cachemodel;
235   index_param_t *codeidx;
236   faixbox_param_t *precpacket;
237   message_param_t *msg;
238   Byte8_t nmax, binOffset, binLength;
239   int layer_id, numOflayers;
240   
241   cachemodel = msgqueue->cachemodel;
242   codeidx = cachemodel->target->codeidx;
243   precpacket = codeidx->precpacket[ comp_id];
244   numOflayers = codeidx->COD.numOflayers;
245
246   nmax = get_nmax(precpacket);
247   if( layers < 0)
248     layers = numOflayers;
249     
250   binOffset = 0;
251   for( layer_id = 0; layer_id < layers; layer_id++){
252
253     binLength = get_elemLen( precpacket, seq_id*numOflayers+layer_id, tile_id);
254     
255     if( !cachemodel->pp_model[comp_id][ tile_id*nmax+seq_id*numOflayers+layer_id]){
256   
257       msg = (message_param_t *)malloc( sizeof(message_param_t));
258       msg->last_byte = (layer_id == (numOflayers-1));
259       msg->in_class_id = comp_precinct_id( tile_id, comp_id, seq_id, codeidx->SIZ.Csiz, codeidx->SIZ.XTnum * codeidx->SIZ.YTnum);
260       msg->class_id = PRECINCT_MSG;
261       msg->csn = cachemodel->target->csn;
262       msg->bin_offset = binOffset;
263       msg->length = binLength;
264       msg->aux = 0;
265       msg->res_offset = codeidx->offset+get_elemOff( precpacket, seq_id*numOflayers+layer_id, tile_id);
266       msg->phld = NULL;
267       msg->next = NULL;
268
269       enqueue_message( msg, msgqueue);
270       
271       cachemodel->pp_model[comp_id][ tile_id*nmax+seq_id*numOflayers+layer_id] = true;
272     }
273     binOffset += binLength;
274   }
275 }
276
277 Byte8_t comp_precinct_id( int t, int c, int s, int num_components, int num_tiles)
278 {
279   return t + (c + s * num_components ) * num_tiles;
280 }
281
282 void enqueue_box(  int meta_id, boxlist_param_t *boxlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset);
283 void enqueue_phld( int meta_id, placeholderlist_param_t *phldlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset);
284 void enqueue_boxcontents( int meta_id, boxcontents_param_t *boxcontents, msgqueue_param_t *msgqueue, Byte8_t *binOffset);
285
286 void enqueue_metadata( int meta_id, msgqueue_param_t *msgqueue)
287 {
288   metadatalist_param_t *metadatalist;
289   metadata_param_t *metadata;
290   Byte8_t binOffset;
291
292   metadatalist = msgqueue->cachemodel->target->codeidx->metadatalist;
293   metadata = search_metadata( meta_id, metadatalist);
294   
295   if( !metadata){
296     fprintf( FCGI_stderr, "Error: metadata-bin %d not found\n", meta_id);
297     return;
298   }
299   binOffset = 0;
300   
301   if( metadata->boxlist)
302     enqueue_box( meta_id, metadata->boxlist, msgqueue, &binOffset);
303
304   if( metadata->placeholderlist)
305     enqueue_phld( meta_id, metadata->placeholderlist, msgqueue, &binOffset);
306
307   if( metadata->boxcontents)
308     enqueue_boxcontents( meta_id, metadata->boxcontents, msgqueue, &binOffset);
309   
310   msgqueue->last->last_byte = true;
311 }
312
313 message_param_t * gene_metamsg( int meta_id, Byte8_t binoffset, Byte8_t length, Byte8_t res_offset, placeholder_param_t *phld, Byte8_t csn);
314
315 void enqueue_box( int meta_id, boxlist_param_t *boxlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
316 {
317   box_param_t *box;
318   message_param_t *msg;
319   
320   box = boxlist->first;
321   while( box){
322     msg = gene_metamsg( meta_id, *binOffset, box->length, box->offset, NULL, msgqueue->cachemodel->target->csn);
323     enqueue_message( msg, msgqueue);
324
325     *binOffset += box->length;
326     box = box->next;
327   }
328 }
329
330 void enqueue_phld( int meta_id, placeholderlist_param_t *phldlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
331 {
332   placeholder_param_t *phld;
333   message_param_t *msg;
334   
335   phld = phldlist->first;
336   while( phld){
337     msg = gene_metamsg( meta_id, *binOffset, phld->LBox, 0, phld, msgqueue->cachemodel->target->csn);
338     enqueue_message( msg, msgqueue);
339
340     *binOffset += phld->LBox;
341     phld = phld->next;
342   }
343 }
344
345 void enqueue_boxcontents( int meta_id, boxcontents_param_t *boxcontents, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
346 {
347   message_param_t *msg;
348
349   msg = gene_metamsg( meta_id, *binOffset, boxcontents->length, boxcontents->offset, NULL, msgqueue->cachemodel->target->csn);
350   enqueue_message( msg, msgqueue);
351   
352   *binOffset += boxcontents->length;
353 }
354
355 message_param_t * gene_metamsg( int meta_id, Byte8_t binOffset, Byte8_t length, Byte8_t res_offset, placeholder_param_t *phld, Byte8_t csn)
356 {
357   message_param_t *msg;
358
359   msg = (message_param_t *)malloc( sizeof(message_param_t));
360     
361   msg->last_byte = false;
362   msg->in_class_id = meta_id;
363   msg->class_id = METADATA_MSG;
364   msg->csn = csn;
365   msg->bin_offset = binOffset;
366   msg->length = length;
367   msg->aux = 0; // non exist
368   msg->res_offset = res_offset;
369   msg->phld = phld;
370   msg->next = NULL;
371
372   return msg;
373 }
374
375 void enqueue_message( message_param_t *msg, msgqueue_param_t *msgqueue)
376 {
377   if( msgqueue->first)
378     msgqueue->last->next = msg;
379   else
380     msgqueue->first = msg;
381   
382   msgqueue->last = msg;
383 }
384
385 void add_bin_id_vbas_stream( Byte_t bb, Byte_t c, Byte8_t in_class_id, int tmpfd);
386 void add_vbas_stream( Byte8_t code, int tmpfd);
387 void add_body_stream( message_param_t *msg, int fd, int tmpfd);
388 void add_placeholder_stream( placeholder_param_t *phld, int tmpfd);
389
390 void recons_stream_from_msgqueue( msgqueue_param_t *msgqueue, int tmpfd)
391 {
392   message_param_t *msg;
393   Byte8_t class_id, csn;
394   Byte_t bb, c;
395   
396   if( !(msgqueue))
397     return;
398
399   msg = msgqueue->first;
400   class_id = -1;
401   csn = -1;
402   while( msg){
403     if( msg->csn == csn){
404       if( msg->class_id == class_id)
405         bb = 1;
406       else{
407         bb = 2;
408         class_id = msg->class_id;
409       }
410     }
411     else{
412       bb = 3;
413       class_id = msg->class_id;
414       csn = msg->csn;
415     }
416
417     c = msg->last_byte ? 1 : 0;
418     
419     add_bin_id_vbas_stream( bb, c, msg->in_class_id, tmpfd);
420     
421     if( bb >= 2)
422       add_vbas_stream( class_id, tmpfd);
423     if (bb == 3)
424       add_vbas_stream( csn, tmpfd);
425     
426     add_vbas_stream( msg->bin_offset, tmpfd);
427     add_vbas_stream (msg->length, tmpfd);
428     
429     if( msg->class_id%2) // Aux is present only if the id is odd
430       add_vbas_stream( msg->aux, tmpfd);
431
432     if( msg->phld)
433       add_placeholder_stream( msg->phld, tmpfd);
434     else
435       add_body_stream( msg, msgqueue->cachemodel->target->fd, tmpfd);
436
437     msg = msg->next;
438   }
439 }
440
441 void add_vbas_with_bytelen_stream( Byte8_t code, int bytelength, int tmpfd);
442 void print_binarycode( Byte8_t n, int segmentlen);
443
444 void add_bin_id_vbas_stream( Byte_t bb, Byte_t c, Byte8_t in_class_id, int tmpfd)
445 {
446   int bytelength;
447   Byte8_t tmp;
448
449   // A.2.3 In-class identifiers 
450   // 7k-3bits, where k is the number of bytes in the VBAS
451   bytelength = 1;
452   tmp = in_class_id >> 4;
453   while( tmp){
454     bytelength ++;
455     tmp >>= 7;
456   }
457
458   in_class_id |= (((bb & 3) << 5) | (c & 1) << 4) << ((bytelength-1)*7);
459   
460   add_vbas_with_bytelen_stream( in_class_id, bytelength, tmpfd);
461 }
462
463 void add_vbas_stream( Byte8_t code, int tmpfd)
464 {
465   int bytelength;
466   Byte8_t tmp;
467
468   bytelength = 1;
469   tmp = code;
470   while( tmp >>= 7)
471     bytelength ++;
472
473   add_vbas_with_bytelen_stream( code, bytelength, tmpfd);
474 }
475
476 void add_vbas_with_bytelen_stream( Byte8_t code, int bytelength, int tmpfd)
477 {
478   int n;
479   Byte8_t seg;
480   
481   n = bytelength - 1;
482   while( n >= 0) {
483     seg = ( code >> (n*7)) & 0x7f;
484     if( n)
485       seg |= 0x80;
486     if( write( tmpfd, ( Byte4_t *)&seg, 1) != 1){
487       fprintf( FCGI_stderr, "Error: failed to write vbas\n");
488       return;
489     }
490     n--;
491   }
492 }
493
494 void add_body_stream( message_param_t *msg, int fd, int tmpfd)
495 {
496   Byte_t *data;
497
498   if( !(data = fetch_bytes( fd, msg->res_offset, msg->length))){
499     fprintf( FCGI_stderr, "Error: fetch_bytes in add_body_stream()\n");
500     return;
501   }
502
503   if( write( tmpfd, data, msg->length) < 1){
504     free( data);
505     fprintf( FCGI_stderr, "Error: fwrite in add_body_stream()\n");
506     return;
507   }
508   free(data);
509 }
510
511 void add_bigendian_bytestream( Byte8_t code, int bytelength, int tmpfd);
512
513 void add_placeholder_stream( placeholder_param_t *phld, int tmpfd)
514 {
515   add_bigendian_bytestream( phld->LBox, 4, tmpfd);
516   if( write( tmpfd, phld->TBox, 4) < 1){
517     fprintf( FCGI_stderr, "Error: fwrite in add_placeholder_stream()\n");
518     return;
519   }
520   add_bigendian_bytestream( phld->Flags, 4, tmpfd);
521   add_bigendian_bytestream( phld->OrigID, 8, tmpfd);
522
523   if( write( tmpfd, phld->OrigBH, phld->OrigBHlen) < 1){
524     fprintf( FCGI_stderr, "Error: fwrite in add_placeholder_stream()\n");
525     return;
526   }
527 }
528
529 void add_bigendian_bytestream( Byte8_t code, int bytelength, int tmpfd)
530 {
531   int n;
532   Byte8_t seg;
533   
534   n = bytelength - 1;
535   while( n >= 0) {
536     seg = ( code >> (n*8)) & 0xff;
537     if( write( tmpfd, ( Byte4_t *)&seg, 1) != 1){
538       fprintf( FCGI_stderr, "ERROR: failed to write bigendian_bytestream\n");
539       return;
540     }
541     n--;
542   }
543 }
544
545 void print_binarycode( Byte8_t n, int segmentlen)
546 {
547   char buf[256];
548   int i=0, j, k;
549
550   do{
551     buf[i++] = n%2 ? '1' : '0';
552   }while((n=n/2));
553
554   for( j=segmentlen-1; j>=i; j--)
555     putchar('0');
556   
557   for( j=i-1, k=0; j>=0; j--, k++){
558     putchar( buf[j]);
559     if( !((k+1)%segmentlen))
560       printf(" ");
561   }
562   printf("\n");
563 }
564
565 Byte_t * parse_bin_id_vbas( Byte_t *streamptr, Byte_t *bb, Byte_t *c, Byte8_t *in_class_id);
566 Byte_t * parse_vbas( Byte_t *streamptr, Byte8_t *elem);
567
568 void parse_JPIPstream( Byte_t *JPIPstream, Byte8_t streamlen, Byte8_t offset, msgqueue_param_t *msgqueue)
569 {
570   Byte_t *ptr;  // stream pointer
571   message_param_t *msg;
572   Byte_t bb, c;
573   Byte8_t class_id, csn;
574
575   class_id = -1; // dummy
576   csn = -1;
577   ptr = JPIPstream;
578   while( ptr-JPIPstream < streamlen){
579     msg = (message_param_t *)malloc( sizeof(message_param_t));
580     
581     ptr = parse_bin_id_vbas( ptr, &bb, &c, &msg->in_class_id);
582     
583     msg->last_byte   = c == 1 ? true : false;
584     
585     if( bb >= 2)
586       ptr = parse_vbas( ptr, &class_id);
587
588     msg->class_id = class_id;
589     
590     if (bb == 3)
591       ptr = parse_vbas( ptr, &csn);
592     msg->csn = csn;
593     
594     ptr = parse_vbas( ptr, &msg->bin_offset);
595     ptr = parse_vbas( ptr, &msg->length);
596     
597     if( msg->class_id%2) // Aux is present only if the id is odd
598       ptr = parse_vbas( ptr, &msg->aux);
599     else
600       msg->aux = 0;
601     
602     msg->res_offset = ptr-JPIPstream+offset;   
603     msg->phld = NULL;
604     msg->next = NULL;
605
606     if(msgqueue->first)
607       msgqueue->last->next = msg;
608     else
609       msgqueue->first = msg;
610     msgqueue->last = msg;
611     
612     ptr += msg->length;
613   }
614 }
615
616 void parse_metadata( metadata_param_t *metadata, message_param_t *msg, Byte_t *stream);
617
618 void parse_metamsg( msgqueue_param_t *msgqueue, Byte_t *stream, Byte8_t streamlen, metadatalist_param_t *metadatalist)
619 {
620   message_param_t *msg;
621
622   if( metadatalist == NULL)
623     return;
624   
625   msg = msgqueue->first;
626   while( msg){
627     if( msg->class_id == METADATA_MSG){
628       metadata_param_t *metadata = gene_metadata( msg->in_class_id, NULL, NULL, NULL);
629       insert_metadata_into_list( metadata, metadatalist);
630       parse_metadata( metadata, msg, stream+msg->res_offset);
631     }
632     msg = msg->next;
633   }
634 }
635
636 placeholder_param_t * parse_phld( Byte_t *datastream, Byte8_t metalength);
637
638 void parse_metadata( metadata_param_t *metadata, message_param_t *msg, Byte_t *datastream)
639 {
640   char *boxtype = (char *)(datastream+4);
641
642   msg->phld = NULL;
643
644   if( strncmp( boxtype, "phld", 4) == 0){
645     if( !metadata->placeholderlist)
646         metadata->placeholderlist = gene_placeholderlist();
647     
648     placeholder_param_t *phld = parse_phld( datastream, msg->length);
649     msg->phld = phld;
650     insert_placeholder_into_list( phld, metadata->placeholderlist);
651   }
652   else if( isalpha(boxtype[0]) && isalpha(boxtype[1]) &&
653            (isalnum(boxtype[2])||isblank(boxtype[2])) &&
654            (isalpha(boxtype[3])||isblank(boxtype[3]))){
655     if( !metadata->boxlist)
656       metadata->boxlist = gene_boxlist();
657     
658     box_param_t *box = gene_boxbyOffinStream( datastream, msg->res_offset);
659     insert_box_into_list( box, metadata->boxlist);
660   }
661   else
662     metadata->boxcontents = gene_boxcontents( msg->res_offset, msg->length);
663 }
664
665 placeholder_param_t * parse_phld( Byte_t *datastream, Byte8_t metalength)
666 {
667   placeholder_param_t *phld;
668
669   phld = (placeholder_param_t *)malloc( sizeof(placeholder_param_t));
670   
671   phld->LBox = big4( datastream);
672   strcpy( phld->TBox, "phld");
673   phld->Flags = big4( datastream+8);
674   phld->OrigID = big8( datastream+12);
675   phld->OrigBHlen = metalength - 20;
676   phld->OrigBH = (Byte_t *)malloc(phld->OrigBHlen);
677   memcpy( phld->OrigBH, datastream+20, phld->OrigBHlen);
678   phld->next = NULL;
679
680   return phld;
681 }
682
683 Byte_t * parse_bin_id_vbas( Byte_t *streamptr, Byte_t *bb, Byte_t *c, Byte8_t *in_class_id)
684 {
685   Byte_t code;
686   Byte_t *ptr;
687
688   ptr = streamptr;
689   code = *(ptr++);
690
691   *bb = (code >> 5) & 3;
692   *c  = (code >> 4) & 1;
693   
694   *in_class_id = code & 15;
695
696   while(code >> 7){
697     code = *(ptr++);
698     *in_class_id = (*in_class_id << 7) | (code & 0x7f);
699   }
700   return ptr;
701 }
702
703 Byte_t * parse_vbas( Byte_t *streamptr, Byte8_t *elem)
704 {
705   Byte_t code;
706   Byte_t *ptr;
707   
708   *elem = 0;
709   ptr = streamptr;
710   do{
711     code = *(ptr++);
712     *elem = (*elem << 7) | (code & 0x7f);
713   }while(code >> 7);
714   
715   return ptr;
716 }
717
718 void delete_message_in_msgqueue( message_param_t **msg, msgqueue_param_t *msgqueue)
719 {
720   message_param_t *ptr;
721
722   if( !(*msg))
723     return;
724
725   if( *msg == msgqueue->first)
726     msgqueue->first = (*msg)->next;
727   else{
728     ptr = msgqueue->first;
729     while( ptr->next != *msg){
730       ptr=ptr->next;
731     }
732     
733     ptr->next = (*msg)->next;
734     
735     if( *msg == msgqueue->last)
736       msgqueue->last = ptr;
737   }
738   free( *msg);
739 }