Added skeleton for query charset conversion. Bug #977.
[yaz-moved-to-github.git] / src / ber_oid.c
1 /*
2  * Copyright (C) 1995-2007, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: ber_oid.c,v 1.9 2007-01-03 08:42:15 adam Exp $
6  */
7
8 /** 
9  * \file ber_oid.c
10  * \brief Implements BER OID encoding and decoding
11  *
12  * This source file implements BER encoding and decoding of
13  * the OID type.
14  */
15 #if HAVE_CONFIG_H
16 #include <config.h>
17 #endif
18
19 #include "odr-priv.h"
20
21 int ber_oidc(ODR o, Odr_oid *p, int max_oid_size)
22 {
23     int len, lenp, end;
24     int pos, n, res, id;
25     unsigned char octs[8];
26
27     switch (o->direction)
28     {
29     case ODR_DECODE:
30         if ((res = ber_declen(o->bp, &len, odr_max(o))) < 1)
31         {
32             odr_seterror(o, OPROTO, 18);
33             return 0;
34         }
35         if (len < 0)
36         {
37             odr_seterror(o, OPROTO, 19);
38             return 0;
39         }
40         o->bp += res;
41         if (len > odr_max(o))
42         {
43             odr_seterror(o, OPROTO, 20);
44             return 0;
45         }
46         pos = 0;
47         while (len)
48         {
49             int id = 0;
50             do
51             {
52                 if (!len)
53                 {
54                     odr_seterror(o, OPROTO, 21);
55                     return 0;
56                 }
57                 id <<= 7;
58                 id |= *o->bp & 0X7F;
59                 len--;
60             }
61             while (*(o->bp++) & 0X80);
62
63             if (id < 0)
64             {
65                 odr_seterror(o, ODATA, 23);
66                 return 0;
67             }
68             if (pos > 0)
69                 p[pos++] = id;
70             else
71             {
72                 p[0] = id / 40;
73                 if (p[0] > 2)
74                     p[0] = 2;
75                 p[1] = id - p[0] * 40;
76                 pos = 2;
77             }
78             if (pos >= max_oid_size)
79             {
80                 odr_seterror(o, OPROTO, 55);
81                 return 0;
82             }
83         }
84         if (pos < 2 || p[0] < 0 || p[1] < 0)
85         {
86             odr_seterror(o, ODATA, 23);
87             return 0;
88         }
89         p[pos] = -1;
90         return 1;
91     case ODR_ENCODE:
92         /* we'll allow ourselves the quiet luxury of only doing encodings
93            shorter than 127 */
94         lenp = odr_tell(o);
95         if (odr_putc(o, 0) < 0)   /* dummy */
96             return 0;
97         if (p[0] < 0 || p[1] < 0)
98         {
99             odr_seterror(o, ODATA, 23);
100             return 0;
101         }
102         for (pos = 1; p[pos] != -1; pos++)
103         {
104             n = 0;
105             if (pos == 1)
106                 id = p[0]*40 + p[1];
107             else 
108                 id = p[pos];
109             do
110             {
111                 octs[n++] = id & 0X7F;
112                 id >>= 7;
113             }
114             while (id);
115             while (n--)
116             {
117                 unsigned char p;
118
119                 p = octs[n] | ((n > 0) << 7);
120                 if (odr_putc(o, p) < 0)
121                     return 0;
122             }
123         }
124         end = odr_tell(o);
125         odr_seek(o, ODR_S_SET, lenp);
126         if (ber_enclen(o, (end - lenp) - 1, 1, 1) != 1)
127         {
128             odr_seterror(o, OOTHER, 52);
129             return 0;
130         }
131         odr_seek(o, ODR_S_END, 0);
132         return 1;
133     default: 
134         odr_seterror(o, OOTHER, 22);
135         return 0;
136     }
137 }
138 /*
139  * Local variables:
140  * c-basic-offset: 4
141  * indent-tabs-mode: nil
142  * End:
143  * vim: shiftwidth=4 tabstop=8 expandtab
144  */
145