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:13 johnmcp
|
---|
8 | * Added the YAZ toolkit source to the packages directory (for z39.50 stuff)
|
---|
9 | *
|
---|
10 | * Revision 1.18 2000/02/29 13:44:55 adam
|
---|
11 | * Check for config.h (currently not generated).
|
---|
12 | *
|
---|
13 | * Revision 1.17 2000/02/28 11:20:06 adam
|
---|
14 | * Using autoconf. New definitions: YAZ_BEGIN_CDECL/YAZ_END_CDECL.
|
---|
15 | *
|
---|
16 | * Revision 1.16 2000/01/31 13:15:21 adam
|
---|
17 | * Removed uses of assert(3). Cleanup of ODR. CCL parser update so
|
---|
18 | * that some characters are not surrounded by spaces in resulting term.
|
---|
19 | * ILL-code updates.
|
---|
20 | *
|
---|
21 | * Revision 1.15 1999/11/30 13:47:11 adam
|
---|
22 | * Improved installation. Moved header files to include/yaz.
|
---|
23 | *
|
---|
24 | * Revision 1.14 1999/05/26 07:49:35 adam
|
---|
25 | * C++ compilation.
|
---|
26 | *
|
---|
27 | * Revision 1.13 1999/01/08 11:23:22 adam
|
---|
28 | * Added const modifier to some of the BER/ODR encoding routines.
|
---|
29 | *
|
---|
30 | * Revision 1.12 1996/07/06 19:58:33 quinn
|
---|
31 | * System headerfiles gathered in yconfig
|
---|
32 | *
|
---|
33 | * Revision 1.11 1995/09/29 17:12:16 quinn
|
---|
34 | * Smallish
|
---|
35 | *
|
---|
36 | * Revision 1.10 1995/09/29 17:01:50 quinn
|
---|
37 | * More Windows work
|
---|
38 | *
|
---|
39 | * Revision 1.9 1995/09/28 10:12:39 quinn
|
---|
40 | * Windows-support changes
|
---|
41 | *
|
---|
42 | * Revision 1.8 1995/09/27 15:02:55 quinn
|
---|
43 | * Modified function heads & prototypes.
|
---|
44 | *
|
---|
45 | * Revision 1.7 1995/05/16 08:50:44 quinn
|
---|
46 | * License, documentation, and memory fixes
|
---|
47 | *
|
---|
48 | * Revision 1.6 1995/04/18 08:15:14 quinn
|
---|
49 | * Added dynamic memory allocation on encoding (whew). Code is now somewhat
|
---|
50 | * neater. We'll make the same change for decoding one day.
|
---|
51 | *
|
---|
52 | * Revision 1.5 1995/03/27 15:01:44 quinn
|
---|
53 | * Added include of sys/types to further portability
|
---|
54 | *
|
---|
55 | * Revision 1.4 1995/03/08 12:12:07 quinn
|
---|
56 | * Added better error checking.
|
---|
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:58 quinn
|
---|
62 | * A damn mess, but now things work, I think.
|
---|
63 | *
|
---|
64 | * Revision 1.1 1995/02/02 16:21:52 quinn
|
---|
65 | * First kick.
|
---|
66 | *
|
---|
67 | */
|
---|
68 | #if HAVE_CONFIG_H
|
---|
69 | #include <config.h>
|
---|
70 | #endif
|
---|
71 |
|
---|
72 | #include <string.h>
|
---|
73 |
|
---|
74 | #ifdef WIN32
|
---|
75 | #include <winsock.h>
|
---|
76 | #else
|
---|
77 | #include <arpa/inet.h>
|
---|
78 | #endif
|
---|
79 |
|
---|
80 | #include <yaz/odr.h>
|
---|
81 |
|
---|
82 | static int ber_encinteger(ODR o, int val);
|
---|
83 | static int ber_decinteger(const unsigned char *buf, int *val);
|
---|
84 |
|
---|
85 | int ber_integer(ODR o, int *val)
|
---|
86 | {
|
---|
87 | int res;
|
---|
88 |
|
---|
89 | switch (o->direction)
|
---|
90 | {
|
---|
91 | case ODR_DECODE:
|
---|
92 | if ((res = ber_decinteger(o->bp, val)) <= 0)
|
---|
93 | {
|
---|
94 | o->error = OPROTO;
|
---|
95 | return 0;
|
---|
96 | }
|
---|
97 | o->bp += res;
|
---|
98 | return 1;
|
---|
99 | case ODR_ENCODE:
|
---|
100 | if ((res = ber_encinteger(o, *val)) < 0)
|
---|
101 | return 0;
|
---|
102 | return 1;
|
---|
103 | case ODR_PRINT: return 1;
|
---|
104 | default: o->error = OOTHER; return 0;
|
---|
105 | }
|
---|
106 | }
|
---|
107 |
|
---|
108 | /*
|
---|
109 | * Returns: number of bytes written or -1 for error (out of bounds).
|
---|
110 | */
|
---|
111 | int ber_encinteger(ODR o, int val)
|
---|
112 | {
|
---|
113 | int lenpos;
|
---|
114 | int a, len;
|
---|
115 | union { int i; unsigned char c[sizeof(int)]; } tmp;
|
---|
116 |
|
---|
117 | lenpos = odr_tell(o);
|
---|
118 | if (odr_putc(o, 0) < 0) /* dummy */
|
---|
119 | return -1;
|
---|
120 | tmp.i = htonl(val); /* ensure that that we're big-endian */
|
---|
121 | for (a = 0; a < (int) sizeof(int) - 1; a++) /* skip superfluous octets */
|
---|
122 | if (!((tmp.c[a] == 0 && !(tmp.c[a+1] & 0X80)) ||
|
---|
123 | (tmp.c[a] == 0XFF && (tmp.c[a+1] & 0X80))))
|
---|
124 | break;
|
---|
125 | len = sizeof(int) - a;
|
---|
126 | if (odr_write(o, (unsigned char*) tmp.c + a, len) < 0)
|
---|
127 | return -1;
|
---|
128 | odr_seek(o, ODR_S_SET, lenpos);
|
---|
129 | if (ber_enclen(o, len, 1, 1) != 1)
|
---|
130 | return -1;
|
---|
131 | odr_seek(o, ODR_S_END, 0);
|
---|
132 | #ifdef ODR_DEBUG
|
---|
133 | fprintf(stderr, "[val=%d]", val);
|
---|
134 | #endif
|
---|
135 | return 0;
|
---|
136 | }
|
---|
137 |
|
---|
138 | /*
|
---|
139 | * Returns: Number of bytes read or 0 if no match, -1 if error.
|
---|
140 | */
|
---|
141 | int ber_decinteger(const unsigned char *buf, int *val)
|
---|
142 | {
|
---|
143 | const unsigned char *b = buf;
|
---|
144 | unsigned char fill;
|
---|
145 | int res, len, remains;
|
---|
146 | union { int i; unsigned char c[sizeof(int)]; } tmp;
|
---|
147 |
|
---|
148 | if ((res = ber_declen(b, &len)) < 0)
|
---|
149 | return -1;
|
---|
150 | if (len > (int) sizeof(int)) /* let's be reasonable, here */
|
---|
151 | return -1;
|
---|
152 | b+= res;
|
---|
153 |
|
---|
154 | remains = sizeof(int) - len;
|
---|
155 | memcpy(tmp.c + remains, b, len);
|
---|
156 | if (*b & 0X80)
|
---|
157 | fill = 0XFF;
|
---|
158 | else
|
---|
159 | fill = 0X00;
|
---|
160 | memset(tmp.c, fill, remains);
|
---|
161 | *val = ntohl(tmp.i);
|
---|
162 |
|
---|
163 | b += len;
|
---|
164 | #ifdef ODR_DEBUG
|
---|
165 | fprintf(stderr, "[val=%d]", *val);
|
---|
166 | #endif
|
---|
167 | return b - buf;
|
---|
168 | }
|
---|