1 /* asngen.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: asngen.c
27 *
28 * Author: James Ostell
29 *
30 * Version Creation Date: 3/4/91
31 *
32 * $Revision: 6.3 $
33 *
34 * File Description:
35 * General application interface routines for ASNlib
36 * using these has the advantage that your routine will read binary
37 * and print value messages with no changes
38 * it has the disadvantage that you link both binary and text routines
39 * whether you use them or not
40 *
41 * Modifications:
42 * --------------------------------------------------------------------------
43 * Date Name Description of modification
44 * ------- ---------- -----------------------------------------------------
45 * 3/4/91 Kans Stricter typecasting for GNU C and C++
46 * 04-20-93 Schuler LIBCALL calling convention
47 *
48 * $Log: asngen.c,v $
49 * Revision 6.3 2003/09/15 16:16:33 kans
50 * added AsnWriteEx, AsnTxtWriteEx, and AsnPrintStream
51 *
52 * Revision 6.2 1997/10/29 02:40:40 vakatov
53 * Type castings to pass through the C++ compiler
54 *
55 * Revision 6.1 1997/10/28 15:13:00 epstein
56 * add AsnFindNthPieceOfObject
57 *
58 * Revision 6.0 1997/08/25 18:09:55 madden
59 * Revision changed to 6.0
60 *
61 * Revision 5.1 1996/12/03 21:43:48 vakatov
62 * Adopted for 32-bit MS-Windows DLLs
63 *
64 * Revision 5.0 1996/05/28 14:00:29 ostell
65 * Set to revision 5.0
66 *
67 * Revision 4.1 1996/01/03 22:59:49 ostell
68 * added ExpOptCheck on AsnReadVal()
69 *
70 * Revision 4.0 1995/07/26 13:47:38 ostell
71 * force revision to 4.0
72 *
73 * Revision 2.8 1995/05/15 18:38:28 ostell
74 * added Log line
75 *
76 *
77 * ==========================================================================
78 */
79
80 #include "asnbuild.h"
81
82 /*****************************************************************************
83 *
84 * AsnReadId()
85 * generalized read ident
86 *
87 *****************************************************************************/
AsnReadId(AsnIoPtr aip,AsnModulePtr amp,AsnTypePtr atp)88 NLM_EXTERN AsnTypePtr LIBCALL AsnReadId (AsnIoPtr aip, AsnModulePtr amp, AsnTypePtr atp)
89
90 {
91 if (aip->read_id)
92 AsnIoErrorMsg(aip, 104, aip->linenumber);
93 aip->read_id = TRUE;
94
95 if (aip->type & ASNIO_TEXT)
96 return AsnTxtReadId(aip, amp, atp);
97 else if (aip->type & ASNIO_BIN)
98 return AsnBinReadId(aip, atp);
99
100 return NULL;
101 }
102
103 /*****************************************************************************
104 *
105 * AsnReadVal()
106 * generalized readvalue
107 *
108 *****************************************************************************/
AsnReadVal(AsnIoPtr aip,AsnTypePtr atp,DataValPtr vp)109 NLM_EXTERN Int2 LIBCALL AsnReadVal (AsnIoPtr aip, AsnTypePtr atp, DataValPtr vp)
110
111 {
112 Int2 retval = -1;
113
114 if (! aip->read_id)
115 AsnIoErrorMsg(aip, 103, aip->linenumber);
116 aip->read_id = FALSE;
117
118 if (aip->type & ASNIO_TEXT)
119 retval = AsnTxtReadVal(aip, atp, vp);
120 else if (aip->type & ASNIO_BIN)
121 retval = AsnBinReadVal(aip, atp, vp);
122
123 if (aip->aeop != NULL) /* exploring nodes */
124 AsnCheckExpOpt(aip, atp, vp);
125
126 return retval;
127 }
128
129 /*****************************************************************************
130 *
131 * AsnWrite()
132 * generalized write value
133 *
134 *****************************************************************************/
AsnWrite(AsnIoPtr aip,AsnTypePtr atp,DataValPtr dvp)135 NLM_EXTERN Boolean LIBCALL AsnWrite (AsnIoPtr aip, AsnTypePtr atp, DataValPtr dvp)
136
137 {
138 Boolean retval = FALSE;
139
140 if (aip->aeop != NULL) /* exploring nodes */
141 AsnCheckExpOpt(aip, atp, dvp);
142
143 if (aip->type & ASNIO_TEXT)
144 retval = AsnTxtWrite(aip, atp, dvp);
145 else if (aip->type & ASNIO_BIN)
146 retval = AsnBinWrite(aip, atp, dvp);
147
148 if (aip->io_failure)
149 return FALSE;
150 return retval;
151 }
152
153 /*****************************************************************************
154 *
155 * AsnWriteEx()
156 * specialized write value
157 *
158 *****************************************************************************/
AsnWriteEx(AsnIoPtr aip,AsnTypePtr atp,DataValPtr dvp,AsnStreamStringFunc stream)159 NLM_EXTERN Boolean LIBCALL AsnWriteEx (AsnIoPtr aip, AsnTypePtr atp, DataValPtr dvp, AsnStreamStringFunc stream)
160
161 {
162 Boolean retval = FALSE;
163
164 if (aip->aeop != NULL)
165 AsnCheckExpOpt(aip, atp, dvp);
166
167 if (aip->type & ASNIO_TEXT)
168 retval = AsnTxtWriteEx(aip, atp, dvp, stream);
169 else if (aip->type & ASNIO_BIN)
170 return FALSE;
171
172 if (aip->io_failure)
173 return FALSE;
174 return retval;
175 }
176
177 /*****************************************************************************
178 *
179 * AsnSkipValue(aip, atp)
180 * Assumes that a read id has just been done
181 * Assumes all values to be encountered are linked to atp
182 * will skip values until it returns to the former level
183 * returns TRUE if no errors
184 * ends with a ReadVal()
185 *
186 *****************************************************************************/
AsnSkipValue(AsnIoPtr aip,AsnTypePtr atp)187 NLM_EXTERN Boolean LIBCALL AsnSkipValue (AsnIoPtr aip, AsnTypePtr atp)
188
189 {
190 Int2 level;
191
192 level = AsnGetLevel(aip);
193 if (! AsnReadVal(aip, atp, NULL))
194 return FALSE;
195
196 while (level < AsnGetLevel(aip))
197 {
198 if ((atp = AsnReadId(aip, NULL, atp)) == NULL)
199 return FALSE;
200 if (! AsnReadVal(aip, atp, NULL))
201 return FALSE;
202 }
203 return TRUE;
204 }
205
206 /*****************************************************************************
207 *
208 * AsnOpenStruct(aip, atp, ptr)
209 * write atp as a START_STRUCT
210 *
211 *****************************************************************************/
AsnOpenStruct(AsnIoPtr aip,AsnTypePtr atp,Pointer ptr)212 NLM_EXTERN Boolean LIBCALL AsnOpenStruct (AsnIoPtr aip, AsnTypePtr atp, Pointer ptr)
213
214 {
215 DataVal av;
216 Boolean retval;
217
218 av.intvalue = START_STRUCT;
219 if(aip->aeosp != NULL)
220 aip->aeosp->the_struct = ptr;
221 retval = AsnWrite(aip, atp, &av);
222 if(aip->aeosp != NULL)
223 aip->aeosp->the_struct = NULL;
224 return retval;
225 }
226
227 /*****************************************************************************
228 *
229 * AsnCloseStruct(aip, atp, ptr)
230 * writes an END_STRUCT for atp
231 *
232 *****************************************************************************/
AsnCloseStruct(AsnIoPtr aip,AsnTypePtr atp,Pointer ptr)233 NLM_EXTERN Boolean LIBCALL AsnCloseStruct (AsnIoPtr aip, AsnTypePtr atp, Pointer ptr)
234
235 {
236 DataVal av;
237 Int2 i;
238 Boolean retval;
239
240 i = aip->type_indent;
241 if (! i)
242 {
243 AsnIoErrorMsg(aip, 20 );
244 return FALSE;
245 }
246
247 i--;
248 while ((i) &&
249 (AsnFindBaseIsa(aip->typestack[i].type) == CHOICE_TYPE))
250 i--;
251 if (aip->typestack[i].type != atp)
252 {
253 AsnIoErrorMsg(aip, 21, AsnErrGetTypeName(atp->name),
254 AsnErrGetTypeName(aip->typestack[i].type->name));
255 return FALSE;
256 }
257
258 av.intvalue = END_STRUCT;
259 if(aip->aeosp != NULL)
260 aip->aeosp->the_struct = ptr;
261 retval = AsnWrite(aip, atp, &av);
262 if(aip->aeosp != NULL)
263 aip->aeosp->the_struct = NULL;
264 return retval;
265 }
266
267 /*****************************************************************************
268 *
269 * AsnWriteChoice(aip, atp, the_choice, the_value)
270 *
271 *****************************************************************************/
AsnWriteChoice(AsnIoPtr aip,AsnTypePtr atp,Int2 the_choice,DataValPtr the_value)272 NLM_EXTERN Boolean LIBCALL AsnWriteChoice (AsnIoPtr aip, AsnTypePtr atp, Int2 the_choice, DataValPtr the_value)
273
274 {
275 Boolean retval;
276 DataVal av;
277
278 if (the_value == NULL)
279 {
280 av.ptrvalue = NULL;
281 the_value = &av;
282 }
283 if(aip->aeosp != NULL)
284 aip->aeosp->the_choice = the_choice;
285 retval = AsnWrite(aip, atp, the_value);
286 if(aip->aeosp != NULL)
287 aip->aeosp->the_choice = NO_CHOICE_SET;
288 return retval;
289 }
290
291 /*****************************************************************************
292 *
293 * Int2 AsnGetLevel(aip)
294 * returns current level in parse stack
295 * to traverse a struct (SEQUENCE, SET, SET OF, SEQUENCE OF)
296 * atp = AsnReadId(aip, ...) id for struct
297 * level = AsnGetLevel(aip); record level
298 * AsnReadVal(aip, ...) read open bracket to indent a level
299 * while (AsnGetLevel(aip) != level)
300 * {
301 * AsnReadId()
302 * AsnReadVal()
303 * }
304 * At this point you have read the close bracket for the struct
305 *
306 *****************************************************************************/
AsnGetLevel(AsnIoPtr aip)307 NLM_EXTERN Int2 LIBCALL AsnGetLevel (AsnIoPtr aip)
308
309 {
310 return (Int2)aip->type_indent;
311 }
312
313 /*****************************************************************************
314 *
315 * AsnCheckExpOpt(aip, atp, dvp)
316 * see if atp is a node we are looking for
317 * call user callback if it is
318 *
319 *****************************************************************************/
AsnCheckExpOpt(AsnIoPtr aip,AsnTypePtr atp,DataValPtr dvp)320 NLM_EXTERN void LIBCALL AsnCheckExpOpt (AsnIoPtr aip, AsnTypePtr atp, DataValPtr dvp)
321
322 {
323 AsnExpOptPtr aeop;
324 AsnTypePtr base;
325 Boolean got_one;
326 Int2 i, j, isa, isa_end_struct;
327
328 aeop = aip->aeop;
329 base = AsnFindBaseType(atp);
330 while (aeop != NULL)
331 {
332 got_one = FALSE;
333 if (aeop->numtypes == 1) /* checking one type */
334 {
335 if ((aeop->types[0] == atp) ||
336 (aeop->types[0] == base))
337 {
338 got_one = TRUE;
339 }
340 }
341 else if (aeop->numtypes == 0) /* checking all types */
342 got_one = TRUE;
343 else
344 {
345 if (aeop->types[aeop->numtypes - 1] == atp)
346 {
347 isa = base->type->isa;
348
349 isa_end_struct = 0;
350 if ((isa == SEQ_TYPE) || (isa == SET_TYPE) ||
351 (isa == SEQOF_TYPE) || (isa == SETOF_TYPE))
352 {
353 if (dvp->intvalue != START_STRUCT)
354 isa_end_struct = 1;
355 }
356
357 if ((Int2)aip->type_indent >= (aeop->numtypes - 1 - isa_end_struct))
358 {
359 if (isa_end_struct)
360 i = aip->type_indent - 2;
361 else
362 i = aip->type_indent - 1;
363 j = aeop->numtypes - 2;
364 while ((j > 0) && (i > 0))
365 {
366 if (aip->typestack[i].type == aeop->types[j])
367 {
368 j--; i--;
369 }
370 else
371 break;
372 }
373 if (! j) /* got through it all */
374 {
375 if ((aip->typestack[i].type == aeop->types[0]) ||
376 (AsnFindBaseType(aip->typestack[i].type) ==
377 aeop->types[0]))
378 got_one = TRUE;
379 }
380 }
381 }
382 }
383
384 if (got_one) /* found it */
385 {
386 aip->aeosp->atp = atp;
387 aip->aeosp->dvp = dvp;
388 aip->aeosp->data = aeop->user_data;
389 (* aeop->user_callback)(aip->aeosp);
390 }
391 aeop = aeop->next;
392 }
393 return;
394 }
395
396 /*****************************************************************************
397 *
398 * AsnExpOptNew(aip, path, ptr, func)
399 *
400 *****************************************************************************/
AsnExpOptNew(AsnIoPtr aip,CharPtr path,Pointer ptr,AsnExpOptFunc func)401 NLM_EXTERN AsnExpOptPtr LIBCALL AsnExpOptNew (AsnIoPtr aip, CharPtr path, Pointer ptr, AsnExpOptFunc func) /* user supplied callback */
402
403 {
404 AsnExpOptPtr curr, prev;
405 AsnTypePtr PNTR typeptr = NULL;
406 Int2 typecount = 0;
407
408 if (path != NULL) /* get type array */
409 {
410 typeptr = AsnTypePathFind(NULL, path, &typecount);
411 if (typeptr == NULL) /* path not found */
412 return NULL;
413 }
414 curr = (AsnExpOptPtr) MemNew(sizeof(AsnExpOpt));
415 curr->user_data = ptr;
416 curr->user_callback = func;
417 curr->types = typeptr;
418 curr->numtypes = typecount;
419 if (aip->aeop == NULL) /* first one */
420 {
421 aip->aeop = curr;
422 aip->aeosp = (AsnExpOptStructPtr) MemNew(sizeof(AsnExpOptStruct));
423 aip->aeosp->aip = aip;
424 aip->aeosp->the_choice = NO_CHOICE_SET;
425 }
426 else
427 {
428 prev = aip->aeop;
429 while (prev->next != NULL)
430 prev = prev->next;
431 prev->next = curr;
432 }
433 return curr;
434 }
435
436 /*****************************************************************************
437 *
438 * AsnExpOptFree(aip, aeop)
439 * if aeop == NULL, free them all
440 *
441 *****************************************************************************/
AsnExpOptFree(AsnIoPtr aip,AsnExpOptPtr aeop)442 NLM_EXTERN AsnExpOptPtr LIBCALL AsnExpOptFree (AsnIoPtr aip, AsnExpOptPtr aeop)
443
444 {
445 AsnExpOptPtr curr, next, prev;
446
447 curr = aip->aeop;
448 prev = NULL;
449 while (curr != NULL)
450 {
451 if ((aeop == NULL) || (aeop == curr))
452 {
453 next = curr->next;
454 if (prev != NULL)
455 prev->next = next;
456 else
457 aip->aeop = next;
458 MemFree(curr->types);
459 MemFree(curr);
460 curr = next;
461 }
462 else
463 {
464 prev = curr;
465 curr = curr->next;
466 }
467 }
468 if (prev == NULL) /* nothing left */
469 aip->aeosp = (AsnExpOptStructPtr) MemFree(aip->aeosp); /* free the AsnExpOptStruct */
470 return NULL;
471 }
472
473 /*****************************************************************************
474 *
475 * AsnNullValueMsg(aip, node)
476 * posts an error message when a NULL value is passed to the object
477 * loaders for node.
478 *
479 *****************************************************************************/
AsnNullValueMsg(AsnIoPtr aip,AsnTypePtr node)480 NLM_EXTERN void LIBCALL AsnNullValueMsg (AsnIoPtr aip, AsnTypePtr node)
481
482 {
483 char * tmpbuf;
484 CharPtr str;
485
486 tmpbuf = (char*) malloc(512); /* temp. local buffer for mswindows */
487 str = StringMove(tmpbuf, "NULL value passed to object loader for ");
488 str = AsnTypeDumpStack(str, aip);
489 if (node != NULL)
490 {
491 if (*(str - 1) == '>') /* already read or written */
492 {
493 while (*str != '<')
494 str--;
495 }
496 else
497 {
498 *str = '.';
499 str++;
500 }
501 StringMove(str, node->name);
502 }
503 ErrPost(CTX_NCBIOBJ, 1, tmpbuf);
504 free(tmpbuf);
505 return;
506 }
507
508
509
510 typedef struct {
511 Int4 count;
512 Pointer val;
513 } StructInfo;
514
GetNth(AsnExpOptStructPtr aeosp)515 static void LIBCALLBACK GetNth(AsnExpOptStructPtr aeosp)
516 {
517 StructInfo *sp;
518
519 if (aeosp->dvp->intvalue != START_STRUCT) return;
520 sp = (StructInfo *) aeosp->data;
521 if (sp->count-- == 1)
522 sp->val = (Pointer) aeosp->the_struct;
523 }
524
525 /* Finds the Nth occurrence of any low-level ASN.1 object within a higher
526 level object for which an ASN.1 Write function exists. The string
527 parameter must identify the low-level object for which the search is
528 being performed.
529
530 Note that this function can be used to obtain pieces of an object in an
531 object-oriented "method", rather than using the native method of
532 traversing pointers to fetch the desired piece. However, note that
533 this technique is very inefficient since the entire structure must be
534 traversed to obtain each component. */
535 NLM_EXTERN VoidPtr LIBCALL
AsnFindNthPieceOfObject(AsnWriteFunc wfunc,Pointer datum,CharPtr string,Int4 n)536 AsnFindNthPieceOfObject(AsnWriteFunc wfunc, Pointer datum, CharPtr string, Int4 n)
537 {
538 AsnIoPtr aip;
539 StructInfo si;
540 AsnExpOptPtr aeop;
541
542 aip = AsnIoNullOpen();
543 si.count = n;
544 si.val = NULL;
545 aeop = AsnExpOptNew(aip, string, (Pointer)&si, GetNth);
546 wfunc(datum, aip, NULL);
547 AsnIoClose(aip);
548 return si.val;
549 }
550
551