1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
13
/* $Id: gsserial.c 8022 2007-06-05 22:23:38Z giles $ */
14
/* some utilities useful for converting objects to serial form */
22
* Procedures for converint between integers and a variable-length,
23
* little-endian string representation thereof. This scheme uses a
24
* base-128 format with the high-order bit of each byte used as a
25
* continuation flag ((b & 0x80) == 0 ==> this is the last byte of the
26
* current number). See gsserial.h for complete information.
30
* Determine the size of the string representation of an unsigned or
34
enc_u_size_uint(uint uval)
38
while ((uval >>= enc_u_shift) > 0)
44
enc_s_size_int(int ival)
46
/* MIN_INT must be handled specially */
48
if (ival == enc_s_min_int)
49
return enc_s_sizew_max;
52
return enc_u_sizew((uint)ival << 1);
56
* Encode a signed or unsigned integer. The array pointed to by ptr is
57
* assumed to be large enough. The returned pointer immediately follows
61
enc_u_put_uint(uint uval, byte * ptr)
66
tmp_v = uval & (enc_u_lim_1b - 1);
67
if ((uval >>= enc_u_shift) == 0)
69
*ptr++ = tmp_v | enc_u_lim_1b;
76
enc_s_put_int(int ival, byte * ptr)
80
/* MIN_INT must be handled specially */
81
if (ival < 0 && ival != enc_s_min_int)
86
tmp_v = (uval & enc_s_max_1b) | (ival < 0 ? enc_s_max_1b + 1 : 0);
87
if (uval > enc_s_max_1b) {
88
*ptr++ = tmp_v | enc_u_lim_1b;
89
return enc_u_put_uint(uval >> enc_s_shift0, ptr);
98
* Decode an integer string for a signed or unsigned integer. Note that
99
* two forms of this procedure are provide, to allow both const and non-
100
* const byte pointers to be handled (the former is far more common).
103
enc_u_get_uint(uint * pval, const byte * ptr)
105
uint uval = 0, tmp_val;
108
while (((tmp_val = *ptr++) & enc_u_lim_1b) != 0) {
109
uval |= (tmp_val & (enc_u_lim_1b - 1)) << shift;
110
shift += enc_u_shift;
112
*pval = uval | (tmp_val << shift);
118
enc_u_get_uint_nc(uint * pval, byte * ptr)
120
const byte * tmp_ptr = ptr;
122
tmp_ptr = enc_u_get_uint(pval, tmp_ptr);
123
return ptr += tmp_ptr - ptr;
127
enc_s_get_int(int * pval, const byte * ptr)
132
if ((ival & (enc_s_max_1b + 1)) != 0) {
133
ival ^= enc_s_max_1b + 1;
136
if ((ival & enc_u_lim_1b) != 0) {
139
ival ^= enc_u_lim_1b;
140
ptr = enc_u_get_uint(&tmp_val, ptr);
141
ival |= tmp_val << enc_s_shift0;
143
if (neg && ival >= 0) /* >= check required for enc_s_min_int */
151
enc_s_get_int_nc(int * pval, byte * ptr)
153
const byte * tmp_ptr = ptr;
155
tmp_ptr = enc_s_get_int(pval, tmp_ptr);
156
return ptr += tmp_ptr - ptr;
166
* Encoding and decoding of integers is verified using a round-trip process,
167
* integer ==> string ==> integer. The string size is separately checked to
168
* verify that it is not too large (it can't be too small if the round-trip
169
* check works). If an integer x is represented by nbytes, then it must be
170
* that x >= 1U << (7 * (n - 1)) (unsigned; 1U << (7 * (n - 2) + 6) for
171
* signed integers; there is no need to check 1-byte encodings).
173
* It is possible to check every value, but this is not necessary. Any
174
* failures that arise will do so in the vicinty of powers of 2.
177
/* check the length of an encoded string */
179
check_u_sizew(uint uval, int len)
181
if (len != enc_u_sizew(uval))
183
"Size calculation error for (usigned) %u (%d != %d)\n",
188
(len > enc_u_sizew_max || uval < 1U << (enc_u_shift * (len - 1))) )
189
fprintf( stderr, "unsigned encoding too large for %u (%d bytes)\n",
195
check_s_sizew(int ival, int len)
199
if (len != enc_s_sizew(ival))
201
"Size calculation error for (signed) %d (%d != %d)\n",
207
if (ival < 0 && ival != enc_s_min_int)
211
if ( len > enc_s_sizew_max ||
212
uval < 1U << (enc_s_shift1 * (len - 2) + enc_s_shift0) )
214
"signed encoding too large for %d (%d bytes)\n",
219
/* check the encode and decode procedures on a value */
223
byte buff[32]; /* generous size */
225
const byte * cp1 = buff;
229
memset(buff, 0, sizeof(buff));
230
enc_u_putw(uval, cp0);
231
check_u_sizew(uval, cp0 - buff);
232
memset(cp0, (uval == 0 ? 0x7f : 0), sizeof(buff) - (cp0 - buff));
234
enc_u_getw(res_val, cp1);
237
"encoded length disparity (const) for "
238
"(unsigned) %u (%d != %d)\n",
244
"decode error (const) for (unsigned) %u (!= %u)\n",
248
enc_u_getw_nc(res_val, cp2);
251
"encoded length disparity (non-const) for "
252
"(unsigned) %u (%d != %d)\n",
258
"decode error (non-const) for (unsigned) %u (!= %u)\n",
266
byte buff[32]; /* generous size */
268
const byte * cp1 = buff;
272
memset(buff, 0, sizeof(buff));
273
enc_s_putw(ival, cp0);
274
check_s_sizew(ival, cp0 - buff);
275
memset(cp0, (ival == 0 ? 0x7f : 0), sizeof(buff) - (cp0 - buff));
277
enc_s_getw(res_val, cp1);
280
"encoded length disparity (const) for "
281
"(signed) %d (%d != %d)\n",
287
"decode error (const) for (signed) %d (!= %d)\n",
291
enc_s_getw_nc(res_val, cp2);
294
"encoded length disparity (non-const) for "
295
"(signed) %d (%d != %d)\n",
301
"decode error (non-const) for (unsigned) %d (!= %d)\n",
306
/* test the provided value and some surrounding values */
308
check_u_vals(uint uval)
314
check_u(uval - diff);
315
check_u(uval + diff);
316
} while ((diff <<= 1) < uval);
320
check_s_vals(int ival)
325
if (ival == enc_s_min_int) {
327
check_s(ival - diff);
328
check_s(ival + diff);
329
} while ((diff <<= 1) != enc_s_min_int);
331
int abs_val = (ival < 0 ? -ival : ival);
334
check_s(ival - diff);
335
check_s(ival + diff);
336
} while ((diff <<= 1) < abs_val);
348
for (uval = 1; uval != 0; uval <<= 1)
352
for (ival = 1; ival != 0; ival <<= 1) {
354
if (ival != enc_s_min_int)
358
fprintf(stderr, "all done\n");
362
#endif /* UNIT_TEST */