1 /* asnio.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: asnio.c
27 *
28 * Author: James Ostell
29 *
30 * Version Creation Date: 3/4/91
31 *
32 * $Revision: 6.16 $
33 *
34 * File Description:
35 * Routines for AsnIo objects. This code has some machine dependencies.
36 * Currently it works for all ncbi supported platforms.
37 *
38 * Modifications:
39 * --------------------------------------------------------------------------
40 * Date Name Description of modification
41 * ------- ---------- -----------------------------------------------------
42 *
43 * ==========================================================================
44 */
45
46 /*****************************************************************************
47 *
48 * asnio.c
49 * routines for AsnIo objects
50 * AsnIoError() uses varargs, so has some portability issues
51 *
52 *****************************************************************************/
53
54 #include "asnbuild.h"
55 #include <tsprintf.h>
56
57 /*
58 NLM_EXTERN char * g_asnlib = "AsnLib";
59 */
60
61 static Int2 bufsize = ASNIO_BUFSIZE; /* current default size of AsnIo buf */
62
63 /*****************************************************************************
64 *
65 * AsnIoPtr AsnIoOpen(file_name, mode)
66 *
67 *****************************************************************************/
AsnIoOpen(CharPtr file_name,CharPtr mode)68 NLM_EXTERN AsnIoPtr LIBCALL AsnIoOpen (CharPtr file_name, CharPtr mode)
69 {
70 AsnIoPtr aip;
71 Int1 type;
72 FILE *fp;
73
74 if (file_name == NULL)
75 {
76 AsnIoErrorMsg(NULL, 80);
77 return NULL;
78 }
79
80 if (! StringCmp(mode, "r"))
81 type = ASNIO_TEXT_IN;
82 else if (! StringCmp(mode, "w"))
83 type = ASNIO_TEXT_OUT;
84 else if (! StringCmp(mode, "wx"))
85 {
86 type = ASNIO_TEXT_OUT;
87 type |= ASNIO_XML;
88 }
89 else if (! StringCmp(mode, "rb"))
90 type = ASNIO_BIN_IN;
91 else if (! StringCmp(mode, "wb"))
92 type = ASNIO_BIN_OUT;
93 else
94 {
95 AsnIoErrorMsg(NULL, 81, mode);
96 return NULL;
97 }
98
99 if (!StringCmp(mode, "wx")) {
100 fp = FileOpen(file_name, "w");
101 } else {
102 fp = FileOpen(file_name, mode);
103 }
104
105 if (fp == NULL)
106 {
107 /*** Message posted by FileOpen() **
108 AsnIoErrorMsg(NULL, 82, file_name);
109 ***********************************/
110 return NULL;
111 }
112
113 aip = AsnIoNew(type, fp, NULL, NULL, NULL);
114 if (aip != NULL)
115 aip->fname = StringSave(file_name);
116
117 return aip;
118 }
119
120 static CharPtr AsnXMLModuleDefaultPrefix = "\0";
121 static CharPtr AsnXMLModulePrefix = "\0";
122
AsnSetXMLmodulePrefix(CharPtr prefix)123 NLM_EXTERN Boolean LIBCALL AsnSetXMLmodulePrefix (CharPtr prefix)
124 {
125 static CharPtr zero = "\0";
126 AsnXMLModulePrefix = prefix;
127 if (prefix == NULL)
128 AsnXMLModulePrefix = zero;
129 return TRUE;
130 }
AsnSetXMLmodulePrefixToDefault(void)131 NLM_EXTERN Boolean LIBCALL AsnSetXMLmodulePrefixToDefault (void)
132 {
133 AsnXMLModulePrefix = AsnXMLModuleDefaultPrefix;
134 return TRUE;
135 }
136
AsnGetXMLmodulePrefix(void)137 NLM_EXTERN CharPtr LIBCALL AsnGetXMLmodulePrefix (void)
138 {
139 return AsnXMLModulePrefix;
140 }
141
142 /*****************************************************************************
143 *
144 * AsnIoPtr AsnIoNew(type, fp, iostruct, readfunc, writefunc)
145 * function pointers are optional
146 * if not given, uses file functions
147 *
148 *****************************************************************************/
AsnIoNew(Int1 type,FILE * fp,Pointer iostruct,IoFuncType readfunc,IoFuncType writefunc)149 NLM_EXTERN AsnIoPtr LIBCALL AsnIoNew (Int1 type, FILE *fp, Pointer iostruct, IoFuncType readfunc, IoFuncType writefunc)
150 {
151 AsnIoPtr aip;
152 #ifdef OS_UNIX
153 CharPtr str;
154 int val;
155 #endif
156
157
158 aip = (AsnIoPtr) MemNew(sizeof(AsnIo));
159 if (aip == NULL)
160 return NULL;
161
162 aip->bufsize = bufsize;
163 if (! (type & ASNIO_CARRIER)) /* not AsnIoNullOpen() */
164 aip->buf = (BytePtr) MemNew(bufsize);
165 aip->type = type;
166 aip->fp = fp;
167 aip->iostruct = iostruct;
168 aip->readfunc = readfunc;
169 aip->writefunc = writefunc;
170
171 if (type & ASNIO_OUT)
172 aip->bytes = aip->bufsize; /* have a buffer ready to write */
173 aip->linebuf = (CharPtr)aip->buf;
174 aip->tabsize = 2;
175 aip->linelength = 78;
176 aip->max_indent = 10; /* start with 10 indent levels */
177 aip->first = (BoolPtr) MemNew((sizeof(Boolean) * 10));
178 aip->first[0] = TRUE;
179 aip->typestack = (PstackPtr) MemNew((sizeof(Pstack) * 10));
180 aip->max_type = 10;
181
182 #ifdef OS_UNIX
183 /* !!! CXX-3341 Allow environment variables to set initial policies !!! */
184
185 str = (CharPtr) getenv ("FIX_NON_PRINT_POLICY");
186 if (StringDoesHaveText (str) && sscanf (str, "%d", &val) == 1 && val >= 0 && val <= 3) {
187 aip->fix_non_print = (Uint1) val;
188 }
189
190 if ((type & ASNIO_BIN) && (type & ASNIO_IN)) {
191 str = (CharPtr) getenv ("UTF8_INPUT_POLICY");
192 if (StringDoesHaveText (str) && sscanf (str, "%d", &val) == 1 && val >= 0 && val <= 3) {
193 aip->fix_utf8_in = (Uint1) val;
194 }
195 }
196
197 if ((type & ASNIO_BIN) && (type & ASNIO_OUT)) {
198 str = (CharPtr) getenv ("UTF8_OUTPUT_POLICY");
199 if (StringDoesHaveText (str) && sscanf (str, "%d", &val) == 1 && val >= 0 && val <= 3) {
200 aip->fix_utf8_out = (Uint1) val;
201 }
202 }
203 #endif
204
205 return aip;
206 }
207
208 /*****************************************************************************
209 *
210 * AsnIoPtr AsnIoClose(aip)
211 *
212 *****************************************************************************/
AsnIoClose(AsnIoPtr aip)213 NLM_EXTERN AsnIoPtr LIBCALL AsnIoClose (AsnIoPtr aip)
214 {
215 return AsnIoFree (aip, TRUE);
216 }
217
218 /*****************************************************************************
219 *
220 * AsnIoPtr AsnIoFree(aip, close_file)
221 *
222 *****************************************************************************/
AsnIoFree(AsnIoPtr aip,Boolean close_file)223 NLM_EXTERN AsnIoPtr LIBCALL AsnIoFree (AsnIoPtr aip, Boolean close_file)
224 {
225 FILE *fp;
226 int type;
227
228 if (aip == NULL)
229 return aip;
230
231 type = aip->type;
232 fp = aip->fp;
233
234 if (type & ASNIO_OUT)
235 {
236 aip->first[aip->indent_level] = TRUE;
237 if (type & ASNIO_TEXT)
238 AsnPrintNewLine(aip);
239 AsnIoFlush(aip);
240 }
241
242 if (close_file)
243 FileClose(fp);
244
245 MemFree(aip->first);
246 MemFree(aip->typestack);
247 MemFree(aip->buf);
248 if (aip->fname != NULL)
249 MemFree(aip->fname);
250 AsnIoOptionFree(aip, 0, 0);
251 AsnExpOptFree(aip, NULL);
252 MemFree(aip);
253 return NULL;
254 }
255
256 /*****************************************************************************
257 *
258 * AsnOptionPtr AsnIoOptionNew(aip, ao_class, type, data, freefunc)
259 * allocates and adds an option to aip
260 * returns a pointer to it.
261 *
262 *****************************************************************************/
AsnIoOptionNew(AsnIoPtr aip,Int2 ao_class,Int2 type,DataVal data,AsnOptFreeFunc freefunc)263 NLM_EXTERN AsnOptionPtr LIBCALL AsnIoOptionNew (AsnIoPtr aip, Int2 ao_class, Int2 type, DataVal data, AsnOptFreeFunc freefunc)
264 {
265 if (aip == NULL)
266 return NULL;
267
268 return AsnOptionNew(&aip->aop, ao_class, type, data, freefunc);
269 }
270
271 /*****************************************************************************
272 *
273 * AsnIoOptionFree(aip, ao_class, type)
274 * clears options of ao_class
275 * or if ao_class == 0 clears all options
276 * if type == 0, clears all options of ao_class
277 *
278 *****************************************************************************/
AsnIoOptionFree(AsnIoPtr aip,Int2 ao_class,Int2 type)279 NLM_EXTERN void LIBCALL AsnIoOptionFree (AsnIoPtr aip, Int2 ao_class, Int2 type)
280 {
281 AsnOptionFree(&aip->aop, ao_class, type);
282 return;
283 }
284
285 /*****************************************************************************
286 *
287 * AsnOptionPtr AsnIoOptionGet(aip, ao_class, type, last)
288 * gets next option after last
289 * start with last = NULL
290 * if ao_class = 0, match any ao_class
291 * type = 0 match any type
292 *
293 *****************************************************************************/
AsnIoOptionGet(AsnIoPtr aip,Int2 ao_class,Int2 type,AsnOptionPtr last)294 NLM_EXTERN AsnOptionPtr LIBCALL AsnIoOptionGet (AsnIoPtr aip, Int2 ao_class, Int2 type, AsnOptionPtr last)
295 {
296 if (aip == NULL)
297 return NULL;
298
299 return AsnOptionGet(aip->aop, ao_class, type, last);
300 }
301
302 /*****************************************************************************
303 *
304 * AsnOptionPtr AsnOptionNew(aopp, ao_class, type, data, freefunc)
305 * allocates and adds an option to aopp
306 * returns a pointer to it.
307 *
308 *****************************************************************************/
AsnOptionNew(AsnOptionPtr PNTR aopp,Int2 ao_class,Int2 type,DataVal data,AsnOptFreeFunc freefunc)309 NLM_EXTERN AsnOptionPtr LIBCALL AsnOptionNew (AsnOptionPtr PNTR aopp, Int2 ao_class, Int2 type, DataVal data, AsnOptFreeFunc freefunc)
310 {
311 AsnOptionPtr aop, curr;
312
313 aop = (AsnOptionPtr) MemNew(sizeof(AsnOption));
314 if (aop == NULL)
315 return NULL;
316
317 aop->ao_class = ao_class;
318 aop->type = type;
319 aop->data = data;
320 aop->freefunc = freefunc;
321
322 if (aopp != NULL)
323 {
324 curr = *aopp;
325 if (curr == NULL)
326 *aopp = aop;
327 else
328 {
329 while (curr->next != NULL)
330 curr = curr->next;
331 curr->next = aop;
332 }
333 }
334 return aop;
335 }
336
337 /*****************************************************************************
338 *
339 * AsnOptionFree(aopp, ao_class, type)
340 * clears options of ao_class
341 * or if ao_class == 0 clears all options
342 * if type == 0, clears all options of ao_class
343 *
344 *****************************************************************************/
AsnOptionFree(AsnOptionPtr PNTR aopp,Int2 ao_class,Int2 type)345 NLM_EXTERN void LIBCALL AsnOptionFree (AsnOptionPtr PNTR aopp, Int2 ao_class, Int2 type)
346 {
347 AsnOptionPtr curr, next, prev, first;
348
349 if (aopp == NULL)
350 return;
351
352 curr = *aopp;
353 prev = NULL;
354 first = NULL;
355 while (curr != NULL)
356 {
357 next = curr->next;
358 if (AsnClassTypeMatch (ao_class, type,
359 curr->ao_class, curr->type))
360 {
361 if (curr->freefunc != NULL)
362 (*curr->freefunc)(curr->data.ptrvalue);
363 if (prev != NULL)
364 prev->next = next;
365 MemFree(curr);
366 }
367 else
368 {
369 if (first == NULL)
370 first = curr;
371 prev = curr;
372 }
373 curr = next;
374 }
375
376 *aopp = first;
377 return;
378 }
379
380
381 /*****************************************************************************
382 *
383 * Boolean AsnClassTypeMatch (ao_class, type, this_class, this_type)
384 * checks if ao_class and type match in a way that makes for
385 * clean logic
386 **********************/
AsnClassTypeMatch(Int2 ao_class,Int2 type,Int2 this_class,Int2 this_type)387 NLM_EXTERN Boolean LIBCALL AsnClassTypeMatch (Int2 ao_class, Int2 type, Int2 this_class, Int2 this_type)
388 {
389 Boolean retval = FALSE;
390
391 if ((! ao_class) || (ao_class == this_class))
392 {
393 if ((! type) || (type == this_type))
394 {
395 retval = TRUE;
396 }
397 }
398
399 return retval;
400 }
401
402 /*****************************************************************************
403 *
404 * AsnOptionPtr AsnOptionGet(head, ao_class, type, last)
405 * gets next option after last
406 * start with last = NULL
407 * if ao_class = 0, match any ao_class
408 * type = 0 match any type
409 *
410 *****************************************************************************/
AsnOptionGet(AsnOptionPtr head,Int2 ao_class,Int2 type,AsnOptionPtr last)411 NLM_EXTERN AsnOptionPtr LIBCALL AsnOptionGet (AsnOptionPtr head, Int2 ao_class, Int2 type, AsnOptionPtr last)
412
413 {
414 AsnOptionPtr aop;
415
416 if (head == NULL)
417 return NULL;
418
419 aop = head;
420
421 if (last != NULL)
422 {
423 while ((aop != NULL) && (aop != last))
424 aop = aop->next;
425 if (aop != NULL)
426 aop = aop->next;
427 }
428
429 while (aop != NULL)
430 {
431 if ((ao_class == 0) || (ao_class == aop->ao_class))
432 {
433 if ((type == 0) || (type == aop->type))
434 return aop;
435 }
436 aop = aop->next;
437 }
438
439 return NULL;
440 }
441
442 /*****************************************************************************
443 *
444 * Boolean AsnIoSetBufsize(aip, size)
445 * replaces current buffer with one of new size
446 * ASSUMES aip has NOT YET been USED
447 * if (aip == NULL)
448 * changes default size of buffer for all new AsnIo
449 *
450 *****************************************************************************/
AsnIoSetBufsize(AsnIoPtr aip,Int2 size)451 NLM_EXTERN Boolean LIBCALL AsnIoSetBufsize (AsnIoPtr aip, Int2 size)
452 {
453 BytePtr tmp;
454
455 if (aip == NULL)
456 {
457 bufsize = size; /* set default size */
458 return TRUE;
459 }
460 else
461 {
462 tmp = (BytePtr) MemNew(size);
463 if (tmp == NULL)
464 return FALSE;
465 MemFree(aip->buf);
466 aip->buf = tmp;
467 aip->bufsize = size;
468 aip->linebuf = (CharPtr)aip->buf;
469 if (aip->type & ASNIO_OUT)
470 aip->bytes = size;
471 /* have a new sized buffer ready to write */
472 return TRUE;
473 }
474 }
475
476 /*****************************************************************************
477 *
478 * void AsnIoPuts(aip)
479 * put the linebuf
480 *
481 *****************************************************************************/
AsnIoPuts(AsnIoPtr aip)482 NLM_EXTERN void AsnIoPuts (AsnIoPtr aip)
483 {
484 if (aip->linepos == 0)
485 return;
486
487 if (! aip->no_newline)
488 {
489 aip->linebuf[aip->linepos] = '\n';
490 aip->offset++;
491 }
492
493 aip->linepos = 0;
494
495 if ((aip->bytes - aip->offset) > (aip->linelength + ASNIO_BUFSIZE_RESERVE)) /* room left */
496 aip->linebuf = (CharPtr)aip->buf + aip->offset;
497 else
498 {
499 AsnIoWriteBlock(aip); /* write it out */
500 aip->linebuf = (CharPtr)aip->buf; /* reset line pointer */
501 }
502
503 if (aip->no_newline)
504 aip->no_newline = FALSE;
505
506 return;
507 }
508
509
510 /*****************************************************************************
511 *
512 * CharPtr AsnIoGets(aip)
513 * equivalent of fgets()
514 * only works on TEXT_IN files
515 * increments aip->linenumber
516 *
517 *****************************************************************************/
AsnIoGets(AsnIoPtr aip)518 NLM_EXTERN CharPtr AsnIoGets (AsnIoPtr aip)
519 {
520 Int2 offset = aip->offset; /* current end of line */
521 Int2 bytes = aip->bytes - offset; /* unread bytes in buffer */
522 CharPtr str = (CharPtr)aip->buf + offset; /* start of next line */
523 Int2 len = 0; /* # of bytes read in line */
524
525 for (;;) {
526 /* no more data in the buffer? */
527 if (bytes <= 0) {
528 /* check if line is longer than the whole block */
529 if (offset == 0 && len == aip->bufsize) {
530 AsnIoErrorMsg(aip, 74, (int)aip->bufsize, aip->linenumber);
531 return 0;
532 }
533
534 /* move data to the very beginning of the buffer, if necessary */
535 if (offset && aip->bytes == aip->bufsize) {
536 if ( len )
537 MemCopy(aip->buf, aip->buf + offset, (size_t)len);
538 offset = 0;
539 str = (CharPtr)aip->buf + len;
540 }
541
542 /* read to the buffer */
543 aip->offset = offset + len;
544 bytes = AsnIoReadBlock(aip);
545 if ( !bytes ) {
546 if ( !len ) {
547 return 0; /* cant read a thing */
548 } else {
549 *str = '\n';
550 break; /* assume EOF and no last newline */
551 }
552 }
553 continue;
554 }
555
556 /* check for EOL, else forward to the next symbol */
557 len++; /* EOL included */
558 if (*str == '\n' || *str == '\r')
559 break; /* EOL */
560 str++;
561 bytes--;
562 } /* for (;;) */
563
564 aip->offset = offset + len;
565 aip->linenumber++;
566 aip->linebuf = (CharPtr)aip->buf + offset;
567 return aip->linebuf;
568 }
569
570
571 /*****************************************************************************
572 *
573 * Int4 AsnIoTell(aip)
574 * gives seek offset in current file or -1 if error
575 *
576 *****************************************************************************/
AsnIoTell(AsnIoPtr aip)577 NLM_EXTERN Int4 LIBCALL AsnIoTell (AsnIoPtr aip)
578 {
579 Int4 offset, bytes;
580
581 if (!(aip->type & ASNIO_FILE))
582 {
583 AsnIoErrorMsg(aip, 75);
584 return 0L;
585 }
586 offset = ftell(aip->fp); /* position after last read */
587 if (aip->type & ASNIO_IN)
588 {
589 bytes = aip->bytes - aip->offset; /* bytes left in buffer */
590 offset -= bytes; /* real position by byte */
591 if (aip->tagsaved) /* binary tags saved? */
592 offset -= aip->used; /* remove that too */
593 }
594 else
595 {
596 offset += aip->offset; /* unflushed stuff in buffer */
597 }
598 return offset;
599 }
600
601
602 /*****************************************************************************
603 *
604 * Int4 AsnIoSeek(aip, pos)
605 * seeks to pos
606 *
607 *****************************************************************************/
AsnIoSeek(AsnIoPtr aip,Int4 pos)608 NLM_EXTERN Int4 LIBCALL AsnIoSeek (AsnIoPtr aip, Int4 pos)
609 {
610 if (! (aip->type & ASNIO_IN))
611 {
612 AsnIoErrorMsg(aip, 76);
613 return 0L;
614 }
615 if (! (aip->type & ASNIO_FILE))
616 {
617 AsnIoErrorMsg(aip, 77);
618 return 0L;
619 }
620 pos = fseek(aip->fp, pos, 0); /* formatted file */
621 AsnIoReset(aip);
622 return pos;
623 }
624
625 /*****************************************************************************
626 *
627 * Int2 AsnIoReadBlock(aip)
628 * returns bytes read
629 *
630 *****************************************************************************/
AsnIoReadBlock(AsnIoPtr aip)631 NLM_EXTERN Int2 AsnIoReadBlock (AsnIoPtr aip)
632 {
633 Int2 bytes, offset, retval;
634
635 if (aip->type & ASNIO_TEXT)
636 {
637 offset = aip->offset;
638 bytes = aip->bufsize - offset;
639 }
640 else
641 {
642 bytes = aip->bufsize;
643 offset = 0;
644 }
645
646 if (aip->readfunc == NULL) /* use standard read */
647 {
648 retval = (Int2) FileRead((VoidPtr)(aip->buf + offset), (size_t)1, (size_t) bytes, aip->fp);
649 }
650 else /* use alternative read function */
651 retval = (* aip->readfunc)(aip->iostruct, (CharPtr)(aip->buf + offset), (Uint2)bytes);
652 if (retval > 0)
653 aip->bytes = retval + offset; /* space available to read */
654 else
655 aip->bytes = offset;
656 aip->offset = 0; /* bytes read */
657 if (retval < 0)
658 {
659 AsnIoErrorMsg(aip, 78, retval);
660 retval = 0; /* callers look for 0 as bad return value */
661 }
662 return retval;
663 }
664
665 /*****************************************************************************
666 *
667 * Int2 AsnIoWriteBlock(aip)
668 * does NOT return bytes written
669 * return bytes available in buffer to write on
670 *
671 *****************************************************************************/
AsnIoWriteBlock(AsnIoPtr aip)672 NLM_EXTERN Int2 AsnIoWriteBlock (AsnIoPtr aip)
673 {
674 Int2 retval, bytes_to_write, offset;
675
676 if (aip->io_failure)
677 return 0;
678 if (aip->used > 2) /* recursion stopper */
679 return 0;
680 aip->used++; /* recursion counter */
681
682 if (aip->type & ASNIO_TEXT)
683 {
684 offset = (Int2)aip->length; /* amount sent on last AsnIoFlush */
685 bytes_to_write = aip->offset - offset;
686 }
687 else
688 {
689 offset = 0;
690 bytes_to_write = aip->offset;
691 }
692
693 if (aip->writefunc == NULL) /* use standard write */
694 {
695 retval = (Int2) FileWrite((VoidPtr)(aip->buf + offset), (size_t)1,
696 (size_t) bytes_to_write, aip->fp);
697 }
698 else /* use alternative write function */
699 retval = (* aip->writefunc)(aip->iostruct, (CharPtr)(aip->buf + offset),
700 (Uint2) bytes_to_write);
701 if (retval != bytes_to_write)
702 {
703 AsnIoErrorMsg(aip, 79, retval, bytes_to_write);
704 aip->io_failure = TRUE;
705 }
706 if (aip->type & ASNIO_TEXT) /* check for full line */
707 {
708 if ((aip->buf[aip->offset - 1] == '\n') || (aip->no_newline))
709 {
710 aip->length = 0;
711 aip->offset = 0; /* write space used */
712 aip->linebuf = (CharPtr)aip->buf;
713 aip->bytes = aip->bufsize; /* free write space */
714 }
715 else
716 {
717 aip->length = aip->offset; /* store flushed section */
718 }
719 }
720 else
721 {
722 aip->bytes = aip->bufsize; /* free write space */
723 aip->offset = 0; /* write space used */
724 }
725 aip->used--; /* warning! each invocation of this function must decrement */
726 return aip->bytes;
727 }
728
729 static char * AsnIoErrStr[109] = {
730 #ifdef WIN16
731
732 "Sorry. Not supported yet",
733 "Cannot start AsnDeBinType() with unknown Type",
734 "tag mismatch on %Fs",
735 "Expected 00 after tag for %Fs",
736 "Tag mismatch on SET/SEQ OF %Fs",
737 "Unable to match element in %Fs.",
738 "element %Fs out of order in SEQUENCE %Fs",
739 "Skipped element %Fs in SEQUENCE %Fs",
740 "AsnDeBinDecr: lenstack[%d] < 0",
741 "type [%Fs]. Unresolved imported type [%Fs]",
742 "type [%Fs]. Unresolved base type [%Fs]",
743 "Unable to read value of %Fs.",
744 "%ld is an invalid value for %Fs.",
745 "Boolean %Fs must be one byte",
746 "Can't allocate %ld bytes for %Fs",
747 "AsnDeBinReal- not encoded as decimal",
748 "NULL value without 0 length for %Fs",
749 "Premature end of file",
750 "End Struct too late in value",
751 "Unable to write value of %Fs.",
752 "AsnEndStruct with nothing on stack.",
753 "AsnEndStruct of %Fs does not match %Fs",
754 "%Fs [%Fs] is not an element of %Fs",
755 "[%Fs] CHOICE may only have one value [%Fs]",
756 "Cannot duplicate element %Fs in SEQ or SET %Fs",
757 "Parent type not struct. %Fs isa=%d",
758 "Input value file must start with Defined Type. line %ld",
759 "Type Reference not found in module. line %ld",
760 "Expected ::= after Type Reference on input. line %ld",
761 "Expected to start with %Fs. line %ld",
762 "Expected comma or } in input value. line %ld",
763 "Expected identifier. line %ld",
764 "Unable to match element in %Fs. line %ld",
765 "element %Fs out of order in SEQUENCE %Fs. line number %ld",
766 "Skipped element %Fs in SEQUENCE %Fs. line %ld",
767 "type [%Fs]. Unresolved imported type [%Fs]. line %ld",
768 "type [%Fs]. Unresolved base type [%Fs]. line %ld",
769 "Expected { line %ld",
770 "Unable to read value of %Fs. line %ld",
771 "Integer value not found for %Fs. line %ld",
772 "Invalid value for %Fs. line %ld",
773 "General defined values not supported yet. %Fs on line %ld",
774 "Invalid value for BOOLEAN %Fs. line %ld",
775 "No \" on string start for %Fs. line %ld",
776 "No \" on string end for %Fs. line %ld",
777 "No \' on OCTET start for %Fs. line %ld",
778 "AsnLexReadOctets on %Fs. line %ld",
779 "No \'H on OCTETs end for %Fs. line %ld",
780 "Uneven number in OCTETS for %Fs. line %ld",
781 "REAL %Fs must start with {. line %ld",
782 "mantissa error on %Fs. line %ld",
783 "comma missing after mantissa on %Fs. line %ld",
784 "base incorrect on %Fs. line %ld",
785 "only base 2 or 10 allowed. %Fs on line %ld",
786 "comma missing after base on %Fs. line %ld",
787 "exponent error on %Fs. line %ld",
788 "no } on %Fs. line %ld",
789 "Expected NULL for %Fs. line %ld",
790 "Can't identify Bit/Hex string line %ld",
791 "Unrecognized token %c. line %ld",
792 "ReadModule: Ref or ident required. line %ld but got %Fs",
793 "No ] on tag. line %ld",
794 "AsnLexTReadType: defined number not supported. line %ld",
795 "No integer tag. line %ld",
796 "Sorry. Subtypes not supported yet. line %ld",
797 "Enumerated type MUST have values. line %ld",
798 "Expected comma around line %ld",
799 "%Fs is an ASN.1 reserved word. line %ld",
800 "object identifier not implemented",
801 "Module: missing %s. line %ld",
802 "Comma out of place. line %ld",
803 "IMPORTS: expected typeref before FROM on line %ld",
804 "IMPORTS: expected Module on line %ld",
805 "Object Indentifier not supported. line %ld",
806 "Input line longer than %d. line %ld",
807 "AsnIoTell on non-FILE",
808 "AsnIoSeek on non-INPUT file",
809 "AsnIoSeek on non-FILE",
810 "Read Error [%d] in AsnIoReadBlock",
811 "AsnIoWriteBlock: too few bytes written [retvalue %d, requested %d]",
812 "No file name given on AsnIoOpen",
813 "Unrecognized AsnIoOpen mode [%Fs]",
814 "Cannot open file [%Fs]",
815 "Cannot open parse tree load file [%Fs]",
816 "[%Fs] should be EXPORTED from module [%Fs]",
817 "Cannot find path to parse tree load files", /* [85] */
818 "Expected identifier for named integer. line %ld",
819 "Missing ( in named integer. line %ld",
820 "Missing ) in named integer. line %ld",
821 "Expected OF on line %ld",
822 "Expected STRING. line %ld",
823 "Invalid token after OF. line %ld",
824 "Syntax error after OBJECT. line %ld",
825 "Sorry. COMPONENTS OF not supported yet. line %ld",
826 "Default for %Fs not supported",
827 "Sorry. Cannot find type def for %Fs to set DEFAULT. line %ld",
828 "IMPORTS: expected Ref line %ld",
829 "EXPORTS line after IMPORTS. line %ld",
830 "%Fs is not a valid Type name. line %ld",
831 "Redefinition of %Fs. line %ld",
832 "Type %Fs was not resolved in module %Fs",
833 "IMPORTED Type %Fs was never referenced in module %Fs",
834 "No IMPORT source for type %Fs in module %Fs",
835 "Did not AsnReadId before AsnReadVal. line %ld" ,
836 "Did not AsnReadVal before AsnReadId. line %ld",
837 "Did not load parse trees for trying to explore them",
838 "Invalid value(s) [%d] in VisibleString [%Fs ...]",
839 "UTF8String encountered where VisibleString expected",
840 "UTF8String replaced by VisibleString"
841
842 #else
843
844 "Sorry. Not supported yet",
845 "Cannot start AsnDeBinType() with unknown Type",
846 "tag mismatch on %s",
847 "Expected 00 after tag for %s",
848 "Tag mismatch on SET/SEQ OF %s",
849 "Unable to match element in %s.",
850 "element %s out of order in SEQUENCE %s",
851 "Skipped element %s in SEQUENCE %s",
852 "AsnDeBinDecr: lenstack[%d] < 0",
853 "type [%s]. Unresolved imported type [%s]",
854 "type [%s]. Unresolved base type [%s]",
855 "Unable to read value of %s.",
856 "%ld is an invalid value for %s.",
857 "Boolean %s must be one byte",
858 "Can't allocate %ld bytes for %s",
859 "AsnDeBinReal- not encoded as decimal",
860 "NULL value without 0 length for %s",
861 "Premature end of file",
862 "End Struct too late in value",
863 "Unable to write value of %s.",
864 "AsnEndStruct with nothing on stack.",
865 "AsnEndStruct of %s does not match %s",
866 "%s [%s] is not an element of %s",
867 "[%s] CHOICE may only have one value [%s]",
868 "Cannot duplicate element %s in SEQ or SET %s",
869 "Parent type not struct. %s isa=%d",
870 "Input value file must start with Defined Type. line %ld",
871 "Type Reference not found in module. line %ld",
872 "Expected ::= after Type Reference on input. line %ld",
873 "Expected to start with %s. line %ld",
874 "Expected comma or } in input value. line %ld",
875 "Expected identifier. line %ld",
876 "Unable to match element in %s. line %ld",
877 "element %s out of order in SEQUENCE %s. line number %ld",
878 "Skipped element %s in SEQUENCE %s. line %ld",
879 "type [%s]. Unresolved imported type [%s]. line %ld",
880 "type [%s]. Unresolved base type [%s]. line %ld",
881 "Expected { line %ld",
882 "Unable to read value of %s. line %ld",
883 "Integer value not found for %s. line %ld",
884 "Invalid value for %s. line %ld",
885 "General defined values not supported yet. %s on line %ld",
886 "Invalid value for BOOLEAN %s. line %ld",
887 "No \" on string start for %s. line %ld",
888 "No \" on string end for %s. line %ld",
889 "No \' on OCTET start for %s. line %ld",
890 "AsnLexReadOctets on %s. line %ld",
891 "No \'H on OCTETs end for %s. line %ld",
892 "Uneven number in OCTETS for %s. line %ld",
893 "REAL %s must start with {. line %ld",
894 "mantissa error on %s. line %ld",
895 "comma missing after mantissa on %s. line %ld",
896 "base incorrect on %s. line %ld",
897 "only base 2 or 10 allowed. %s on line %ld",
898 "comma missing after base on %s. line %ld",
899 "exponent error on %s. line %ld",
900 "no } on %s. line %ld",
901 "Expected NULL for %s. line %ld",
902 "Can't identify Bit/Hex string line %ld",
903 "Unrecognized token %c. line %ld",
904 "ReadModule: Ref or ident required. line %ld but got %s",
905 "No ] on tag. line %ld",
906 "AsnLexTReadType: defined number not supported. line %ld",
907 "No integer tag. line %ld",
908 "Sorry. Subtypes not supported yet. line %ld",
909 "Enumerated type MUST have values. line %ld",
910 "Expected comma around line %ld",
911 "%s is an ASN.1 reserved word. line %ld",
912 "object identifier not implemented",
913 "Module: missing %s. line %ld",
914 "Comma out of place. line %ld",
915 "IMPORTS: expected typeref before FROM on line %ld",
916 "IMPORTS: expected Module on line %ld",
917 "Object Indentifier not supported. line %ld",
918 "Input line longer than %d. line %ld",
919 "AsnIoTell on non-FILE",
920 "AsnIoSeek on non-INPUT file",
921 "AsnIoSeek on non-FILE",
922 "Read Error [%d] in AsnIoReadBlock",
923 "AsnIoWriteBlock: too few bytes written [retvalue %d, requested %d]",
924 "No file name given on AsnIoOpen",
925 "Unrecognized AsnIoOpen mode [%s]",
926 "Cannot open file [%s]",
927 "Cannot open parse tree load file [%s]",
928 "[%s] should be EXPORTED from module [%s]",
929 "Cannot find path to parse tree load files", /* [85] */
930 "Expected identifier for named integer. line %ld",
931 "Missing ( in named integer. line %ld",
932 "Missing ) in named integer. line %ld",
933 "Expected OF on line %ld",
934 "Expected STRING. line %ld",
935 "Invalid token after OF. line %ld",
936 "Syntax error after OBJECT. line %ld",
937 "Sorry. COMPONENTS OF not supported yet. line %ld",
938 "Default for %s not supported",
939 "Sorry. Cannot find type def for %s to set DEFAULT. line %ld",
940 "IMPORTS: expected Ref line %ld",
941 "EXPORTS line after IMPORTS. line %ld",
942 "%s is not a valid Type name. line %ld",
943 "Redefinition of %s. line %ld",
944 "Type %s was not resolved in module %s",
945 "IMPORTED Type %s was never referenced in module %s",
946 "No IMPORT source for type %s in module %s",
947 "Did not AsnReadId before AsnReadVal. line %ld" ,
948 "Did not AsnReadVal before AsnReadId. line %ld",
949 "Did not load parse trees for trying to explore them",
950 "Invalid value(s) [%d] in VisibleString [%s ...]",
951 "UTF8String encountered where VisibleString expected",
952 "UTF8String replaced by VisibleString"
953
954 #endif
955 };
956
957 /**************************************************************************
958 *
959 * AsnErrGetTypeName(name)
960 *
961 **************************************************************************/
AsnErrGetTypeName(CharPtr name)962 NLM_EXTERN CharPtr LIBCALL AsnErrGetTypeName (CharPtr name)
963 {
964 if (name == NULL)
965 return ".E";
966 else
967 return name;
968 }
969
970 /*****************************************************************************
971 *
972 * AsnIoErrorMsg(aip, errcode, args)
973 *
974 *****************************************************************************/
975 #ifdef VAR_ARGS
AsnIoErrorMsg(aip,errcode,va_alist)976 NLM_EXTERN void CDECL AsnIoErrorMsg(aip, errcode, va_alist)
977 AsnIoPtr aip;
978 int errcode;
979 va_dcl
980 #else
981 NLM_EXTERN void CDECL AsnIoErrorMsg(AsnIoPtr aip, int errcode, ...)
982 #endif
983 {
984 CharPtr buf, ptr;
985 ErrSev severity = SEV_FATAL;
986 size_t length = 1024; /* estimated maximum of AsnTypeDumpStack() */
987 CharPtr aip_fname_str = NULL;
988 CharPtr aip_type_str = NULL;
989 CharPtr arg_str = NULL;
990
991 if (aip != NULL) /* set the error flag for asnlib error */
992 {
993 /* non-printing chars in string may not be fatal */
994 if (errcode == 106 && aip->fix_non_print == 0)
995 severity = SEV_ERROR;
996 else if (errcode == 107)
997 severity = SEV_WARNING;
998 else if (errcode == 108)
999 severity = SEV_WARNING;
1000 else
1001 aip->io_failure = TRUE;
1002
1003 if (aip->fname != NULL)
1004 aip_fname_str = aip->fname;
1005
1006 if (aip->type & ASNIO_IN)
1007 aip_type_str = "Input ";
1008 else
1009 {
1010 AsnIoFlush( aip );
1011 aip_type_str = "Output ";
1012 }
1013 }
1014 length += StringLen(aip_fname_str) + StringLen(aip_type_str);
1015
1016 {{
1017 va_list args;
1018 #ifdef VAR_ARGS
1019 va_start(args); /* get the arguments */
1020 #else
1021 va_start(args, errcode);
1022 #endif
1023 arg_str = StringSave( TSPrintfArgs(AsnIoErrStr[errcode], args) );
1024 va_end(args);
1025 }}
1026 length += StringLen(arg_str);
1027
1028 buf = (CharPtr) Malloc(length + 1); *buf = '\0';
1029 StringCat(buf, aip_fname_str);
1030 StringCat(buf, aip_type_str);
1031 ptr = buf + StringLen( buf );
1032
1033 if (aip != NULL)
1034 {
1035 ASSERT (! *ptr);
1036 AsnTypeDumpStack(ptr, aip); /* put in the type stack */
1037 if (ptr[0] && (ptr[0] != ' ' || ptr[1]))
1038 {
1039 ASSERT (ptr[-1] == ' ');
1040 *--ptr = '\n';
1041 while ( *ptr )
1042 ptr++;
1043 *ptr++ = '\n';
1044 *ptr = '\0';
1045 }
1046 }
1047
1048 ASSERT ( StringLen(buf) + StringLen(arg_str) <= length );
1049 StringCpy(ptr, arg_str);
1050 MemFree( arg_str );
1051
1052 if (aip != NULL && aip->error_ret != NULL)
1053 (*aip->error_ret)((Int2)errcode, (CharPtr)buf);
1054 else
1055 ErrPostEx(severity, CTX_NCBIASN1, errcode, "%s", buf);
1056
1057 Free( buf );
1058 return;
1059 }
1060
1061
1062 /*****************************************************************************
1063 *
1064 * void AsnIoSetErrorMsg(aip, ErrorRetType)
1065 * set user error handler
1066 *
1067 *****************************************************************************/
AsnIoSetErrorMsg(AsnIoPtr aip,AsnErrorFunc error_ret)1068 NLM_EXTERN void LIBCALL AsnIoSetErrorMsg (AsnIoPtr aip, AsnErrorFunc error_ret)
1069 {
1070 aip->error_ret = error_ret;
1071 return;
1072 }
1073
1074 /*****************************************************************************
1075 *
1076 * void AsnIoReset(aip)
1077 * resets parse state of aip
1078 * does not reset file or error handler
1079 *
1080 *****************************************************************************/
AsnIoReset(AsnIoPtr aip)1081 NLM_EXTERN void LIBCALL AsnIoReset (AsnIoPtr aip)
1082 {
1083 FILE * fp;
1084 Int1 type, max_type, max_indent, tabsize;
1085 Int2 linelength;
1086 PstackPtr typestack;
1087 BoolPtr first;
1088 ErrorRetType error_ret;
1089 Pointer iostruct;
1090 IoFuncType readfunc, writefunc;
1091 Int2 tbufsize;
1092 BytePtr buf;
1093 CharPtr fname; /* name of file in use */
1094 AsnOptionPtr aop; /* head of options chain */
1095 AsnExpOptPtr aeop; /* exploration options chain */
1096 AsnExpOptStructPtr aeosp;
1097 Uint1 fix_non_print;
1098 Uint1 fix_utf8_in;
1099 Uint1 fix_utf8_out;
1100 Int2 spec_version;
1101
1102 if (aip->type & ASNIO_OUT)
1103 {
1104 if (aip->type & ASNIO_TEXT)
1105 AsnPrintNewLine(aip);
1106 AsnIoFlush(aip); /* clear it */
1107 }
1108
1109 fp = aip->fp; /* things to save */
1110 linelength = aip->linelength;
1111 tabsize = aip->tabsize;
1112 type = aip->type;
1113 max_type = aip->max_type;
1114 max_indent = aip->max_indent;
1115 first = aip->first;
1116 typestack = aip->typestack;
1117 error_ret = aip->error_ret;
1118 iostruct = aip->iostruct;
1119 readfunc = aip->readfunc;
1120 writefunc = aip->writefunc;
1121 tbufsize = aip->bufsize;
1122 buf = aip->buf;
1123 fname = aip->fname;
1124 aop = aip->aop;
1125 aeop = aip->aeop;
1126 aeosp = aip->aeosp;
1127 fix_non_print = aip->fix_non_print;
1128 fix_utf8_in = aip->fix_utf8_in;
1129 fix_utf8_out = aip->fix_utf8_out;
1130 spec_version = aip->spec_version;
1131
1132 MemFill(aip, '\0', sizeof(AsnIo)); /* clear it */
1133 MemFill(buf, '\0', (size_t)tbufsize);
1134
1135 aip->fp = fp; /* replace saved things */
1136 aip->tabsize = tabsize;
1137 aip->linelength = linelength;
1138 aip->type = type;
1139 aip->max_type = max_type;
1140 aip->max_indent = max_indent;
1141 aip->buf = buf;
1142 aip->linebuf = (CharPtr)aip->buf;
1143 aip->first = first;
1144 aip->typestack = typestack;
1145 aip->error_ret = error_ret;
1146 aip->iostruct = iostruct;
1147 aip->readfunc = readfunc;
1148 aip->writefunc = writefunc;
1149 aip->bufsize = tbufsize;
1150 aip->fname = fname;
1151 aip->aop = aop;
1152 aip->aeop = aeop;
1153 aip->aeosp = aeosp;
1154 aip->fix_non_print = fix_non_print;
1155 aip->fix_utf8_in = fix_utf8_in;
1156 aip->fix_utf8_out = fix_utf8_out;
1157 aip->spec_version = spec_version;
1158 /* clear stacks and buffers */
1159 MemFill(aip->typestack, '\0', (size_t)(sizeof(Pstack) * aip->max_type));
1160 MemFill(aip->first, '\0', (size_t)(sizeof(Boolean) * aip->max_indent));
1161 aip->first[0] = TRUE;
1162
1163 if (aip->type & ASNIO_OUT)
1164 aip->bytes = aip->bufsize; /* space to write */
1165
1166 return;
1167 }
1168
1169 /*****************************************************************************
1170 *
1171 * void AsnIoFlush(aip)
1172 *
1173 *****************************************************************************/
AsnIoFlush(AsnIoPtr aip)1174 NLM_EXTERN void LIBCALL AsnIoFlush (AsnIoPtr aip)
1175 {
1176 if (! (aip->type & ASNIO_OUT))
1177 return;
1178
1179 if (aip->offset)
1180 AsnIoWriteBlock(aip);
1181 if (aip->fp && (aip->type & ASNIO_FILE)) /* not a socket, clear buffers */
1182 fflush(aip->fp); /* NB: fflush(NULL) causes ALL streams to flush */
1183 return;
1184 }
1185
1186 /*****************************************************************************
1187 *
1188 * AsnIoMemOpen(mode, buf, size)
1189 *
1190 *****************************************************************************/
1191
AsnIoMemOpen(CharPtr mode,BytePtr buf,Int4 size)1192 NLM_EXTERN AsnIoMemPtr LIBCALL AsnIoMemOpen (CharPtr mode, BytePtr buf, Int4 size) /* size of buffer, or bytes_to_read */
1193 {
1194 Int1 type;
1195 AsnIoMemPtr aimp;
1196
1197 if (! StringCmp(mode, "r"))
1198 type = (ASNIO_IN | ASNIO_TEXT);
1199 else if (! StringCmp(mode, "rb"))
1200 type = (ASNIO_IN | ASNIO_BIN);
1201 else if (! StringCmp(mode, "w"))
1202 type = (ASNIO_OUT | ASNIO_TEXT);
1203 else if (! StringCmp(mode, "wb"))
1204 type = (ASNIO_OUT | ASNIO_BIN);
1205 else if (! StringCmp(mode, "wx"))
1206 {
1207 type = (ASNIO_OUT | ASNIO_TEXT);
1208 type |= ASNIO_XML;
1209 }
1210 else
1211 {
1212 AsnIoErrorMsg(NULL, 81, mode);
1213 return NULL;
1214 }
1215
1216 aimp =(AsnIoMemPtr) MemNew(sizeof(AsnIoMem));
1217 aimp->size = size;
1218 aimp->buf = buf;
1219 aimp->aip = AsnIoNew(type, NULL, (Pointer)aimp, AsnIoMemRead, AsnIoMemWrite);
1220 return aimp;
1221 }
1222
1223 /*****************************************************************************
1224 *
1225 * AsnIoMemClose(aimp)
1226 *
1227 *****************************************************************************/
AsnIoMemClose(AsnIoMemPtr aimp)1228 NLM_EXTERN AsnIoMemPtr LIBCALL AsnIoMemClose (AsnIoMemPtr aimp)
1229 {
1230 if (aimp == NULL)
1231 return NULL;
1232 AsnIoClose(aimp->aip);
1233 return (AsnIoMemPtr) MemFree(aimp);
1234 }
1235
1236 /*****************************************************************************
1237 *
1238 * AsnIoMemWrite(ptr, buf, count)
1239 *
1240 *****************************************************************************/
AsnIoMemWrite(Pointer ptr,CharPtr buf,Uint2 count)1241 NLM_EXTERN Int2 LIBCALL AsnIoMemWrite (Pointer ptr, CharPtr buf, Uint2 count)
1242 {
1243 Int4 bytes;
1244 AsnIoMemPtr aimp;
1245
1246 aimp = (AsnIoMemPtr)ptr;
1247 bytes = MIN((Int4)count, ((aimp->size) - (aimp->count)));
1248 if (! bytes)
1249 return (Int2)(-1);
1250 MemCopy((aimp->buf + aimp->count), buf, (size_t)bytes);
1251 aimp->count += bytes;
1252 return (Int2) bytes;
1253 }
1254
1255 /*****************************************************************************
1256 *
1257 * AsnIoMemRead(ptr, buf, count)
1258 *
1259 *****************************************************************************/
AsnIoMemRead(Pointer ptr,CharPtr buf,Uint2 count)1260 NLM_EXTERN Int2 LIBCALL AsnIoMemRead (Pointer ptr, CharPtr buf, Uint2 count)
1261 {
1262 Int4 bytes;
1263 AsnIoMemPtr aimp;
1264
1265 aimp = (AsnIoMemPtr)ptr;
1266 bytes = MIN((Int4)count, ((aimp->size) - (aimp->count)));
1267 MemCopy(buf, (aimp->buf + aimp->count), (size_t) bytes);
1268 aimp->count += bytes;
1269 return (Int2) bytes;
1270 }
1271
1272 /*****************************************************************************
1273 *
1274 * AsnIoMemReset(aimp, bytes_to_read)
1275 *
1276 *****************************************************************************/
AsnIoMemReset(AsnIoMemPtr aimp,Int4 bytes_to_read)1277 NLM_EXTERN Boolean LIBCALL AsnIoMemReset (AsnIoMemPtr aimp, Int4 bytes_to_read)
1278 {
1279 AsnIoReset(aimp->aip);
1280 aimp->count = 0;
1281 if (aimp->aip->type & ASNIO_IN)
1282 aimp->size = bytes_to_read;
1283 return TRUE;
1284 }
1285
1286 /*****************************************************************************
1287 *
1288 * AsnIoBSOpen(mode, buf, size)
1289 *
1290 *****************************************************************************/
AsnIoBSOpen(CharPtr mode,ByteStorePtr bsp)1291 NLM_EXTERN AsnIoBSPtr LIBCALL AsnIoBSOpen (CharPtr mode, ByteStorePtr bsp)
1292 {
1293 Int1 type;
1294 AsnIoBSPtr aibp;
1295
1296 if ((mode == NULL) || (bsp == NULL))
1297 return NULL;
1298
1299 if (! StringCmp(mode, "r"))
1300 type = (ASNIO_IN | ASNIO_TEXT);
1301 else if (! StringCmp(mode, "rb"))
1302 type = (ASNIO_IN | ASNIO_BIN);
1303 else if (! StringCmp(mode, "w"))
1304 type = (ASNIO_OUT | ASNIO_TEXT);
1305 else if (! StringCmp(mode, "wb"))
1306 type = (ASNIO_OUT | ASNIO_BIN);
1307 else if (! StringCmp(mode, "wx"))
1308 {
1309 type = (ASNIO_OUT | ASNIO_TEXT);
1310 type |= ASNIO_XML;
1311 }
1312 else
1313 {
1314 AsnIoErrorMsg(NULL, 81, mode);
1315 return NULL;
1316 }
1317
1318 aibp = (AsnIoBSPtr) MemNew(sizeof(AsnIoBS));
1319 aibp->bsp = bsp;
1320 BSSeek(bsp, 0, SEEK_SET);
1321 aibp->aip = AsnIoNew(type, NULL, (Pointer)aibp, AsnIoBSRead, AsnIoBSWrite);
1322 if (type & ASNIO_OUT)
1323 AsnIoSetBufsize(aibp->aip, 10000); /* big internal buffer for */
1324 /* big ByteStore blocks */
1325 return aibp;
1326 }
1327
1328 /*****************************************************************************
1329 *
1330 * AsnIoBSClose(aibp)
1331 *
1332 *****************************************************************************/
AsnIoBSClose(AsnIoBSPtr aibp)1333 NLM_EXTERN AsnIoBSPtr LIBCALL AsnIoBSClose (AsnIoBSPtr aibp)
1334 {
1335 if (aibp == NULL)
1336 return NULL;
1337 AsnIoClose(aibp->aip);
1338 return (AsnIoBSPtr) MemFree(aibp);
1339 }
1340
1341 /*****************************************************************************
1342 *
1343 * AsnIoBSWrite(ptr, buf, count)
1344 *
1345 *****************************************************************************/
AsnIoBSWrite(Pointer ptr,CharPtr buf,Uint2 count)1346 NLM_EXTERN Int2 LIBCALL AsnIoBSWrite (Pointer ptr, CharPtr buf, Uint2 count)
1347 {
1348 Int4 bytes;
1349 AsnIoBSPtr aibp;
1350
1351 aibp = (AsnIoBSPtr)ptr;
1352 bytes = BSWrite(aibp->bsp, (Pointer) buf, (Int4) count);
1353 return (Int2) bytes;
1354 }
1355
1356 /*****************************************************************************
1357 *
1358 * AsnIoBSRead(ptr, buf, count)
1359 *
1360 *****************************************************************************/
AsnIoBSRead(Pointer ptr,CharPtr buf,Uint2 count)1361 NLM_EXTERN Int2 LIBCALL AsnIoBSRead (Pointer ptr, CharPtr buf, Uint2 count)
1362 {
1363 Int4 bytes;
1364 AsnIoBSPtr aibp;
1365
1366 aibp = (AsnIoBSPtr)ptr;
1367 bytes = BSRead(aibp->bsp, (Pointer) buf, (Int4) count);
1368 return (Int2) bytes;
1369 }
1370
1371 /*****************************************************************************
1372 *
1373 * AsnIoCopy(from, fromfunc, tofunc)
1374 * Uses the object loader functions to write "from" to a temporary
1375 * file then read a new object and return a pointer to it
1376 *
1377 *****************************************************************************/
AsnIoCopy(Pointer from,AsnReadFunc readfunc,AsnWriteFunc writefunc)1378 NLM_EXTERN Pointer LIBCALL AsnIoCopy (Pointer from, AsnReadFunc readfunc, AsnWriteFunc writefunc)
1379 {
1380 Pointer res;
1381 AsnIoPtr aip;
1382 CharPtr fname;
1383
1384 if ((from == NULL) || (readfunc == NULL) || (writefunc == NULL))
1385 return NULL;
1386
1387 fname = TmpNam(NULL);
1388 aip = AsnIoOpen(fname, "wb");
1389 if (aip == NULL)
1390 return NULL;
1391
1392 if (! (*writefunc)(from, aip, NULL))
1393 {
1394 AsnIoClose(aip);
1395 return NULL;
1396 }
1397
1398 AsnIoClose(aip);
1399
1400 aip = AsnIoOpen(fname, "rb");
1401 res = (*readfunc)(aip, NULL);
1402
1403 AsnIoClose(aip);
1404 FileRemove(fname);
1405
1406 return res;
1407 }
1408
1409 /*****************************************************************************
1410 *
1411 * AsnIoMemCopy(from, fromfunc, tofunc)
1412 * Uses the object loader functions to write "from" to a ByteStore
1413 * then read a new object and return a pointer to it
1414 *
1415 *****************************************************************************/
AsnIoMemCopy(Pointer from,AsnReadFunc readfunc,AsnWriteFunc writefunc)1416 NLM_EXTERN Pointer LIBCALL AsnIoMemCopy (Pointer from, AsnReadFunc readfunc, AsnWriteFunc writefunc)
1417 {
1418 Pointer res;
1419 AsnIoBSPtr aibp;
1420 ByteStorePtr bsp;
1421
1422 if ((from == NULL) || (readfunc == NULL) || (writefunc == NULL))
1423 return NULL;
1424
1425 bsp = BSNew(5000);
1426 aibp = AsnIoBSOpen("wb", bsp);
1427 if (aibp == NULL)
1428 return NULL;
1429
1430 if (! (*writefunc)(from, aibp->aip, NULL))
1431 {
1432 AsnIoBSClose(aibp);
1433 BSFree(bsp);
1434 return NULL;
1435 }
1436
1437 AsnIoBSClose(aibp);
1438
1439 aibp = AsnIoBSOpen("rb", bsp);
1440 res = (*readfunc)(aibp->aip, NULL);
1441
1442 AsnIoBSClose(aibp);
1443 BSFree(bsp);
1444
1445 return res;
1446 }
1447
1448 static Int2 LIBCALLBACK AsnIoCompWrite PROTO((Pointer, CharPtr, Uint2));
1449
1450 /*****************************************************************************
1451 *
1452 * AsnIoMemComp(a, b, writefunc)
1453 * Uses the object loader functions to write "a" to a ByteStore
1454 * then does a byte by byte compare with the AsnIo stream from "b"
1455 * Returns TRUE if identical.
1456 *
1457 *****************************************************************************/
AsnIoMemComp(Pointer a,Pointer b,AsnWriteFunc writefunc)1458 NLM_EXTERN Boolean LIBCALL AsnIoMemComp (Pointer a, Pointer b, AsnWriteFunc writefunc)
1459 {
1460 AsnIoBSPtr aibp;
1461 ByteStorePtr bsp;
1462 Boolean retval = FALSE;
1463 ErrOpts opts;
1464
1465 if ((a == NULL) || (b == NULL) || (writefunc == NULL))
1466 return retval;
1467
1468 bsp = BSNew(5000);
1469 aibp = AsnIoBSOpen("wb", bsp);
1470 if (aibp == NULL)
1471 return retval;
1472
1473 retval = (*writefunc)(a, aibp->aip, NULL);
1474
1475 AsnIoBSClose(aibp);
1476
1477 if (! retval)
1478 {
1479 BSFree(bsp);
1480 return FALSE;
1481 }
1482
1483 aibp = (AsnIoBSPtr) MemNew(sizeof(AsnIoBS));
1484 aibp->bsp = bsp;
1485 BSSeek(bsp, 0, SEEK_SET);
1486 aibp->aip = AsnIoNew((Int1)(ASNIO_OUT | ASNIO_BIN), NULL, (Pointer)aibp, NULL, AsnIoCompWrite);
1487
1488 ErrSaveOptions(&opts); /* save state */
1489 ErrSetOpts(ERR_IGNORE, 0); /* set to ignore an error */
1490
1491 retval = (*writefunc)(b, aibp->aip, NULL);
1492
1493 AsnIoFlush(aibp->aip);
1494 if (aibp->aip->io_failure == TRUE)
1495 retval = FALSE;
1496
1497 AsnIoBSClose(aibp);
1498 BSFree(bsp);
1499
1500 ErrRestoreOptions(&opts); /* reset state */
1501
1502 return retval;
1503 }
1504
1505 /*****************************************************************************
1506 *
1507 * AsnIoCompWrite(ptr, buf, count)
1508 *
1509 *****************************************************************************/
AsnIoCompWrite(Pointer ptr,CharPtr buf,Uint2 count)1510 static Int2 LIBCALLBACK AsnIoCompWrite (Pointer ptr, CharPtr buf, Uint2 count)
1511 {
1512 Uint2 bytes;
1513 Int2 the_byte;
1514 AsnIoBSPtr aibp;
1515
1516 aibp = (AsnIoBSPtr)ptr;
1517 if (aibp->aip->io_failure)
1518 return (Int2) count;
1519
1520 for (bytes = 0; bytes < count; bytes++, buf++)
1521 {
1522 the_byte = BSGetByte(aibp->bsp);
1523 if ((the_byte == EOF) ||
1524 ((Uint1)(*buf) != (Uint1)the_byte))
1525 {
1526 aibp->aip->io_failure = TRUE;
1527 return (Int2) count;
1528 }
1529 }
1530 return (Int2) bytes;
1531 }
1532 /*****************************************************************************
1533 *
1534 * AsnIoHashWrite(ptr, buf, count)
1535 *
1536 *****************************************************************************/
AsnIoHashWrite(Pointer ptr,CharPtr buf,Uint2 count)1537 static Int2 LIBCALL AsnIoHashWrite (Pointer ptr, CharPtr buf, Uint2 count)
1538 {
1539 Uint4Ptr hashPt = (Uint4Ptr) ptr;
1540 Uint4 hash = * hashPt;
1541 Uint2 i;
1542
1543 for (i=0; i < count; i ++){
1544 hash *= (Uint4) 1103515245;
1545 hash += (Uint4) (buf[i]) + (Uint4) 12345;
1546 }
1547 *hashPt = hash;
1548
1549 return (Int2) count;
1550 }
1551 /*****************************************************************************
1552 *
1553 * AsnIoHash(from, tofunc)
1554 * Uses the object loader functions to calculate a hash value
1555 *
1556 *****************************************************************************/
AsnIoHash(Pointer from,AsnWriteFunc writefunc)1557 NLM_EXTERN Uint4 LIBCALL AsnIoHash (Pointer from, AsnWriteFunc writefunc)
1558 {
1559 Uint4 retval = 0;
1560 AsnIoPtr aip;
1561
1562 if ((from == NULL) || (writefunc == NULL))
1563 return retval;
1564
1565
1566 aip = AsnIoNew(ASNIO_OUT | ASNIO_BIN, NULL, (Pointer)&retval,
1567 NULL, AsnIoHashWrite);
1568
1569 if (! (*writefunc)(from, aip, NULL))
1570 AsnIoFlush(aip);
1571
1572 AsnIoClose(aip);
1573 return retval;
1574 }
1575