Added dynamic memory allocation on encoding (whew). Code is now somewhat
[yaz-moved-to-github.git] / odr / ber_oid.c
1 /*
2  * Copyright (C) 1994, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: ber_oid.c,v $
7  * Revision 1.6  1995-04-18 08:15:18  quinn
8  * Added dynamic memory allocation on encoding (whew). Code is now somewhat
9  * neater. We'll make the same change for decoding one day.
10  *
11  * Revision 1.5  1995/03/20  12:18:22  quinn
12  * Fixed bug in ber_oid
13  *
14  * Revision 1.4  1995/03/08  12:12:11  quinn
15  * Added better error checking.
16  *
17  * Revision 1.3  1995/03/01  08:40:56  quinn
18  * Smallish changes.
19  *
20  * Revision 1.2  1995/02/14  20:39:55  quinn
21  * Fixed bugs in completeBER and (serious one in) ber_oid.
22  *
23  * Revision 1.1  1995/02/03  17:04:36  quinn
24  * Initial revision
25  *
26  */
27
28 #include <odr.h>
29
30 int ber_oidc(ODR o, Odr_oid *p)
31 {
32     int len, lenp, end;
33     int pos, n, res, id;
34     unsigned char octs[8];
35
36     switch (o->direction)
37     {
38         case ODR_DECODE:
39             if ((res = ber_declen(o->bp, &len)) < 1)
40             {
41                 o->error = OPROTO;
42                 return 0;
43             }
44             if (len < 0)
45             {
46                 o->error = OPROTO;
47                 return 0;
48             }
49             o->bp += res;
50             o->left -= res;
51             if (len == 0)
52             {
53                 *p = -1;
54                 return 1;
55             }
56             p[0] = *o->bp / 40;
57             if (p[0] > 2)
58                 p[0] = 2;
59             p[1] = *o->bp - p[0] * 40;
60             o->bp++;
61             o->left--;
62             pos = 2;
63             len--;
64             while (len)
65             {
66                 p[pos] = 0;
67                 do
68                 {
69                     if (!len)
70                     {
71                         o->error = OPROTO;
72                         return 0;
73                     }
74                     p[pos] <<= 7;
75                     p[pos] |= *o->bp & 0X7F;
76                     len--;
77                     o->left--;
78                 }
79                 while (*(o->bp++) & 0X80);
80                 pos++;
81             }
82             p[pos] = -1;
83             return 1;
84         case ODR_ENCODE:
85             /* we'll allow ourselves the quiet luxury of only doing encodings
86                shorter than 127 */
87             lenp = odr_tell(o);
88             if (odr_putc(o, 0) < 0)   /* dummy */
89                 return 0;
90             if (p[0] < 0 && p[1] <= 0)
91             {
92                 o->error = ODATA;
93                 return 0;
94             }
95             for (pos = 1; p[pos] >= 0; pos++)
96             {
97                 id = pos > 1 ? p[pos] : p[0] * 40 + p[1];
98                 n = 0;
99                 do
100                 {
101                     octs[n++] = id & 0X7F;
102                     id >>= 7;
103                 }
104                 while (id);
105                 while (n--)
106                 {
107                     unsigned char p;
108
109                     p = octs[n] | ((n > 0) << 7);
110                     if (odr_putc(o, p) < 0)
111                         return 0;
112                 }
113             }
114             end = odr_tell(o);
115             odr_seek(o, ODR_S_SET, lenp);
116             if (ber_enclen(o, (end - lenp) - 1, 1, 1) != 1)
117             {
118                 o->error = OOTHER;
119                 return 0;
120             }
121             odr_seek(o, ODR_S_END, 0);
122             return 1;
123         default: o->error = OOTHER; return 0;
124     }
125 }