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