Towards 2.1.40.
[yaz-moved-to-github.git] / src / odr_choice.c
1 /*
2  * Copyright (C) 1995-2005, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: odr_choice.c,v 1.6 2005-08-11 14:21:55 adam Exp $
6  */
7
8 /**
9  * \file odr_choice.c
10  * \brief Implements ODR CHOICE codec
11  */
12
13 #if HAVE_CONFIG_H
14 #include <config.h>
15 #endif
16
17 #include "odr-priv.h"
18
19 int odr_choice(ODR o, Odr_arm arm[], void *p, void *whichp,
20                const char *name)
21 {
22     int i, cl = -1, tg, cn, *which = (int *)whichp, bias = o->choice_bias;
23
24     if (o->error)
25         return 0;
26     if (o->direction != ODR_DECODE && !*(char**)p)
27         return 0;
28
29     if (o->direction == ODR_DECODE)
30     {
31         *which = -1;
32         *(char**)p = 0;
33     }
34     o->choice_bias = -1;
35
36     if (o->direction == ODR_PRINT)
37     {
38         if (name)
39         {
40             odr_prname(o, name);
41             odr_printf(o, "choice\n");
42         }
43     }
44     for (i = 0; arm[i].fun; i++)
45     {
46         if (o->direction == ODR_DECODE)
47         {
48             if (bias >= 0 && bias != arm[i].which)
49                 continue;
50             *which = arm[i].which;
51         }
52         else if (*which != arm[i].which)
53             continue;
54
55         if (arm[i].tagmode != ODR_NONE)
56         {
57             if (o->direction == ODR_DECODE && cl < 0)
58             {
59                 if (o->op->stack_top && !odr_constructed_more(o))
60                     return 0;
61                 if (ber_dectag(o->bp, &cl, &tg, &cn, odr_max(o)) <= 0)
62                     return 0;
63             }
64             else if (o->direction != ODR_DECODE)
65             {
66                 cl = arm[i].zclass;
67                 tg = arm[i].tag;
68             }
69             if (tg == arm[i].tag && cl == arm[i].zclass)
70             {
71                 if (arm[i].tagmode == ODR_IMPLICIT)
72                 {
73                     odr_implicit_settag(o, cl, tg);
74                     return (*arm[i].fun)(o, (char **)p, 0, arm[i].name);
75                 }
76                 /* explicit */
77                 if (!odr_constructed_begin(o, p, cl, tg, 0))
78                     return 0;
79                 return (*arm[i].fun)(o, (char **)p, 0, arm[i].name) &&
80                     odr_constructed_end(o);
81             }
82         }
83         else  /* no tagging. Have to poll type */
84         {
85             if ((*arm[i].fun)(o, (char **)p, 1, arm[i].name) && *(char**)p)
86                 return 1;
87         }
88     }
89     return 0;
90 }
91
92 void odr_choice_bias(ODR o, int what)
93 {
94     if (o->enable_bias)
95         o->choice_bias = what;
96 }
97
98 void odr_choice_enable_bias (ODR o, int mode)
99 {
100     o->enable_bias = mode;
101 }
102 /*
103  * Local variables:
104  * c-basic-offset: 4
105  * indent-tabs-mode: nil
106  * End:
107  * vim: shiftwidth=4 tabstop=8 expandtab
108  */
109