NCBI C Toolkit Cross Reference

C/asnlib/asnenbin.c


  1 /* asnenbin.c
  2 * ===========================================================================
  3 *
  4 *                            PUBLIC DOMAIN NOTICE                          
  5 *               National Center for Biotechnology Information
  6 *                                                                          
  7 *  This software/database is a "United States Government Work" under the   
  8 *  terms of the United States Copyright Act.  It was written as part of    
  9 *  the author's official duties as a United States Government employee and 
 10 *  thus cannot be copyrighted.  This software/database is freely available 
 11 *  to the public for use. The National Library of Medicine and the U.S.    
 12 *  Government have not placed any restriction on its use or reproduction.  
 13 *                                                                          
 14 *  Although all reasonable efforts have been taken to ensure the accuracy  
 15 *  and reliability of the software and data, the NLM and the U.S.          
 16 *  Government do not and cannot warrant the performance or results that    
 17 *  may be obtained by using this software or data. The NLM and the U.S.    
 18 *  Government disclaim all warranties, express or implied, including       
 19 *  warranties of performance, merchantability or fitness for any particular
 20 *  purpose.                                                                
 21 *                                                                          
 22 *  Please cite the author in any work or product based on this material.   
 23 *
 24 * ===========================================================================
 25 *
 26 * File Name: asnenbin.c
 27 *
 28 * Author:  James Ostell
 29 *
 30 * Version Creation Date: 3/4/91
 31 *
 32 * $Revision: 6.6 $
 33 *
 34 * File Description:
 35 *   Special binary (BER) encoder for ASN.1
 36 *
 37 * Modifications:  
 38 * --------------------------------------------------------------------------
 39 * Date     Name        Description of modification
 40 * -------  ----------  -----------------------------------------------------
 41 * 3/4/91   Kans        Stricter typecasting for GNU C and C++
 42 * 04-20-93 Schuler     LIBCALL calling convention
 43 *
 44 * $Log: asnenbin.c,v $
 45 * Revision 6.6  2003/11/07 20:57:02  beloslyu
 46 * fix the c++ style comments to a C ones
 47 *
 48 * Revision 6.5  2003/08/01 16:55:24  gouriano
 49 * workaround MSVC++.NET optimization bug
 50 *
 51 * Revision 6.4  2000/12/12 15:56:11  ostell
 52 * added support BigInt
 53 *
 54 * Revision 6.3  1998/06/12 19:27:49  kans
 55 * fixed unix compiler warnings
 56 *
 57 * Revision 6.2  1998/05/02 18:54:25  kans
 58 * for Mac, use %LG instead of %lg, which is not legal C, and not supported by CodeWarrior
 59 *
 60 * Revision 6.1  1998/05/01 23:35:18  kans
 61 * use %lf on Mac, %lg elsewhere, sprintf bug reported
 62 *
 63 * Revision 6.0  1997/08/25 18:09:50  madden
 64 * Revision changed to 6.0
 65 *
 66 * Revision 5.1  1996/12/03 21:43:48  vakatov
 67 * Adopted for 32-bit MS-Windows DLLs
 68 *
 69  * Revision 5.0  1996/05/28  14:00:29  ostell
 70  * Set to revision 5.0
 71  *
 72  * Revision 4.1  1996/02/18  16:45:36  ostell
 73  * changed fix_non_print behavior and added option 3
 74  *
 75  * Revision 4.0  1995/07/26  13:47:38  ostell
 76  * force revision to 4.0
 77  *
 78  * Revision 2.9  1995/05/15  18:38:28  ostell
 79  * added Log line
 80  *
 81 *
 82 * ==========================================================================
 83 */
 84 
 85 #include "asnbuild.h"
 86 
 87 /*****************************************************************************
 88 *
 89 *   Boolean AsnBinWrite(aip, atp, valueptr)
 90 *
 91 *****************************************************************************/
 92 NLM_EXTERN Boolean LIBCALL  AsnBinWrite (AsnIoPtr aip, AsnTypePtr atp, DataValPtr dvp)
 93 {
 94         Int2 isa;
 95         AsnTypePtr atp2;
 96         Boolean terminalvalue;
 97         int next_type;
 98 
 99         terminalvalue = TRUE;   /* most are terminal values */
100 
101         if (! AsnTypeValidateOut(aip, atp, dvp))
102                 return FALSE;
103 
104         atp2 = AsnFindBaseType(atp);
105         isa = atp2->type->isa;
106         if (ISA_STRINGTYPE(isa))
107                 isa = GENERALSTRING_TYPE;
108         
109         if (((isa == SEQ_TYPE) || (isa == SET_TYPE) ||
110                  (isa == SEQOF_TYPE) || (isa == SETOF_TYPE))
111                  && (dvp->intvalue == END_STRUCT))
112         {
113                 AsnEnBinCloseStruct(aip, atp);
114                 return TRUE;
115         }
116 
117         AsnEnBinTags(atp, aip);     /* put in the tags */
118 
119         if (isa == CHOICE_TYPE)     /* show nothing */
120         {
121                 AsnTypeSetIndent(TRUE, aip, atp);
122                 return TRUE;
123         }
124 
125         switch (isa)
126         {
127                 case SEQ_TYPE:
128                 case SET_TYPE:
129                 case SEQOF_TYPE:
130                 case SETOF_TYPE:
131                         if (dvp->intvalue == START_STRUCT)   /* open brace */
132                                 AsnEnBinOpenStruct(aip, atp);
133                         else
134                         {
135                                 AsnIoErrorMsg(aip, 18 );
136                                 return FALSE;
137                         }
138                         terminalvalue = FALSE;
139                         break;
140                 case BOOLEAN_TYPE:
141                         AsnEnBinBoolean(dvp->boolvalue, aip, atp);
142                         break;
143                 case INTEGER_TYPE:
144                 case ENUM_TYPE:
145                         AsnEnBinInteger(dvp->intvalue, aip, atp);
146                         break;
147                 case BIGINT_TYPE:
148                         AsnEnBinBigInt(dvp->bigintvalue, aip, atp);
149                         break;
150                 case REAL_TYPE:
151                         AsnEnBinReal(dvp->realvalue, aip, atp);
152                         break;
153                 case GENERALSTRING_TYPE:
154                         if (! AsnEnBinString((CharPtr) dvp->ptrvalue, aip, atp))
155                                 return FALSE;
156                         break;
157                 case NULL_TYPE:
158                         AsnEnBinNull(aip, atp);
159                         break;
160                 case OCTETS_TYPE:
161                 case STRSTORE_TYPE:
162                         AsnEnBinOctets((ByteStorePtr) dvp->ptrvalue, aip, atp);
163                         break;
164                 default:
165                         AsnIoErrorMsg(aip, 19, AsnErrGetTypeName(atp->name));
166                         return FALSE;
167         }
168 
169         if (terminalvalue)          /* pop out of choice nests */
170         {
171                 if (atp->tagclass != TAG_NONE)
172                         AsnEnBinEndIndef(aip);    /* put indefinate encoding */
173                 next_type = aip->type_indent - 1;   /* end any choices */
174                 while ((next_type >= 0) &&
175                         (AsnFindBaseIsa(aip->typestack[next_type].type) == CHOICE_TYPE))
176                 {
177                         if (aip->typestack[next_type].type->tagclass != TAG_NONE)
178                                 AsnEnBinEndIndef(aip);
179                         next_type--;
180                 }
181                 if (AsnFindBaseIsa(aip->typestack[aip->type_indent - 1].type) == CHOICE_TYPE)
182                         AsnTypeSetIndent(FALSE, aip, atp);
183         }
184         return TRUE;
185 }
186 
187 /*****************************************************************************
188 *
189 *   void AsnEnBinTags(atp, aip)
190 *       encode tags for atp
191 *
192 *****************************************************************************/
193 NLM_EXTERN void AsnEnBinTags (AsnTypePtr atp, AsnIoPtr aip)
194 {
195         int isa, len;
196         Int4 tagnumber;
197         Byte octets[6], bit87, bit6, bit5_1;
198 
199         if (atp->tagclass == TAG_NONE)     /* encode tag, if any */
200                 return;
201 
202         isa = AsnFindBaseIsa(atp);
203         if ((isa == SEQ_TYPE) || (isa == SEQOF_TYPE) ||
204                 (isa == SET_TYPE) || (isa == SETOF_TYPE) ||
205                 (atp->tagclass == TAG_CONTEXT))
206                 bit6 = 32;       /* constructed bit set */
207         else
208                 bit6 = 0;
209 
210         bit87 = atp->tagclass;    /* map directly */
211 
212         tagnumber = atp->tagnumber;
213 
214         if (tagnumber <= 30)        /* only need one octet */
215         {
216                 bit5_1 = (Byte)(tagnumber) & (Byte)0x0ff;
217                 octets[0] = bit87 + bit6 + bit5_1;
218                 AsnEnBinBytes(octets, (Uint4)1, aip);
219         }
220         else
221         {
222                 bit5_1 = 31;            /* extended tag */
223 
224                 octets[0] = bit87 + bit6 + bit5_1;
225 
226                 if (tagnumber <= 0x07f)
227                 {
228                         octets[1] = (Byte)tagnumber;
229                         len = 2;
230                 }
231                 else if (tagnumber <= 0x03fff)
232                 {
233                         octets[1] = (Byte)(128 + ((tagnumber >> 7) & 0x07f));
234                         octets[2] = (Byte)(tagnumber & 0x07f);
235                         len = 3;
236                 }
237                 else if (tagnumber <= 0x01fffff)
238                 {
239                         octets[1] = (Byte)(128 + ((tagnumber >> 14) & 0x07f));
240                         octets[2] = (Byte)(128 + ((tagnumber >> 7) & 0x07f));
241                         octets[3] = (Byte)(tagnumber & 0x07f);
242                         len = 4;
243                 }
244                 else if (tagnumber <= 0x0fffffff)
245                 {
246                         octets[1] = (Byte)(128 + ((tagnumber >> 21) & 0x07f));
247                         octets[2] = (Byte)(128 + ((tagnumber >> 14) & 0x07f));
248                         octets[3] = (Byte)(128 + ((tagnumber >> 7) & 0x07f));
249                         octets[4] = (Byte)(tagnumber & 0x07f);
250                         len = 5;
251                 }
252                 else
253                 {
254                         octets[1] = (Byte)(128 + ((tagnumber >> 28) & 0x07f));
255                         octets[2] = (Byte)(128 + ((tagnumber >> 21) & 0x07f));
256                         octets[3] = (Byte)(128 + ((tagnumber >> 14) & 0x07f));
257                         octets[4] = (Byte)(128 + ((tagnumber >> 7) & 0x07f));
258                         octets[5] = (Byte)(tagnumber & 0x07f);
259                         len = 6;
260                 }
261 
262                 AsnEnBinBytes(octets, (Uint4)len, aip);
263         }
264 
265         if (atp->tagclass == TAG_CONTEXT)    /* indefinate length on user tags */
266                 AsnEnBinStartIndef(aip);
267 
268         return;
269 }
270 
271 /*****************************************************************************
272 *
273 *   void AsnEnBinNull(aip, atp)
274 *
275 *****************************************************************************/
276 NLM_EXTERN void AsnEnBinNull (AsnIoPtr aip, AsnTypePtr atp)
277 {
278         AsnTypePtr atp2;
279 
280         atp2 = AsnFindBaseType(atp);
281         atp2 = atp2->type;
282         AsnEnBinTags(atp2, aip);
283 
284         AsnEnBinLen((Uint4)0, aip);
285         return;
286 }
287 
288 
289 /*****************************************************************************
290 *
291 *   void AsnEnBinReal(realvalue, aip)
292 *
293 *****************************************************************************/
294 NLM_EXTERN void AsnEnBinReal (FloatHi realvalue, AsnIoPtr aip, AsnTypePtr atp)
295 {
296         AsnTypePtr atp2;
297         Byte buf[32];
298         Uint4 len;
299 
300         atp2 = AsnFindBaseType(atp);
301         atp2 = atp2->type;
302         AsnEnBinTags(atp2, aip);
303         buf[0] = 0;    /* use decimal encoding */
304 #ifdef OS_MAC
305         /* sprintf((char *)(buf + 1), "%lf", realvalue); */
306         sprintf((char *)(buf + 1), "%LG", realvalue);
307 #else
308         sprintf((char *)(buf + 1), "%lg", realvalue);
309 #endif
310         len = StringLen((char *)(buf+1)) + 1;
311         AsnEnBinLen(len, aip);
312         AsnEnBinBytes(buf, len, aip);
313 
314         return;
315 }
316 
317 /*****************************************************************************
318 *
319 *   void AsnEnBinInteger(theInt, aip)
320 *
321 *****************************************************************************/
322 NLM_EXTERN void AsnEnBinInteger (Int4 theInt, AsnIoPtr aip, AsnTypePtr atp)
323 {
324         AsnTypePtr atp2;
325         Byte octets[4];
326         int msb, len, i;
327         Int4 cint;
328 
329         atp2 = AsnFindBaseType(atp);
330         atp2 = atp2->type;
331         AsnEnBinTags(atp2, aip);
332 
333         len = 0;
334         /**** split integer into bytes *****/
335         cint = theInt;
336         for (i = 3; i >= 0; i--)
337         {
338                 octets[i] = (Byte)(cint & 0x0ff);
339                 cint >>= 8;
340         }
341 
342         /***** find most significant byte ****/
343         msb = 0;
344         if (theInt >= 0)
345         {
346                 while (msb < 3 && octets[msb] == 0 &&
347                                 ((octets[msb+1] & 0x080) == 0))
348                         msb++;
349         }
350         else
351         {
352                 while (msb < 3 && octets[msb] == 0x0ff &&
353                                 ((octets[msb+1] & 0x080) == 0x080))
354                         msb++;
355         }
356 
357         len = 4 - msb;
358 
359         AsnEnBinLen((Uint4)len, aip);
360 
361         /** shift left to eliminate unnecessary bytes */
362         for ( ; msb > 0; msb--)
363         {
364                 for (i = 0; i < 3; i++)
365                         octets[i] = octets[i+1];
366 /* dirty workaround of an optimization bug of MSVC++.NET compiler */
367 #if defined(_MSC_VER) 
368 #  if _MSC_VER < 1300
369                 octets[3] = 0;
370 #  endif
371 #else
372                 octets[3] = 0;
373 #endif
374         }
375 
376         AsnEnBinBytes(octets, (Uint4)len, aip);
377 
378         return;
379 }
380 
381 /*****************************************************************************
382 *
383 *   void AsnEnBinBigInt(theInt, aip)
384 *
385 *****************************************************************************/
386 NLM_EXTERN void AsnEnBinBigInt (Int8 theInt, AsnIoPtr aip, AsnTypePtr atp)
387 {
388         AsnTypePtr atp2;
389         Byte octets[8];
390         int msb, len, i;
391         Int8 cint;
392 
393         atp2 = AsnFindBaseType(atp);
394         atp2 = atp2->type;
395         AsnEnBinTags(atp2, aip);
396 
397         len = 0;
398         /**** split integer into bytes *****/
399         cint = theInt;
400         for (i = 7; i >= 0; i--)
401         {
402                 octets[i] = (Byte)(cint & 0x0ff);
403                 cint >>= 8;
404         }
405 
406         /***** find most significant byte ****/
407         msb = 0;
408         if (theInt >= 0)
409         {
410                 while (msb < 7 && octets[msb] == 0 &&
411                                 ((octets[msb+1] & 0x080) == 0))
412                         msb++;
413         }
414         else
415         {
416                 while (msb < 7 && octets[msb] == 0x0ff &&
417                                 ((octets[msb+1] & 0x080) == 0x080))
418                         msb++;
419         }
420 
421         len = 8 - msb;
422 
423         AsnEnBinLen((Uint4)len, aip);
424 
425         /** shift left to eliminate unnecessary bytes */
426         for ( ; msb > 0; msb--)
427         {
428                 for (i = 0; i < 7; i++)
429                         octets[i] = octets[i+1];
430 /* dirty workaround of an optimization bug of MSVC++.NET compiler */
431 #if defined(_MSC_VER) 
432 #  if _MSC_VER < 1300
433                 octets[7] = 0;
434 #  endif
435 #else
436                 octets[7] = 0;
437 #endif
438         }
439 
440         AsnEnBinBytes(octets, (Uint4)len, aip);
441 
442         return;
443 }
444 
445 /*****************************************************************************
446 *
447 *   void AsnEnBinBoolean(value, aip)
448 *
449 *****************************************************************************/
450 NLM_EXTERN void AsnEnBinBoolean (Boolean value, AsnIoPtr aip, AsnTypePtr atp)
451 {
452         AsnTypePtr atp2;
453         Byte octets[1];
454 
455         atp2 = AsnFindBaseType(atp);
456         atp2 = atp2->type;
457         AsnEnBinTags(atp2, aip);
458 
459         AsnEnBinLen((Uint4)1, aip);
460 
461         if (value)
462                 octets[0] = 1;
463         else
464                 octets[0] = 0;
465         AsnEnBinBytes(octets, (Uint4)1, aip);
466         return;
467 }
468 /*****************************************************************************
469 *
470 *   Boolean AsnEnBinString(str, aip)
471 *
472 *****************************************************************************/
473 NLM_EXTERN Boolean AsnEnBinString (CharPtr str, AsnIoPtr aip, AsnTypePtr atp)
474 {
475         Uint4 stringlen;
476         AsnTypePtr atp2;
477 
478         atp2 = AsnFindBaseType(atp);
479         atp2 = atp2->type;
480         AsnEnBinTags(atp2, aip);
481 
482         stringlen = StringLen(str);
483         AsnEnBinLen(stringlen, aip);
484         if (! AsnEnBinTheBytes(str, stringlen, aip, TRUE))
485                 return FALSE;
486         return TRUE;
487 }
488 
489 /*****************************************************************************
490 *
491 *   AsnEnBinOctets(bsp, aip, atp)
492 *
493 *****************************************************************************/
494 NLM_EXTERN void AsnEnBinOctets (ByteStorePtr bsp, AsnIoPtr aip, AsnTypePtr atp)
495 {
496         Uint4 totlen, tlen;
497         AsnTypePtr atp2;
498         Byte buf[100];
499 
500         atp2 = AsnFindBaseType(atp);
501         atp2 = atp2->type;
502         AsnEnBinTags(atp2, aip);
503 
504         totlen = BSLen(bsp);
505         AsnEnBinLen(totlen, aip);
506 
507         BSSeek(bsp, 0, SEEK_SET);
508 
509         while (totlen)
510         {
511                 if (totlen < 100)
512                         tlen = totlen;
513                 else
514                         tlen = 100;
515 
516                 BSRead(bsp, buf, tlen);
517                 AsnEnBinBytes(buf, tlen, aip);
518                 totlen -= tlen;
519         }
520         return;
521 }
522 
523 /*****************************************************************************
524 *
525 *   AsnEnBinOpenStruct(aip, atp)
526 *
527 *****************************************************************************/
528 NLM_EXTERN void AsnEnBinOpenStruct (AsnIoPtr aip, AsnTypePtr atp)
529 {
530         AsnTypePtr atp2;
531 
532         atp2 = AsnFindBaseType(atp);
533         atp2 = atp2->type;
534         AsnEnBinTags(atp2, aip);
535         AsnEnBinStartIndef(aip);
536         AsnTypeSetIndent(TRUE, aip, atp);
537         return;
538 }
539 
540 /*****************************************************************************
541 *
542 *   AsnEnBinCloseStruct(aip, atp)
543 *
544 *****************************************************************************/
545 NLM_EXTERN void AsnEnBinCloseStruct (AsnIoPtr aip, AsnTypePtr atp)
546 {
547         int next_type, tagclass;
548 
549         AsnEnBinEndIndef(aip);     /* end the primitive struct */
550         tagclass = aip->typestack[aip->type_indent - 1].type->tagclass;
551         if (tagclass == TAG_CONTEXT)
552                 AsnEnBinEndIndef(aip);   /* end for user tags */
553         next_type = aip->type_indent - 2;   /* end any choices */
554         while ((next_type >= 0) &&
555                 (AsnFindBaseIsa(aip->typestack[next_type].type) == CHOICE_TYPE))
556         {
557                 if (aip->typestack[next_type].type->tagclass != TAG_NONE)
558                         AsnEnBinEndIndef(aip);
559                 next_type--;
560         }
561         AsnTypeSetIndent(FALSE, aip, atp);
562         return;
563 }
564 
565 
566 /*****************************************************************************
567 *
568 *   AsnEnBinStartIndef(aip)
569 *
570 *****************************************************************************/
571 NLM_EXTERN void AsnEnBinStartIndef (AsnIoPtr aip)
572 {
573         Byte octets[1];
574 
575         octets[0] = 128;     /* indefinate length encoding */
576         AsnEnBinBytes(octets, (Uint4)1, aip);
577         return;
578 }
579 
580 /*****************************************************************************
581 *
582 *   AsnEnBinEndIndef(aip)
583 *
584 *****************************************************************************/
585 NLM_EXTERN void AsnEnBinEndIndef (AsnIoPtr aip)
586 {
587         Byte nulls[2];
588 
589         nulls[0] = 0;
590         nulls[1] = 0;
591         AsnEnBinBytes(nulls, (Uint4)2, aip);
592         return;
593 }
594 
595 
596 /*****************************************************************************
597 *
598 *   void AsnEnBinTheBytes(ptr, len, aip, is_string)
599 *       write bytes to asnio output
600 *
601 *****************************************************************************/
602 NLM_EXTERN Boolean LIBCALL  AsnEnBinTheBytes (Pointer ptr, Uint4 len, AsnIoPtr aip, Boolean is_string)
603 {
604         register BytePtr from, to;
605         register int bytes, amount, bad_char = 0, bad_char_ctr = 0;
606 
607         bytes = (int)(aip->bytes - aip->offset);
608         if (! bytes)
609                 bytes = (int)AsnIoWriteBlock(aip);
610         to = aip->buf + aip->offset;
611         from = (BytePtr) ptr;
612 
613         while (len)
614         {
615                 if (aip->io_failure)   /* physical device write failure */
616                         return FALSE;
617 
618                 if (len <= (Uint4)bytes)
619                         amount = (int)len;
620                 else
621                         amount = bytes;
622                 bytes -= amount;
623                 len -= (Uint4)amount;
624                 while (amount)
625                 {
626                         *to = *from;
627                         if (is_string)
628                         {
629                                 if ((aip->fix_non_print != 2) && ((*from < ' ') || (*from > '~')))
630                                 {
631                                         if (! bad_char_ctr)
632                                                 bad_char = (int)(*from);
633                                         bad_char_ctr++;
634                                         *from = '#';
635                                         *to = '#';   /* replace with # */
636                                 }
637                         }
638                         from++; to++; amount--;
639                 }
640                 if (! bytes)
641                 {
642                         aip->offset = aip->bytes;     /* set to write whole block */
643                         bytes = (int)AsnIoWriteBlock(aip);
644                         to = aip->buf;
645                 }
646         }
647         aip->offset = (Int2) (aip->bytes - (Int2) bytes);
648         if ((bad_char_ctr) && ((aip->fix_non_print == 0) || (aip->fix_non_print == 3)))
649                 AsnIoErrorMsg(aip, 106, bad_char, (CharPtr)ptr);
650         return TRUE;
651 }
652 
653 /*****************************************************************************
654 *
655 *   void AsnBinLen(len, aip)
656 *       encode a definate length
657 *
658 *****************************************************************************/
659 NLM_EXTERN void AsnEnBinLen (Uint4 len, AsnIoPtr aip)
660 {
661         Byte octets[5];
662         int octnum, i;
663 
664         for (octnum = 0; octnum < 5; octnum++)
665                 octets[octnum] = 0;
666 
667         if (len <= 127)      /* use short form */
668         {
669                 octets[0] = (Byte)(len & 0x0ffff);
670                 AsnEnBinBytes(octets, (Uint4)1, aip);
671                 return;
672         }
673 
674         if (len <= 0x0ff)  /* use long form */
675                 octnum = 1;
676         else if (len <= 0x0ffff)
677                 octnum = 2;
678         else if (len <= 0x0ffffff)
679                 octnum = 3;
680         else
681                 octnum = 4;
682 
683         octets[0] = (Byte)(0x080 | (octnum & 0x07f));
684 
685         for (i = 1; i <= octnum; i++)
686                 octets[i] = (Byte)((len >> ((octnum - i) * 8)) & 0x0ff);
687 
688         octnum++;
689         AsnEnBinBytes(octets, (Uint4)octnum, aip);
690         return;
691 }
692 
693 

source navigation ]   [ diff markup ]   [ identifier search ]   [ freetext search ]   [ file search ]  

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.