3ecd59be54c14b8cfc9532d1205e64671a3ced0b
[yaz-moved-to-github.git] / odr / ber_oid.c
1 /*
2  * Copyright (c) 1995, Index Data
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: ber_oid.c,v $
7  * Revision 1.11  2000-01-31 13:15:21  adam
8  * Removed uses of assert(3). Cleanup of ODR. CCL parser update so
9  * that some characters are not surrounded by spaces in resulting term.
10  * ILL-code updates.
11  *
12  * Revision 1.10  1999/11/30 13:47:11  adam
13  * Improved installation. Moved header files to include/yaz.
14  *
15  * Revision 1.9  1995/09/29 17:12:19  quinn
16  * Smallish
17  *
18  * Revision 1.8  1995/09/27  15:02:56  quinn
19  * Modified function heads & prototypes.
20  *
21  * Revision 1.7  1995/05/16  08:50:47  quinn
22  * License, documentation, and memory fixes
23  *
24  * Revision 1.6  1995/04/18  08:15:18  quinn
25  * Added dynamic memory allocation on encoding (whew). Code is now somewhat
26  * neater. We'll make the same change for decoding one day.
27  *
28  * Revision 1.5  1995/03/20  12:18:22  quinn
29  * Fixed bug in ber_oid
30  *
31  * Revision 1.4  1995/03/08  12:12:11  quinn
32  * Added better error checking.
33  *
34  * Revision 1.3  1995/03/01  08:40:56  quinn
35  * Smallish changes.
36  *
37  * Revision 1.2  1995/02/14  20:39:55  quinn
38  * Fixed bugs in completeBER and (serious one in) ber_oid.
39  *
40  * Revision 1.1  1995/02/03  17:04:36  quinn
41  * Initial revision
42  *
43  */
44
45 #include <yaz/odr.h>
46
47 int ber_oidc(ODR o, Odr_oid *p)
48 {
49     int len, lenp, end;
50     int pos, n, res, id;
51     unsigned char octs[8];
52
53     switch (o->direction)
54     {
55         case ODR_DECODE:
56             if ((res = ber_declen(o->bp, &len)) < 1)
57             {
58                 o->error = OPROTO;
59                 return 0;
60             }
61             if (len < 0)
62             {
63                 o->error = OPROTO;
64                 return 0;
65             }
66             o->bp += res;
67             if (len == 0)
68             {
69                 *p = -1;
70                 return 1;
71             }
72             p[0] = *o->bp / 40;
73             if (p[0] > 2)
74                 p[0] = 2;
75             p[1] = *o->bp - p[0] * 40;
76             o->bp++;
77             pos = 2;
78             len--;
79             while (len)
80             {
81                 p[pos] = 0;
82                 do
83                 {
84                     if (!len)
85                     {
86                         o->error = OPROTO;
87                         return 0;
88                     }
89                     p[pos] <<= 7;
90                     p[pos] |= *o->bp & 0X7F;
91                     len--;
92                 }
93                 while (*(o->bp++) & 0X80);
94                 pos++;
95             }
96             p[pos] = -1;
97             return 1;
98         case ODR_ENCODE:
99             /* we'll allow ourselves the quiet luxury of only doing encodings
100                shorter than 127 */
101             lenp = odr_tell(o);
102             if (odr_putc(o, 0) < 0)   /* dummy */
103                 return 0;
104             if (p[0] < 0 && p[1] <= 0)
105             {
106                 o->error = ODATA;
107                 return 0;
108             }
109             for (pos = 1; p[pos] >= 0; pos++)
110             {
111                 id = pos > 1 ? p[pos] : p[0] * 40 + p[1];
112                 n = 0;
113                 do
114                 {
115                     octs[n++] = id & 0X7F;
116                     id >>= 7;
117                 }
118                 while (id);
119                 while (n--)
120                 {
121                     unsigned char p;
122
123                     p = octs[n] | ((n > 0) << 7);
124                     if (odr_putc(o, p) < 0)
125                         return 0;
126                 }
127             }
128             end = odr_tell(o);
129             odr_seek(o, ODR_S_SET, lenp);
130             if (ber_enclen(o, (end - lenp) - 1, 1, 1) != 1)
131             {
132                 o->error = OOTHER;
133                 return 0;
134             }
135             odr_seek(o, ODR_S_END, 0);
136             return 1;
137         default: o->error = OOTHER; return 0;
138     }
139 }