source: trunk/gsdl/packages/yaz/odr/ber_tag.c@ 1343

Last change on this file since 1343 was 1343, checked in by johnmcp, 24 years ago

Added the YAZ toolkit source to the packages directory (for z39.50 stuff)

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