Renamed logf function to yaz_log. Removed VC++ project files.
[yaz-moved-to-github.git] / odr / ber_tag.c
1 /*
2  * Copyright (c) 1995-1999, Index Data
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: ber_tag.c,v $
7  * Revision 1.19  1999-01-08 11:23:25  adam
8  * Added const modifier to some of the BER/ODR encoding routines.
9  *
10  * Revision 1.18  1998/02/11 11:53:34  adam
11  * Changed code so that it compiles as C++.
12  *
13  * Revision 1.17  1997/09/30 09:33:10  adam
14  * Minor changes - removed indentation of ifdef.
15  *
16  * Revision 1.16  1997/09/17 12:10:33  adam
17  * YAZ version 1.4.
18  *
19  * Revision 1.15  1997/09/01 08:51:06  adam
20  * New windows NT/95 port using MSV5.0. Had to avoid a few static
21  * variables used in function ber_tag. These are now part of the
22  * ODR structure.
23  *
24  * Revision 1.14  1997/05/14 06:53:56  adam
25  * C++ support.
26  *
27  * Revision 1.13  1995/09/29 17:12:21  quinn
28  * Smallish
29  *
30  * Revision 1.12  1995/09/27  15:02:57  quinn
31  * Modified function heads & prototypes.
32  *
33  * Revision 1.11  1995/05/16  08:50:48  quinn
34  * License, documentation, and memory fixes
35  *
36  * Revision 1.10  1995/04/18  08:15:18  quinn
37  * Added dynamic memory allocation on encoding (whew). Code is now somewhat
38  * neater. We'll make the same change for decoding one day.
39  *
40  * Revision 1.9  1995/03/15  08:37:18  quinn
41  * Fixed protocol bugs.
42  *
43  * Revision 1.8  1995/03/10  11:44:40  quinn
44  * Fixed serious stack-bug in odr_cons_begin
45  *
46  * Revision 1.7  1995/03/08  12:12:13  quinn
47  * Added better error checking.
48  *
49  * Revision 1.6  1995/02/14  11:54:33  quinn
50  * Adjustments.
51  *
52  * Revision 1.5  1995/02/10  18:57:24  quinn
53  * More in the way of error-checking.
54  *
55  * Revision 1.4  1995/02/10  15:55:28  quinn
56  * Bug fixes, mostly.
57  *
58  * Revision 1.3  1995/02/09  15:51:46  quinn
59  * Works better now.
60  *
61  * Revision 1.2  1995/02/07  17:52:59  quinn
62  * A damn mess, but now things work, I think.
63  *
64  * Revision 1.1  1995/02/02  16:21:53  quinn
65  * First kick.
66  *
67  */
68
69 #include <stdio.h>
70 #include <odr.h>
71
72 /* ber_tag
73  * On encoding:
74  *      if  p: write tag. return 1 (success) or -1 (error).
75  *      if !p: return 0.
76  * On decoding:
77  *      if tag && zclass match up, advance pointer and return 1. set cons.
78  *      else leave pointer unchanged. Return 0.
79  *
80  * Should perhaps be odr_tag?
81  */
82 int ber_tag(ODR o, void *p, int zclass, int tag, int *constructed, int opt)
83 {
84     Odr_ber_tag *odr_ber_tag = &o->odr_ber_tag;
85     int rd;
86     char **pp = (char **)p;
87
88     if (o->direction == ODR_DECODE)
89         *pp = 0;
90     o->t_class = -1;
91     if (o->stackp < 0)
92     {
93         odr_seek(o, ODR_S_SET, 0);
94         o->ecb.top = 0;
95         o->bp = o->buf;
96         odr_ber_tag->lclass = -1;
97     }
98     switch (o->direction)
99     {
100         case ODR_ENCODE:
101                 if (!*pp)
102                 {
103                     if (!opt)
104                         o->error = OREQUIRED;
105                     return 0;
106                 }
107                 if ((rd = ber_enctag(o, zclass, tag, *constructed)) < 0)
108                     return -1;
109 #ifdef ODR_DEBUG
110             fprintf(stderr, "\n[class=%d,tag=%d,cons=%d,stackp=%d]", zclass, tag,
111                         *constructed, o->stackp);
112 #endif
113                 return 1;
114
115         case ODR_DECODE:
116                 if (o->stackp > -1 && !odr_constructed_more(o))
117             {
118                     if (!opt)
119                             o->error = OREQUIRED;
120                     return 0;
121                 }
122                 if (odr_ber_tag->lclass < 0)
123                 {
124                     if ((odr_ber_tag->br = ber_dectag(o->bp, &odr_ber_tag->lclass,
125                                      &odr_ber_tag->ltag, &odr_ber_tag->lcons)) <= 0)
126                 {
127                     o->error = OPROTO;
128                             return 0;
129                 }
130 #ifdef ODR_DEBUG
131                     fprintf(stderr,
132                             "\n[class=%d,tag=%d,cons=%d,stackp=%d]",
133                             odr_ber_tag->lclass, odr_ber_tag->ltag,
134                             odr_ber_tag->lcons, o->stackp);
135 #endif
136                 }
137                 if (zclass == odr_ber_tag->lclass && tag == odr_ber_tag->ltag)
138                 {
139                     o->bp += odr_ber_tag->br;
140                     o->left -= odr_ber_tag->br;
141                     *constructed = odr_ber_tag->lcons;
142                     odr_ber_tag->lclass = -1;
143                     return 1;
144                 }
145                 else
146                 {
147                     if (!opt)
148                             o->error = OREQUIRED;
149                     return 0;
150                 }
151         case ODR_PRINT:
152                     if (!*pp && !opt)
153                         o->error = OREQUIRED;
154                     return *pp != 0;
155         default:
156             o->error = OOTHER;
157             return 0;
158     }
159 }
160
161 /* ber_enctag
162  * BER-encode a zclass/tag/constructed package (identifier octets). Return
163  * number of bytes encoded, or -1 if out of bounds.
164  */
165 int ber_enctag(ODR o, int zclass, int tag, int constructed)
166 {
167     int cons = (constructed ? 1 : 0), n = 0;
168     unsigned char octs[sizeof(int)], b;
169
170     b = (zclass << 6) & 0XC0;
171     b |= (cons << 5) & 0X20;
172     if (tag <= 30)
173     {
174         b |= tag & 0X1F;
175         if (odr_putc(o, b) < 0)
176             return -1;
177         return 1;
178     }
179     else
180     {
181         b |= 0X1F;
182         if (odr_putc(o, b) < 0)
183             return -1;
184         do
185         {
186             octs[n++] = tag & 0X7F;
187             tag >>= 7;
188         }
189         while (tag);
190         while (n--)
191         {
192             unsigned char oo;
193
194             oo = octs[n] | ((n > 0) << 7);
195             if (odr_putc(o, oo) < 0)
196                 return -1;
197         }
198         return 0;
199     }
200 }
201
202 /* ber_dectag
203  * Decode BER identifier octets. Return number of bytes read or -1 for error.
204  */
205 int ber_dectag(const unsigned char *buf, int *zclass, int *tag, int *constructed)
206 {
207     const unsigned char *b = buf;
208
209     *zclass = *b >> 6;
210     *constructed = (*b >> 5) & 0X01;
211     if ((*tag = *b & 0x1F) <= 30)
212         return 1;
213     b++;
214     *tag = 0;
215     do
216     {
217         *tag <<= 7;
218         *tag |= *b & 0X7F;
219         if (b - buf >= 5) /* Precaution */
220             return -1;
221     }
222     while (*(b++) & 0X80);
223     return b - buf;
224 }