Improved installation. Moved header files to include/yaz.
[yaz-moved-to-github.git] / odr / odr_choice.c
1 /*
2  * Copyright (c) 1995-1999, Index Data
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: odr_choice.c,v $
7  * Revision 1.17  1999-11-30 13:47:11  adam
8  * Improved installation. Moved header files to include/yaz.
9  *
10  * Revision 1.16  1999/04/20 09:56:48  adam
11  * Added 'name' paramter to encoder/decoder routines (typedef Odr_fun).
12  * Modified all encoders/decoders to reflect this change.
13  *
14  * Revision 1.15  1998/02/11 11:53:34  adam
15  * Changed code so that it compiles as C++.
16  *
17  * Revision 1.14  1997/05/14 06:53:57  adam
18  * C++ support.
19  *
20  * Revision 1.13  1997/04/30 08:52:10  quinn
21  * Null
22  *
23  * Revision 1.12  1996/10/08  12:58:17  adam
24  * New ODR function, odr_choice_enable_bias, to control behaviour of
25  * odr_choice_bias.
26  *
27  * Revision 1.11  1995/09/29  17:12:23  quinn
28  * Smallish
29  *
30  * Revision 1.10  1995/09/27  15:02:58  quinn
31  * Modified function heads & prototypes.
32  *
33  * Revision 1.9  1995/08/15  12:00:23  quinn
34  * Updated External
35  *
36  * Revision 1.8  1995/06/19  17:01:51  quinn
37  * This should bring us in sync with the version distributed as 1.0b
38  *
39  * Revision 1.7  1995/06/19  13:06:50  quinn
40  * Fixed simple bug in the code to handle untagged choice elements.
41  *
42  * Revision 1.6  1995/05/16  08:50:53  quinn
43  * License, documentation, and memory fixes
44  *
45  * Revision 1.5  1995/03/18  12:16:31  quinn
46  * Minor changes.
47  *
48  * Revision 1.4  1995/03/14  16:59:38  quinn
49  * Added odr_constructed_more check
50  *
51  * Revision 1.3  1995/03/08  12:12:22  quinn
52  * Added better error checking.
53  *
54  * Revision 1.2  1995/02/09  15:51:48  quinn
55  * Works better now.
56  *
57  * Revision 1.1  1995/02/07  17:52:59  quinn
58  * A damn mess, but now things work, I think.
59  *
60  */
61
62 #include <yaz/odr.h>
63
64 int odr_choice(ODR o, Odr_arm arm[], void *p, void *whichp,
65                const char *name)
66 {
67     int i, cl = -1, tg, cn, *which = (int *)whichp, bias = o->choice_bias;
68
69     if (o->error)
70         return 0;
71     if (o->direction != ODR_DECODE && !*(char**)p)
72         return 0;
73     o->choice_bias = -1;
74
75     if (o->direction == ODR_PRINT)
76     {
77         if (name)
78         {
79             odr_prname(o, name);
80             fprintf (o->print, "choice\n");
81         }
82     }
83     for (i = 0; arm[i].fun; i++)
84     {
85         if (o->direction == ODR_DECODE)
86         {
87             if (bias >= 0 && bias != arm[i].which)
88                 continue;
89             *which = arm[i].which;
90         }
91         else if (*which != arm[i].which)
92             continue;
93
94         if (arm[i].tagmode != ODR_NONE)
95         {
96             if (o->direction == ODR_DECODE && cl < 0)
97             {
98                 if (o->stackp > -1 && !odr_constructed_more(o))
99                     return 0;
100                 if (ber_dectag(o->bp, &cl, &tg, &cn) <= 0)
101                     return 0;
102             }
103             else if (o->direction != ODR_DECODE)
104             {
105                 cl = arm[i].zclass;
106                 tg = arm[i].tag;
107             }
108             if (tg == arm[i].tag && cl == arm[i].zclass)
109             {
110                 if (arm[i].tagmode == ODR_IMPLICIT)
111                 {
112                     odr_implicit_settag(o, cl, tg);
113                     return (*arm[i].fun)(o, (char **)p, 0, arm[i].name);
114                 }
115                 /* explicit */
116                 if (!odr_constructed_begin(o, p, cl, tg, 0))
117                     return 0;
118                 return (*arm[i].fun)(o, (char **)p, 0, arm[i].name) &&
119                     odr_constructed_end(o);
120             }
121         }
122         else  /* no tagging. Have to poll type */
123         {
124             if ((*arm[i].fun)(o, (char **)p, 1, arm[i].name) && *(char**)p)
125                 return 1;
126         }
127     }
128     *which = -1;
129     *(char*)p = 0;
130     return 0;
131 }
132
133 void odr_choice_bias(ODR o, int what)
134 {
135     if (o->enable_bias)
136         o->choice_bias = what;
137 }
138
139 void odr_choice_enable_bias (ODR o, int mode)
140 {
141     o->enable_bias = mode;
142 }