1 /* asndebin.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: asndebin.c
27 *
28 * Author: James Ostell
29 *
30 * Version Creation Date: 3/4/91
31 *
32 * $Revision: 6.16 $
33 *
34 * File Description:
35 * Special binary form (BER) decoder for ASN.1
36 *
37 * Modifications:
38 * --------------------------------------------------------------------------
39 * Date Name Description of modification
40 * ------- ---------- -----------------------------------------------------
41 *
42 * ==========================================================================
43 */
44
45 #include "asnbuild.h"
46
47 #define ASNDEBIN_EOF -2
48
RelaxVisibleStringUTF8(AsnIoPtr aip,AsnTypePtr atp)49 static void RelaxVisibleStringUTF8 (AsnIoPtr aip, AsnTypePtr atp) {
50
51 Int2 isa = 0;
52 Uint1 fix_utf8_in;
53
54 if (aip == NULL || atp == NULL) return;
55 if (atp->type != NULL) {
56 isa = atp->type->isa;
57 } else {
58 isa = atp->isa;
59 }
60 if (! ISA_STRINGTYPE (isa)) return;
61 if (aip->tagclass != atp->tagclass) return;
62 if (aip->tagnumber == atp->tagnumber) return;
63
64 /* !!! CXX-3341 temporarily allow UTF8/VisibleString flexibility !!! */
65 fix_utf8_in = aip->fix_utf8_in;
66 if (fix_utf8_in == 3) return;
67
68 if (aip->tagnumber == TAG_VISIBLESTRING && atp->tagnumber == TAG_UTF8STRING) {
69 aip->tagnumber = atp->tagnumber;
70 } else if (aip->tagnumber == TAG_UTF8STRING && atp->tagnumber == TAG_VISIBLESTRING) {
71 aip->tagnumber = atp->tagnumber;
72
73 if (fix_utf8_in == 0) {
74 aip->utf8_read = TRUE;
75 } else if (fix_utf8_in == 1) {
76 if (! aip->utf8_read) {
77 AsnIoErrorMsg(aip, 107);
78 }
79 aip->utf8_read = TRUE;
80 } else if (fix_utf8_in == 2) {
81 AsnIoErrorMsg(aip, 107);
82 aip->utf8_read = TRUE;
83 }
84 }
85 }
86
87 /*****************************************************************************
88 *
89 * AsnTypePtr AsnBinReadId(aip, atp)
90 * reads identifier for next value
91 *
92 *****************************************************************************/
AsnBinReadId(AsnIoPtr aip,AsnTypePtr atp)93 NLM_EXTERN AsnTypePtr LIBCALL AsnBinReadId (AsnIoPtr aip, AsnTypePtr atp)
94 {
95 Int4 used;
96
97 Int2 isa;
98 AsnTypePtr atp2, atp3, atp4;
99 Boolean found;
100 PstackPtr psp, prevpsp, currpsp;
101
102 used = 0;
103
104 if (! aip->type_indent) /* just starting or ending reading */
105 {
106 if (atp == NULL) /* starting an unknown item */
107 {
108 AsnIoErrorMsg(aip, 1);
109 return NULL;
110 }
111
112 used = AsnDeBinScanTag(aip); /* read the tag */
113
114 if (used == ASNDEBIN_EOF) /* end of file */
115 return NULL;
116 /* see RT toolbox ticket 15030485 for the below fix */
117
118 atp2 = AsnFindBaseType(atp); /* find the base type */
119 if (atp2 == NULL)
120 return atp2;
121 if (atp2->type == NULL)
122 return atp2->type;
123 isa = atp2->type->isa;
124
125
126 if (atp2->type->isa != CHOICE_TYPE)
127 {
128 atp2 = atp2->type; /* will be primitive tag */
129
130 RelaxVisibleStringUTF8 (aip, atp2);
131
132 if ((aip->tagclass != atp2->tagclass) ||
133 (aip->tagnumber != atp2->tagnumber))
134 found = FALSE;
135 else
136 found = TRUE;
137 }
138 else
139 {
140 atp2 = (AsnTypePtr) atp->branch; /* look for a match among choices */
141 found = FALSE;
142 while ((atp2 != NULL) && (! found))
143 {
144 RelaxVisibleStringUTF8 (aip, atp2);
145
146 if ((aip->tagclass == atp2->tagclass) &&
147 (aip->tagnumber == atp2->tagnumber))
148 found = TRUE;
149 else
150 atp2 = atp2->next;
151 }
152 aip->tagsaved = TRUE; /* will need tag for which CHOICE next round */
153 }
154
155 if (! found)
156 {
157 AsnIoErrorMsg(aip, 2, AsnErrGetTypeName(atp->name));
158 return NULL;
159 }
160
161 psp = & aip->typestack[0];
162 psp->len = aip->length;
163 psp->type = atp;
164 psp->resolved = FALSE;
165 psp->tag_indef = FALSE;
166
167 return atp;
168 }
169
170 prevpsp = & aip->typestack[aip->type_indent - 1]; /* previous level */
171 currpsp = prevpsp + 1; /* current level */
172
173 /** end of definate length struct ****/
174 if (prevpsp->len == 0)
175 {
176 prevpsp->resolved = TRUE;
177 return prevpsp->type;
178 }
179
180 if (currpsp->type != NULL) /* reading a struct */
181 {
182 if (! aip->tagsaved) /* already read it? */
183 {
184 used = AsnDeBinScanTag(aip); /* read the tag */
185 if (! AsnDeBinDecr(used, aip)) /* decrement length counter */
186 return NULL;
187 }
188
189 if ((aip->length == 0) && (aip->tagclass == 0) &&
190 (aip->tagnumber == 0)) /* length 0, could be end of contents */
191 {
192 if (prevpsp->len == INDEFINATE)
193 {
194 prevpsp->resolved = TRUE;
195 aip->tagsaved = FALSE;
196 if (prevpsp->tag_indef) /* indefinate user tag? */
197 {
198 used = AsnDeBinScanTag(aip); /* should be 00 for tag */
199 if (! AsnDeBinDecr(used, aip))
200 return NULL;
201 if ((aip->length == 0) && (aip->tagclass == 0) &&
202 (aip->tagnumber == 0))
203 prevpsp->tag_indef = FALSE;
204 else
205 {
206 AsnIoErrorMsg(aip, 3, AsnErrGetTypeName(prevpsp->type->name));
207 return NULL;
208 }
209 }
210 return prevpsp->type;
211 }
212 }
213 else
214 aip->tagsaved = TRUE;
215 }
216
217
218 if (aip->type_indent) /* check for SEQOF and SETOF */
219 {
220 atp = prevpsp->type;
221 atp2 = AsnFindBaseType(atp);
222 isa = atp2->type->isa;
223 if ((isa == SEQOF_TYPE) || (isa == SETOF_TYPE))
224 {
225 atp = (AsnTypePtr) atp2->branch; /* set of what type? */
226 currpsp->type = atp;
227 currpsp->len = INDEFINATE;
228 currpsp->resolved = FALSE;
229 currpsp->tag_indef = FALSE;
230 atp2 = AsnFindBaseType(atp);
231 isa = atp2->type->isa;
232 atp2 = atp2->type; /* get universal type */
233 used = AsnDeBinScanTag(aip); /* read the tag */
234 if (! AsnDeBinDecr(used, aip))
235 return NULL;
236
237 RelaxVisibleStringUTF8 (aip, atp2);
238
239 if ((aip->tagclass != atp2->tagclass) ||
240 (aip->tagnumber != atp2->tagnumber))
241 {
242 if ((aip->length == 0) && (aip->tagclass == 0) &&
243 (aip->tagnumber == 0)) /* length 0, could be end of contents */
244 { /* this handles an empty SEQ OF/SET OF ***/
245 if (prevpsp->len == INDEFINATE)
246 {
247 prevpsp->resolved = TRUE;
248 aip->tagsaved = FALSE;
249 if (prevpsp->tag_indef) /* indefinate user tag? */
250 {
251 used = AsnDeBinScanTag(aip); /* should be 00 for tag */
252 if (! AsnDeBinDecr(used, aip))
253 return NULL;
254 if ((aip->length == 0) && (aip->tagclass == 0) &&
255 (aip->tagnumber == 0))
256 prevpsp->tag_indef = FALSE;
257 else
258 {
259 AsnIoErrorMsg(aip, 3, AsnErrGetTypeName(prevpsp->type->name));
260 return NULL;
261 }
262 }
263 return prevpsp->type;
264 }
265 }
266 else if (isa == CHOICE_TYPE) /* no tag */
267 {
268 aip->tagsaved = TRUE;
269 }
270 else
271 {
272 AsnIoErrorMsg(aip, 4, AsnErrGetTypeName(atp->name));
273 return NULL;
274 }
275 }
276 currpsp->len = aip->length;
277 return atp; /* no type identifier */
278 }
279 }
280
281 used = AsnDeBinScanTag(aip); /* read the tag */
282 if (! AsnDeBinDecr(used, aip)) /* decrement length counter */
283 return NULL;
284
285 if ((aip->length == 0) && (aip->tagclass == 0) &&
286 (aip->tagnumber == 0)) /* length 0, could be end of contents */
287 {
288 if (prevpsp->len == INDEFINATE)
289 {
290 prevpsp->resolved = TRUE;
291 aip->tagsaved = FALSE;
292 if (prevpsp->tag_indef) /* indefinate user tag? */
293 {
294 used = AsnDeBinScanTag(aip); /* should be 00 for tag */
295 if (! AsnDeBinDecr(used, aip))
296 return NULL;
297 if ((aip->length == 0) && (aip->tagclass == 0) &&
298 (aip->tagnumber == 0))
299 prevpsp->tag_indef = FALSE;
300 else
301 {
302 AsnIoErrorMsg(aip, 3, AsnErrGetTypeName(prevpsp->type->name));
303 return NULL;
304 }
305 }
306 return prevpsp->type;
307 }
308 }
309
310 atp2 = AsnFindBaseType(prevpsp->type);
311 atp = AsnDeBinFindElement(aip, (AsnTypePtr) atp2->branch);
312 if (atp == NULL)
313 {
314 AsnIoErrorMsg(aip, 5, AsnErrGetTypeName(prevpsp->type->name));
315 return NULL;
316 }
317
318 if (atp2->type->isa == SEQ_TYPE) /* check sequence order */
319 {
320 atp3 = currpsp->type;
321 if (atp3 != NULL)
322 {
323 atp4 = (AsnTypePtr) atp2->branch;
324 atp3 = atp3->next;
325 while (atp4 != atp3)
326 {
327 if (atp == atp4)
328 {
329 AsnIoErrorMsg(aip, 6, AsnErrGetTypeName(atp->name), AsnErrGetTypeName(atp2->name));
330 return NULL;
331 }
332 atp4 = atp4->next;
333 }
334 }
335 else
336 atp3 = (AsnTypePtr) atp2->branch;
337
338 while ((atp3 != NULL) && (atp3 != atp))
339 {
340 if (! (atp3->optional || atp3->hasdefault))
341 {
342 AsnIoErrorMsg(aip, 7, AsnErrGetTypeName(atp3->name), AsnErrGetTypeName(atp2->name));
343 return NULL;
344 }
345 atp3 = atp3->next;
346 }
347 }
348
349 currpsp->type = atp;
350 currpsp->len = aip->length;
351 currpsp->resolved = FALSE; /* mark first use */
352 if ((atp->tagclass != TAG_UNIVERSAL) && (atp->tagclass != TAG_NONE)
353 && (aip->length == INDEFINATE))
354 currpsp->tag_indef = TRUE;
355 return atp;
356 }
357
358 /*****************************************************************************
359 *
360 * Boolean AsnDeBinDecr(used, aip)
361 * decrement all levels above level with used bytes
362 *
363 *****************************************************************************/
AsnDeBinDecr(Int4 used,AsnIoPtr aip)364 NLM_EXTERN Boolean AsnDeBinDecr (Int4 used, AsnIoPtr aip)
365 {
366 PstackPtr psp, psp0;
367
368 if (used == ASNDEBIN_EOF) return FALSE; /* avoid infinite loop in higher levels */
369
370 if (used <= 0) /* tag saved or INDEFINATE */
371 return TRUE;
372
373 psp = (psp0 = aip->typestack) + aip->type_indent;
374 while (psp > psp0) {
375 --psp;
376 if (psp->len == INDEFINATE) /* if one INDEFINATE, assume all are */
377 return TRUE;
378 if ((psp->len -= used) < 0) {
379 AsnIoErrorMsg(aip, 8, (int)(psp - psp0) /* level */);
380 return FALSE;
381 }
382 }
383 return TRUE;
384 }
385
386 /**** old version ***********************
387 NLM_EXTERN Boolean AsnDeBinDecr (Int4 used, AsnIoPtr aip)
388 {
389 Int2 level;
390
391 if (used == INDEFINATE)
392 return TRUE;
393
394 level = aip->type_indent;
395 while (level)
396 {
397 level--;
398 if (aip->typestack[level].len != INDEFINATE)
399 {
400 aip->typestack[level].len -= used;
401 if (aip->typestack[level].len < 0)
402 {
403 AsnIoErrorMsg(aip, 8, level);
404 return FALSE;
405 }
406 }
407 }
408 return TRUE;
409 }
410 *****************************************/
411 /*****************************************************************************
412 *
413 * Int4 AsnDeBinScanTag(aip)
414 * scan the next tag-length element
415 * return bytes used from input
416 *
417 *****************************************************************************/
AsnDeBinScanTag(AsnIoPtr aip)418 NLM_EXTERN Int4 AsnDeBinScanTag (AsnIoPtr aip)
419 {
420 Int4 used;
421 Uint4 number;
422 Int2 bytes, lenbytes;
423 BytePtr bp;
424 Byte octet, bit8_7, bit5_1;
425 Boolean bit6;
426
427 used = 0; /* no bytes read yet */
428 if (aip->tagsaved) /* return currently saved tag */
429 {
430 aip->tagsaved = FALSE;
431 return used; /* no additional bytes read */
432 }
433
434 bytes = aip->bytes - aip->offset; /* current location in buffer */
435 if (! bytes)
436 {
437 bytes = AsnIoReadBlock(aip);
438 if (bytes == 0)
439 return ASNDEBIN_EOF;
440 }
441 bp = aip->buf + aip->offset;
442
443 /*** read first octet of tag-id ******/
444 octet = *bp;
445 bp++; bytes--; used++;
446
447 bit5_1 = octet & (Byte)0x1f; /* short form tag number */
448 bit6 = (Byte)((octet >> 5) & 0x01); /* constructed? */
449 bit8_7 = (Byte)((octet >> 6) & 0x03); /* tag class */
450
451 switch (bit8_7) /* get tag class */
452 {
453 case 0x0:
454 aip->tagclass = TAG_UNIVERSAL;
455 break;
456 case 0x1:
457 aip->tagclass = TAG_APPLICATION;
458 break;
459 case 0x2:
460 aip->tagclass = TAG_CONTEXT;
461 break;
462 case 0x3:
463 aip->tagclass = TAG_PRIVATE;
464 break;
465 }
466
467 aip->constructed = bit6; /* constructed? */
468
469 /*** get the tag-id ****/
470 if (bit5_1 != 0x1f) /* short form */
471 {
472 aip->tagnumber = bit5_1; /* that's it */
473 }
474 else /* long form */
475 {
476 number = 0; /* have to build it up */
477 do
478 {
479 if (! bytes)
480 {
481 bytes = AsnIoReadBlock(aip);
482 if (! bytes)
483 {AsnIoErrorMsg(aip, 17); return 0;}
484 bp = aip->buf;
485 }
486 octet = *bp;
487 bp++; bytes--; used++;
488 number = (number << 7) + (octet & 0x7f);
489 }
490 while ((octet & 0x80) != 0);
491 aip->tagnumber = (Int2) number;
492 }
493
494 /*** scan the length, if present */
495 if (! bytes)
496 {
497 bytes = AsnIoReadBlock(aip);
498 if (! bytes)
499 {AsnIoErrorMsg(aip, 17); return 0;}
500 bp = aip->buf;
501 }
502
503 octet = *bp;
504 bp++; bytes--; used++;
505
506 if (! (octet & 0x80)) /* short form used */
507 aip->length = octet & 0x7f;
508 else if ((octet & 0x7f) == 0x00) /* indefinate form used */
509 aip->length = INDEFINATE;
510 else /* long form used */
511 {
512 number = 0;
513 for (lenbytes = (Int2)(octet & 0x7f); lenbytes > 0; lenbytes--)
514 {
515 if (! bytes)
516 {
517 bytes = AsnIoReadBlock(aip);
518 if (! bytes)
519 {AsnIoErrorMsg(aip, 17); return 0;}
520 bp = aip->buf;
521 }
522 octet = *bp;
523 bp++; bytes--; used++;
524 number = (number << 8) + octet;
525 }
526 aip->length = number;
527 }
528
529 aip->offset = aip->bytes - bytes;
530 aip->used = used;
531 return used;
532 }
533
534 /*****************************************************************************
535 *
536 * Int2 AsnBinReadVal(aip, atp, valueptr)
537 * read the value pointed at by atp
538 * this should be the same as aip->typestack[aip->type_indent].type
539 * returns START_STRUCT
540 * END_STRUCT
541 * 1 if ok
542 * 0 if an error occurred
543 * if (valueptr == NULL)
544 * just checks that value is of proper type
545 *
546 *****************************************************************************/
547 static CharPtr AsnDeBinReadStringUTF8 (AsnIoPtr aip, AsnTypePtr atp);
548
AsnBinReadVal(AsnIoPtr aip,AsnTypePtr atp,DataValPtr valueptr)549 NLM_EXTERN Int2 LIBCALL AsnBinReadVal (AsnIoPtr aip, AsnTypePtr atp, DataValPtr valueptr)
550 {
551 Int4 used;
552 Int2 isa, retval;
553 Boolean terminalvalue; /* set if read a terminal value */
554 AsnTypePtr atp2;
555 Boolean read_value;
556 DataVal fake_value;
557 AsnTypePtr base_type, curr_type;
558 int next_type;
559 PstackPtr currpsp, prevpsp;
560
561 currpsp = & aip->typestack[aip->type_indent];
562 curr_type = currpsp->type;
563 if (aip->type_indent)
564 prevpsp = currpsp - 1;
565 else
566 prevpsp = NULL;
567
568 if (atp == NULL)
569 return 0;
570
571 base_type = AsnFindBaseType(atp);
572 if (base_type == NULL) /* not found */
573 {
574 base_type = atp;
575 while (base_type->type != NULL)
576 base_type = base_type->type;
577 if (base_type->imported)
578 {
579 AsnIoErrorMsg(aip,9, AsnErrGetTypeName(atp->name), AsnErrGetTypeName(base_type->name));
580 return 0;
581 }
582 else
583 {
584 AsnIoErrorMsg(aip,10, AsnErrGetTypeName(atp->name), AsnErrGetTypeName(base_type->name));
585 return 0;
586 }
587 }
588 isa = base_type->type->isa;
589
590 if (valueptr == NULL) /* just check the value */
591 {
592 read_value = FALSE;
593 valueptr = &fake_value;
594 }
595 else
596 read_value = TRUE;
597
598 retval = 1; /* normal return */
599 terminalvalue = TRUE; /* most values are terminal values */
600
601 if (ISA_STRINGTYPE(isa) && isa != UTF8STRING_TYPE)
602 isa = GENERALSTRING_TYPE;
603
604 switch (isa)
605 {
606 case SEQ_TYPE:
607 case SET_TYPE:
608 case SETOF_TYPE:
609 case SEQOF_TYPE:
610 terminalvalue = FALSE; /* handled by AsnTypeSetIndent() */
611 if ((prevpsp == NULL) || (! prevpsp->resolved)) /* open brace */
612 {
613 AsnTypeSetIndent(TRUE, aip, atp);
614 while (aip->tagclass != TAG_UNIVERSAL) /* read to struct */
615 {
616 used = AsnDeBinScanTag(aip);
617 if (! AsnDeBinDecr(used, aip))
618 return 0;
619 }
620 retval = START_STRUCT;
621 valueptr->intvalue = START_STRUCT;
622 terminalvalue = FALSE;
623 }
624 else
625 { /* close brace already read in AsnBinReadId */
626 switch (isa)
627 {
628 case SEQOF_TYPE:
629 case SETOF_TYPE:
630 break;
631 case SEQ_TYPE: /* check that no more waiting */
632 if (curr_type != NULL) /* check next one */
633 atp2 = curr_type->next;
634 else /* empty sequence written */
635 atp2 = (AsnTypePtr) base_type->branch;
636 while (atp2 != NULL)
637 {
638 if (! (atp2->optional || atp2->hasdefault))
639 {
640 AsnIoErrorMsg(aip, 7, AsnErrGetTypeName(atp2->name), AsnErrGetTypeName(atp->name));
641 return 0;
642 }
643 atp2 = atp2->next;
644 }
645 break;
646 default:
647 break;
648 }
649 next_type = aip->type_indent - 2; /* end any choices */
650 while ((next_type >= 0) &&
651 (AsnFindBaseIsa(aip->typestack[next_type].type) == CHOICE_TYPE))
652 {
653 currpsp = & aip->typestack[next_type];
654 atp2 = currpsp->type;
655 if ((atp2->tagclass != TAG_NONE) &&
656 (currpsp->tag_indef))
657 {
658 used = AsnDeBinScanTag(aip); /* should be 00 for tag */
659 if (! AsnDeBinDecr(used, aip))
660 return 0;
661 if ((aip->length == 0) && (aip->tagclass == 0) &&
662 (aip->tagnumber == 0))
663 currpsp->tag_indef = FALSE;
664 else
665 {
666 AsnIoErrorMsg(aip, 3, AsnErrGetTypeName(atp2->name));
667 return 0;
668 }
669 }
670 next_type--;
671 }
672 AsnTypeSetIndent(FALSE, aip, curr_type);
673 retval = END_STRUCT;
674 valueptr->intvalue = END_STRUCT;
675 }
676 break;
677 case CHOICE_TYPE:
678 AsnTypeSetIndent(TRUE, aip, atp); /* nest down to type */
679 terminalvalue = FALSE;
680 break;
681 default: /* set up for primitive type */
682 base_type = AsnFindBaseType(atp);
683 base_type = base_type->type; /* point at the type itself */
684
685 RelaxVisibleStringUTF8 (aip, base_type);
686
687 while ((aip->tagclass != base_type->tagclass) ||
688 (aip->tagnumber != base_type->tagnumber))/* read to element */
689 {
690 used = AsnDeBinScanTag(aip);
691 if (! AsnDeBinDecr(used, aip))
692 return 0;
693
694 RelaxVisibleStringUTF8 (aip, base_type);
695 }
696
697 if ((aip->bytes - aip->offset) == 0)
698 {
699 if (! AsnIoReadBlock(aip))
700 {AsnIoErrorMsg(aip, 17); return 0;}
701 }
702 switch (isa)
703 {
704 case BOOLEAN_TYPE:
705 valueptr->boolvalue = AsnDeBinReadBoolean(aip, atp);
706 break;
707 case INTEGER_TYPE:
708 valueptr->intvalue = AsnDeBinReadBigInt(aip, atp);
709 break;
710 case ENUM_TYPE:
711 valueptr->intvalue = AsnDeBinReadInteger(aip, atp);
712 break;
713 case BIGINT_TYPE:
714 valueptr->bigintvalue = AsnDeBinReadBigInt(aip, atp);
715 break;
716 case REAL_TYPE:
717 valueptr->realvalue = AsnDeBinReadReal(aip);
718 break;
719 case GENERALSTRING_TYPE:
720 if (read_value)
721 {
722 valueptr->ptrvalue = AsnDeBinReadString(aip, atp);
723 if (valueptr->ptrvalue == NULL)
724 return 0;
725 }
726 else
727 AsnDeBinSkipString(aip);
728 break;
729 case UTF8STRING_TYPE:
730 if (read_value)
731 {
732 valueptr->ptrvalue = AsnDeBinReadStringUTF8(aip, atp);
733 if (valueptr->ptrvalue == NULL)
734 return 0;
735 }
736 else
737 AsnDeBinSkipString(aip);
738 break;
739 case NULL_TYPE:
740 AsnDeBinReadNull(aip, atp);
741 break;
742 case OCTETS_TYPE:
743 case STRSTORE_TYPE:
744 if (read_value)
745 {
746 valueptr->ptrvalue = AsnDeBinReadOctets(aip);
747 if (valueptr->ptrvalue == NULL) return 0;
748 }
749 else
750 AsnDeBinSkipOctets(aip);
751 break;
752 default:
753 AsnIoErrorMsg(aip, 11, AsnErrGetTypeName(atp->name));
754 return 0;
755 }
756 if (currpsp->tag_indef) /* indefinate user tag */
757 {
758 used = AsnDeBinScanTag(aip); /* should be 00 for tag */
759 if (! AsnDeBinDecr(used, aip))
760 return 0;
761 if ((aip->length == 0) && (aip->tagclass == 0) &&
762 (aip->tagnumber == 0))
763 currpsp->tag_indef = FALSE;
764 else
765 {
766 AsnIoErrorMsg(aip, 3, AsnErrGetTypeName(atp->name));
767 return 0;
768 }
769 }
770 }
771
772 if (terminalvalue) /* pop out of any CHOICE nests */
773 {
774 next_type = aip->type_indent - 1; /* end any choices */
775 if ((next_type >= 0) &&
776 (AsnFindBaseIsa(aip->typestack[next_type].type) == CHOICE_TYPE))
777 {
778 while ((next_type >= 0) &&
779 (AsnFindBaseIsa(aip->typestack[next_type].type) == CHOICE_TYPE))
780 {
781 currpsp = & aip->typestack[next_type];
782 atp2 = currpsp->type;
783 if ((curr_type->tagclass != TAG_NONE) &&
784 (currpsp->tag_indef))
785 {
786 used = AsnDeBinScanTag(aip); /* should be 00 for tag */
787 if (! AsnDeBinDecr(used, aip))
788 return 0;
789 if ((aip->length == 0) && (aip->tagclass == 0) &&
790 (aip->tagnumber == 0))
791 currpsp->tag_indef = FALSE;
792 else
793 {
794 AsnIoErrorMsg(aip, 3, AsnErrGetTypeName(atp2->name));
795 return 0;
796 }
797 }
798 next_type--;
799 }
800 AsnTypeSetIndent(FALSE, aip, curr_type);
801 }
802 }
803
804 return retval;
805 }
806
807 /*****************************************************************************
808 *
809 * AsnTypePtr AsnDeBinFindType(aip, amp)
810 * returns pointer to type definition in amp
811 * or NULL if not found
812 *
813 *****************************************************************************/
AsnDeBinFindType(AsnIoPtr aip,AsnModulePtr amp)814 NLM_EXTERN AsnTypePtr AsnDeBinFindType (AsnIoPtr aip, AsnModulePtr amp)
815 {
816 AsnTypePtr atp;
817
818 while (amp != NULL)
819 {
820 atp = AsnDeBinFindElement(aip, amp->types);
821 if (atp != NULL)
822 return atp;
823
824 amp = amp->next;
825 }
826 return NULL;
827 }
828
829 /*****************************************************************************
830 *
831 * AsnTypePtr AsnDeBinFindElement(aip, atp)
832 * finds an element in a list of elements
833 * (elements of SEQ, SET, CHOICE)
834 *
835 *****************************************************************************/
AsnDeBinFindElement(AsnIoPtr aip,AsnTypePtr atp)836 NLM_EXTERN AsnTypePtr AsnDeBinFindElement (AsnIoPtr aip, AsnTypePtr atp)
837 {
838 while (atp != NULL)
839 {
840 RelaxVisibleStringUTF8 (aip, atp);
841
842 if ((aip->tagclass == atp->tagclass) &&
843 (aip->tagnumber == atp->tagnumber))
844 return atp;
845 else
846 atp = atp->next;
847 }
848 return NULL;
849 }
850
851
852 /*****************************************************************************
853 *
854 * Int4 AsnDeBinReadInteger(aip, atp)
855 * expects an INTEGER or ENUMERATED next
856 * assumes none of it has already been read
857 * does not advance to next token
858 * atp points to the definition of this integer for named values
859 *
860 *****************************************************************************/
AsnDeBinReadInteger(AsnIoPtr aip,AsnTypePtr atp)861 NLM_EXTERN Int4 AsnDeBinReadInteger (AsnIoPtr aip, AsnTypePtr atp)
862 {
863 Int2 bytes, len;
864 Uint4 number;
865 BytePtr bp;
866 AsnValxNodePtr avnp;
867 Int4 value;
868 AsnTypePtr atp2;
869
870 bytes = aip->bytes - aip->offset;
871 bp = aip->buf + aip->offset;
872 len = (Int2) aip->length;
873 aip->tagsaved = FALSE;
874
875 if ((*bp & 0x80) != 0) /* negative number */
876 number = (Uint4)(-1);
877 else
878 number = 0;
879
880 while (len)
881 {
882 number = (number << 8) | (*bp & 0xff);
883 bp++; bytes--; len--;
884 if (! bytes)
885 {
886 bytes = AsnIoReadBlock(aip);
887 if (! bytes)
888 {AsnIoErrorMsg(aip, 17); return 0;}
889 bp = aip->buf;
890 }
891 }
892
893 value = (Int4) number;
894
895 if (! AsnDeBinDecr(aip->length, aip))
896 return 0;
897 aip->offset = aip->bytes - bytes;
898
899 if (AsnFindBaseIsa(atp) != ENUM_TYPE)
900 return value;
901
902 /******************** read a named integer value *********/
903
904 atp2 = AsnFindBaseType(atp);
905 if (atp2->branch != NULL) /* named values */
906 {
907 avnp = (AsnValxNodePtr) atp2->branch;
908 while (avnp != NULL)
909 {
910 if (avnp->intvalue == value)
911 return value;
912 avnp = avnp->next;
913 }
914 }
915
916 AsnIoErrorMsg(aip, 12, value, AsnErrGetTypeName(atp->name));
917
918 return 0;
919 }
920
921 /*****************************************************************************
922 *
923 * Int8 AsnDeBinReadBigInt(aip, atp)
924 * expects an INTEGER next
925 * assumes none of it has already been read
926 * does not advance to next token
927 * atp points to the definition of this integer for named values
928 *
929 *****************************************************************************/
AsnDeBinReadBigInt(AsnIoPtr aip,AsnTypePtr atp)930 NLM_EXTERN Int8 AsnDeBinReadBigInt (AsnIoPtr aip, AsnTypePtr atp)
931 {
932 Int2 bytes, len;
933 Uint8 number;
934 BytePtr bp;
935 AsnValxNodePtr avnp;
936 Int8 value;
937 AsnTypePtr atp2;
938
939 bytes = aip->bytes - aip->offset;
940 bp = aip->buf + aip->offset;
941 len = (Int2) aip->length;
942 aip->tagsaved = FALSE;
943
944 if ((*bp & 0x80) != 0) /* negative number */
945 number = (Uint8)(-1);
946 else
947 number = 0;
948
949 while (len)
950 {
951 number = (number << 8) | (*bp & 0xff);
952 bp++; bytes--; len--;
953 if (! bytes)
954 {
955 bytes = AsnIoReadBlock(aip);
956 if (! bytes)
957 {AsnIoErrorMsg(aip, 17); return 0;}
958 bp = aip->buf;
959 }
960 }
961
962 value = (Int8) number;
963
964 if (! AsnDeBinDecr(aip->length, aip))
965 return 0;
966 aip->offset = aip->bytes - bytes;
967
968 if (AsnFindBaseIsa(atp) != ENUM_TYPE)
969 return value;
970
971 /******************** read a named integer value *********/
972
973 atp2 = AsnFindBaseType(atp);
974 if (atp2->branch != NULL) /* named values */
975 {
976 avnp = (AsnValxNodePtr) atp2->branch;
977 while (avnp != NULL)
978 {
979 if (avnp->intvalue == value)
980 return value;
981 avnp = avnp->next;
982 }
983 }
984
985 AsnIoErrorMsg(aip, 12, value, AsnErrGetTypeName(atp->name));
986
987 return (Int8)0;
988 }
989
990 /*****************************************************************************
991 *
992 * Boolean AsnDeBinReadBoolean(aip, atp)
993 * expects a BOOLEAN next
994 * assumes none of it has already been read
995 * does not advance to next token
996 * atp points to the definition of this BOOLEN
997 *
998 *****************************************************************************/
AsnDeBinReadBoolean(AsnIoPtr aip,AsnTypePtr atp)999 NLM_EXTERN Boolean AsnDeBinReadBoolean (AsnIoPtr aip, AsnTypePtr atp)
1000 {
1001 BytePtr bp;
1002 Byte octet;
1003 Boolean result = TRUE;
1004
1005 aip->tagsaved = FALSE;
1006 if (aip->length != 1)
1007 {
1008 AsnIoErrorMsg(aip, 13, AsnErrGetTypeName(atp->name));
1009 return FALSE;
1010 }
1011
1012 bp = aip->buf + aip->offset;
1013 octet = *bp;
1014
1015 if (octet == 0)
1016 result = FALSE;
1017 else
1018 result = TRUE;
1019
1020 aip->offset++;
1021 AsnDeBinDecr((Int4)1, aip);
1022
1023 return result;
1024 }
1025
1026 /*****************************************************************************
1027 *
1028 * Int4 AsnDeBinReadString(aip, atp)
1029 * expects any String type next
1030 * assumes none of it has already been read
1031 * does not advance to next token
1032 * atp points to the definition of this String
1033 * packs String to single value, if segmented on input
1034 *
1035 *****************************************************************************/
AsnDeBinReadStringEx(AsnIoPtr aip,AsnTypePtr atp,Uint1 fix_non_print)1036 static CharPtr AsnDeBinReadStringEx (AsnIoPtr aip, AsnTypePtr atp, Uint1 fix_non_print)
1037 {
1038 Int4 len;
1039 register int bytes, amount;
1040 register BytePtr bp;
1041 register CharPtr tmp;
1042 CharPtr result;
1043
1044 aip->tagsaved = FALSE;
1045 len = aip->length;
1046 AsnDeBinDecr(len, aip);
1047 result = (CharPtr) MemGet((size_t)(len + 1), FALSE);
1048 if (result == NULL)
1049 {
1050 AsnIoErrorMsg(aip, 14, len, AsnErrGetTypeName(atp->name));
1051 return NULL;
1052 }
1053 result[len] = '\0';
1054
1055 bp = aip->buf + aip->offset;
1056 bytes = (int)(aip->bytes - aip->offset);
1057 tmp = result;
1058
1059 while (len)
1060 {
1061 if ((Int4)bytes >= len)
1062 amount = (int) len;
1063 else
1064 amount = bytes;
1065 bytes -= amount;
1066 len -= (Int4)amount;
1067 while (amount)
1068 {
1069 if ((fix_non_print != 2) && ((* bp < ' ') || (*bp > '~')))
1070 {
1071 *tmp = '\0';
1072 if ((fix_non_print == 0) || (fix_non_print == 3))
1073 {
1074 AsnIoErrorMsg(aip, 106, (int)(*bp), result);
1075 }
1076 *bp = '#'; /* repair string with # */
1077 }
1078 *tmp = *bp;
1079 tmp++; bp++; amount--;
1080 }
1081 if (! bytes)
1082 {
1083 bytes = (int) AsnIoReadBlock(aip);
1084 if (! bytes)
1085 {AsnIoErrorMsg(aip, 17); return NULL;}
1086 bp = aip->buf;
1087 }
1088 }
1089 aip->offset = aip->bytes - (Int2) bytes;
1090 return result;
1091 }
1092
AsnDeBinReadString(AsnIoPtr aip,AsnTypePtr atp)1093 NLM_EXTERN CharPtr AsnDeBinReadString (AsnIoPtr aip, AsnTypePtr atp)
1094
1095 {
1096 return AsnDeBinReadStringEx (aip, atp, aip->fix_non_print);
1097 }
1098
AsnDeBinReadStringUTF8(AsnIoPtr aip,AsnTypePtr atp)1099 static CharPtr AsnDeBinReadStringUTF8 (AsnIoPtr aip, AsnTypePtr atp)
1100
1101 {
1102 return AsnDeBinReadStringEx (aip, atp, 2);
1103 }
1104
1105 /*****************************************************************************
1106 *
1107 * void AsnDeBinSkipString(aip)
1108 * expects any String type next
1109 * assumes none of it has already been read
1110 * does not advance to next token
1111 * just reads past end of string
1112 *
1113 *****************************************************************************/
AsnDeBinSkipString(AsnIoPtr aip)1114 NLM_EXTERN void AsnDeBinSkipString (AsnIoPtr aip)
1115 {
1116 Int4 len;
1117 register int bytes, amount;
1118 register BytePtr bp, tmp;
1119 int bad;
1120
1121 aip->tagsaved = FALSE;
1122 len = aip->length;
1123 AsnDeBinDecr(len, aip);
1124
1125 bp = aip->buf + aip->offset;
1126 tmp = bp;
1127 bytes = (int)(aip->bytes - aip->offset);
1128
1129 while (len)
1130 {
1131 if ((Int4)bytes >= len)
1132 amount = (int) len;
1133 else
1134 amount = bytes;
1135 bytes -= amount;
1136 len -= (Int4)amount;
1137 while (amount)
1138 {
1139 if ((* bp < ' ') || (*bp > '~'))
1140 {
1141 bad = (int)(*bp);
1142 *bp = '\0';
1143 AsnIoErrorMsg(aip, 106, bad, (CharPtr)tmp);
1144 aip->io_failure = TRUE;
1145 }
1146 bp++; amount--;
1147 }
1148 if (! bytes)
1149 {
1150 bytes = (int) AsnIoReadBlock(aip);
1151 if (! bytes)
1152 {AsnIoErrorMsg(aip, 17); return;}
1153 bp = aip->buf;
1154 tmp = bp;
1155 }
1156 }
1157 aip->offset = aip->bytes - (Int2) bytes;
1158 return;
1159 }
1160
1161 /*****************************************************************************
1162 *
1163 * AsnDeBinReadOctets(aip)
1164 * expects any OCTETS type next
1165 * assumes none of it has already been read
1166 * does not advance to next token
1167 *
1168 *****************************************************************************/
AsnDeBinReadOctets(AsnIoPtr aip)1169 NLM_EXTERN ByteStorePtr AsnDeBinReadOctets (AsnIoPtr aip)
1170 {
1171 Int4 len;
1172 Int2 bytes, amount;
1173 BytePtr bp;
1174 ByteStorePtr bsp;
1175
1176 aip->tagsaved = FALSE;
1177 len = aip->length;
1178 AsnDeBinDecr(len, aip);
1179 bsp = BSNew((Uint4)len);
1180 if (bsp == NULL) return bsp;
1181
1182 bp = aip->buf + aip->offset;
1183 bytes = aip->bytes - aip->offset;
1184
1185 while (len)
1186 {
1187 if ((Int4)bytes >= len)
1188 amount = (Int2) len;
1189 else
1190 amount = bytes;
1191 BSWrite(bsp, bp, amount);
1192 len -= amount;
1193 bytes -= amount;
1194 if (! bytes)
1195 {
1196 bytes = AsnIoReadBlock(aip);
1197 if (! bytes)
1198 {AsnIoErrorMsg(aip, 17); return NULL;}
1199 bp = aip->buf;
1200 }
1201 }
1202 aip->offset = aip->bytes - bytes;
1203 return bsp;
1204 }
1205
1206 /*****************************************************************************
1207 *
1208 * AsnDeBinSkipOctets(aip)
1209 * expects any OCTETS type next
1210 * assumes none of it has already been read
1211 * does not advance to next token
1212 *
1213 *****************************************************************************/
AsnDeBinSkipOctets(AsnIoPtr aip)1214 NLM_EXTERN void AsnDeBinSkipOctets (AsnIoPtr aip)
1215 {
1216 Int4 len;
1217 Int2 bytes, amount;
1218
1219 aip->tagsaved = FALSE;
1220 len = aip->length;
1221 AsnDeBinDecr(len, aip);
1222
1223 bytes = aip->bytes - aip->offset;
1224
1225 while (len)
1226 {
1227 if ((Int4)bytes >= len)
1228 amount = (Int2) len;
1229 else
1230 amount = bytes;
1231 len -= amount;
1232 bytes -= amount;
1233 if (! bytes)
1234 {
1235 bytes = AsnIoReadBlock(aip);
1236 if (! bytes)
1237 {AsnIoErrorMsg(aip, 17); return ;}
1238 }
1239 }
1240 aip->offset = aip->bytes - bytes;
1241 return;
1242 }
1243
1244 /*****************************************************************************
1245 *
1246 * FloatHi AsnDeBinReadReal(aip)
1247 * expects a REAL next
1248 * assumes none of it has already been read
1249 * does not advance to next token
1250 *
1251 *****************************************************************************/
AsnDeBinReadReal(AsnIoPtr aip)1252 NLM_EXTERN FloatHi AsnDeBinReadReal (AsnIoPtr aip)
1253 {
1254 double result = 0.0;
1255 Int4 len;
1256 Int2 bytes, amount;
1257 BytePtr bp;
1258 char buf[200], *tmp;
1259
1260 aip->tagsaved = FALSE;
1261 len = aip->length;
1262 AsnDeBinDecr(len, aip);
1263
1264 bp = aip->buf + aip->offset;
1265 bytes = aip->bytes - aip->offset;
1266 tmp = buf;
1267
1268 while (len)
1269 {
1270 if ((Int4)bytes >= len)
1271 amount = (Int2) len;
1272 else
1273 amount = bytes;
1274 MemCopy(tmp, bp, (size_t)amount);
1275 tmp += amount;
1276 len -= amount;
1277 bytes -= amount;
1278 if (! bytes)
1279 {
1280 bytes = AsnIoReadBlock(aip);
1281 if (! bytes)
1282 {AsnIoErrorMsg(aip, 17); return (FloatHi)result;}
1283 bp = aip->buf;
1284 }
1285 }
1286 aip->offset = aip->bytes - bytes;
1287
1288 if (buf[0] != '\0') /* not decimal encoding */
1289 {
1290 AsnIoErrorMsg(aip, 15);
1291 return (FloatHi)result;
1292 }
1293
1294 *tmp = '\0';
1295 /* range check base 10 exponents assuming doubles */
1296
1297 if ((tmp = StringStr((buf+1), "e")) != NULL)
1298 {
1299 int n = atoi(tmp + 1);
1300 if (n < DBL_MIN_10_EXP) /** too small, return 0.0 **/
1301 return (FloatHi)result;
1302 else if (n > DBL_MAX_10_EXP) /** too big, return the max */
1303 return (FloatHi)DBL_MAX;
1304 }
1305
1306 if (sscanf((buf + 1), "%lf", &result) != 1) {
1307 result = 0.0;
1308 }
1309 return (FloatHi)result;
1310 }
1311
1312 /*****************************************************************************
1313 *
1314 * void AsnDeBinReadNull(aip, atp)
1315 *
1316 *****************************************************************************/
AsnDeBinReadNull(AsnIoPtr aip,AsnTypePtr atp)1317 NLM_EXTERN void AsnDeBinReadNull (AsnIoPtr aip, AsnTypePtr atp)
1318 {
1319 aip->tagsaved = FALSE;
1320 if (aip->length != 0)
1321 AsnIoErrorMsg(aip, 16, AsnErrGetTypeName(atp->name));
1322
1323 return;
1324 }
1325
1326 /*****************************************************************************
1327 *
1328 * void AsnDeBinSkipStruct(aip)
1329 * skips current structure and all substructures
1330 * Does NOT read following element
1331 *
1332 *****************************************************************************/
AsnDeBinSkipStruct(AsnIoPtr aip)1333 NLM_EXTERN void AsnDeBinSkipStruct (AsnIoPtr aip)
1334 {
1335 aip->tagsaved = FALSE;
1336 AsnIoErrorMsg(aip, 0);
1337 return;
1338 }
1339
1340