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