Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 2002 artofcode LLC.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
/* $Id: gsserial.c,v 1.1 2002/08/22 07:12:29 henrys Exp $ */
17
/* some utilities useful for converting objects to serial form */
18
 
19
#include "stdpre.h"
20
#include "gstypes.h"
21
#include "gsserial.h"
22
 
23
 
24
/*
25
 * Procedures for converint between integers and a variable-length,
26
 * little-endian string representation thereof. This scheme uses a
27
 * base-128 format with the high-order bit of each byte used as a
28
 * continuation flag ((b & 0x80) == 0 ==> this is the last byte of the
29
 * current number). See gsserial.h for complete information.
30
 */
31
 
32
/*
33
 * Determine the size of the string representation of an unsigned or
34
 * signed integer.
35
 */
36
int
37
enc_u_size_uint(uint uval)
38
{
39
    int     i = 1;
40
 
41
    while ((uval >>= enc_u_shift) > 0)
42
        ++i;
43
    return i;
44
}
45
 
46
int
47
enc_s_size_int(int ival)
48
{
49
    /* MIN_INT must be handled specially */
50
    if (ival < 0) {
51
        if (ival == enc_s_min_int)
52
            return enc_s_sizew_max;
53
        ival = -ival;
54
    }
55
    return enc_u_sizew((uint)ival << 1);
56
}
57
 
58
/*
59
 * Encode a signed or unsigned integer. The array pointed to by ptr is
60
 * assumed to be large enough. The returned pointer immediately follows
61
 * the encoded number.
62
 */
63
byte *
64
enc_u_put_uint(uint uval, byte * ptr)
65
{
66
    int     tmp_v;
67
 
68
    for (;;) {
69
        tmp_v = uval & (enc_u_lim_1b - 1);
70
        if ((uval >>= enc_u_shift) == 0)
71
            break;
72
        *ptr++ = tmp_v | enc_u_lim_1b;
73
    }
74
    *ptr++ = tmp_v;
75
    return ptr;
76
}
77
 
78
byte *
79
enc_s_put_int(int ival, byte * ptr)
80
{
81
    uint    uval, tmp_v;
82
 
83
    /* MIN_INT must be handled specially */
84
    if (ival < 0 && ival != enc_s_min_int)
85
        uval = (uint)-ival;
86
    else
87
        uval = (uint)ival;
88
 
89
    tmp_v = (uval & enc_s_max_1b) | (ival < 0 ? enc_s_max_1b + 1 : 0);
90
    if (uval > enc_s_max_1b) {
91
        *ptr++ = tmp_v | enc_u_lim_1b;
92
        return enc_u_put_uint(uval >> enc_s_shift0, ptr);
93
    } else {
94
        *ptr++ = tmp_v;
95
        return ptr;
96
    }
97
}
98
 
99
 
100
/*
101
 * Decode an integer string for a signed or unsigned integer. Note that
102
 * two forms of this procedure are provide, to allow both const and non-
103
 * const byte pointers to be handled (the former is far more common).
104
 */
105
const byte *
106
enc_u_get_uint(uint * pval, const byte * ptr)
107
{
108
    uint    uval = 0, tmp_val;
109
    int     shift = 0;
110
 
111
    while (((tmp_val = *ptr++) & enc_u_lim_1b) != 0) {
112
        uval |= (tmp_val & (enc_u_lim_1b - 1)) << shift;
113
        shift += enc_u_shift;
114
    }
115
    *pval = uval | (tmp_val << shift);
116
 
117
    return ptr;
118
}
119
 
120
byte *
121
enc_u_get_uint_nc(uint * pval, byte * ptr)
122
{
123
    const byte *    tmp_ptr = ptr;
124
 
125
    tmp_ptr = enc_u_get_uint(pval, tmp_ptr);
126
    return ptr += tmp_ptr - ptr;
127
}
128
 
129
const byte *
130
enc_s_get_int(int * pval, const byte * ptr)
131
{
132
    int     ival = *ptr++;
133
    bool    neg = false;
134
 
135
    if ((ival & (enc_s_max_1b + 1)) != 0) {
136
        ival ^= enc_s_max_1b + 1;
137
        neg = true;
138
    }
139
    if ((ival & enc_u_lim_1b) != 0) {
140
        uint     tmp_val;
141
 
142
        ival ^= enc_u_lim_1b;
143
        ptr = enc_u_get_uint(&tmp_val, ptr);
144
        ival |= tmp_val << enc_s_shift0;
145
    }
146
    if (neg && ival >= 0)    /* >= check required for enc_s_min_int */
147
        ival = -ival;
148
 
149
    *pval = ival;
150
    return ptr;
151
}
152
 
153
byte *
154
enc_s_get_int_nc(int * pval, byte * ptr)
155
{
156
    const byte *    tmp_ptr = ptr;
157
 
158
    tmp_ptr = enc_s_get_int(pval, tmp_ptr);
159
    return ptr += tmp_ptr - ptr;
160
}
161
 
162
#ifdef UNIT_TEST
163
 
164
#include <stdio.h>
165
#include <string.h>
166
 
167
 
168
/*
169
 * Encoding and decoding of integers is verified using a round-trip process,
170
 * integer ==> string ==> integer. The string size is separately checked to
171
 * verify that it is not too large (it can't be too small if the round-trip
172
 * check works). If an integer x is represented by nbytes, then it must be
173
 * that x >= 1U << (7 * (n - 1)) (unsigned; 1U << (7 * (n - 2) + 6) for
174
 * signed integers; there is no need to check 1-byte encodings).
175
 *
176
 * It is possible to check every value, but this is not necessary. Any
177
 * failures that arise will do so in the vicinty of powers of 2.
178
 */
179
 
180
/* check the length of an encoded string */
181
void
182
check_u_sizew(uint uval, int len)
183
{
184
    if (len != enc_u_sizew(uval))
185
        fprintf( stderr,
186
                 "Size calculation error for (usigned) %u (%d != %d)\n",
187
                 uval,
188
                 len,
189
                 enc_u_sizew(uval) );
190
    if ( len > 1                                                           &&
191
         (len > enc_u_sizew_max  || uval < 1U << (enc_u_shift * (len - 1)))  )
192
        fprintf( stderr, "unsigned encoding too large for %u (%d bytes)\n",
193
                 uval,
194
                 len );
195
}
196
 
197
void
198
check_s_sizew(int ival, int len)
199
{
200
    uint    uval;
201
 
202
    if (len != enc_s_sizew(ival))
203
        fprintf( stderr,
204
                 "Size calculation error for (signed) %d (%d != %d)\n",
205
                 ival,
206
                 len,
207
                 enc_s_sizew(ival) );
208
    if (len <= 1)
209
        return;
210
    if (ival < 0 && ival != enc_s_min_int)
211
        uval = (uint)-ival;
212
    else
213
        uval = (uint)ival;
214
    if ( len > enc_s_sizew_max                                 ||
215
         uval < 1U << (enc_s_shift1 * (len - 2) + enc_s_shift0)  )
216
        fprintf( stderr,
217
                 "signed encoding too large for %d (%d bytes)\n",
218
                 ival,
219
                 len );
220
}
221
 
222
/* check the encode and decode procedures on a value */
223
void
224
check_u(uint uval)
225
{
226
    byte            buff[32];   /* generous size */
227
    byte *          cp0 = buff;
228
    const byte *    cp1 = buff;
229
    byte *          cp2 = buff;
230
    uint            res_val;
231
 
232
    memset(buff, 0, sizeof(buff));
233
    enc_u_putw(uval, cp0);
234
    check_u_sizew(uval, cp0 - buff);
235
    memset(cp0, (uval == 0 ? 0x7f : 0), sizeof(buff) - (cp0 - buff));
236
 
237
    enc_u_getw(res_val, cp1);
238
    if (cp1 != cp0)
239
        fprintf( stderr,
240
                 "encoded length disparity (const) for "
241
                 "(unsigned) %u (%d != %d)\n",
242
                 uval,
243
                 cp0 - buff,
244
                 cp1 - buff );
245
    if (res_val != uval)
246
        fprintf( stderr,
247
                 "decode error (const) for (unsigned) %u (!= %u)\n",
248
                 uval,
249
                 res_val );
250
 
251
    enc_u_getw_nc(res_val, cp2);
252
    if (cp2 != cp0)
253
        fprintf( stderr,
254
                 "encoded length disparity (non-const) for "
255
                 "(unsigned) %u (%d != %d)\n",
256
                 uval,
257
                 cp0 - buff,
258
                 cp1 - buff );
259
    if (res_val != uval)
260
        fprintf( stderr,
261
                 "decode error (non-const) for (unsigned) %u (!= %u)\n",
262
                 uval,
263
                 res_val );
264
}
265
 
266
void
267
check_s(int ival)
268
{
269
    byte            buff[32];   /* generous size */
270
    byte *          cp0 = buff;
271
    const byte *    cp1 = buff;
272
    byte *          cp2 = buff;
273
    int             res_val;
274
 
275
    memset(buff, 0, sizeof(buff));
276
    enc_s_putw(ival, cp0);
277
    check_s_sizew(ival, cp0 - buff);
278
    memset(cp0, (ival == 0 ? 0x7f : 0), sizeof(buff) - (cp0 - buff));
279
 
280
    enc_s_getw(res_val, cp1);
281
    if (cp1 != cp0)
282
        fprintf( stderr,
283
                 "encoded length disparity (const) for "
284
                 "(signed) %d (%d != %d)\n",
285
                 ival,
286
                 cp0 - buff,
287
                 cp1 - buff );
288
    if (res_val != ival)
289
        fprintf( stderr,
290
                 "decode error (const) for (signed) %d (!= %d)\n",
291
                 ival,
292
                 res_val );
293
 
294
    enc_s_getw_nc(res_val, cp2);
295
    if (cp1 != cp0)
296
        fprintf( stderr,
297
                 "encoded length disparity (non-const) for "
298
                 "(signed) %d (%d != %d)\n",
299
                 ival,
300
                 cp0 - buff,
301
                 cp1 - buff );
302
    if (res_val != ival)
303
        fprintf( stderr,
304
                 "decode error (non-const) for (unsigned) %d (!= %d)\n",
305
                 ival,
306
                 res_val );
307
}
308
 
309
/* test the provided value and some surrounding values */
310
void
311
check_u_vals(uint uval)
312
{
313
    uint    diff = 1;
314
 
315
    check_u(uval);
316
    do {
317
        check_u(uval - diff);
318
        check_u(uval + diff);
319
    } while ((diff <<= 1) < uval);
320
}
321
 
322
void
323
check_s_vals(int ival)
324
{
325
    int     diff = 1;
326
 
327
    check_s(ival);
328
    if (ival == enc_s_min_int) {
329
        do {
330
            check_s(ival - diff);
331
            check_s(ival + diff);
332
        } while ((diff <<= 1) != enc_s_min_int);
333
    } else {
334
        int     abs_val = (ival < 0 ? -ival : ival);
335
 
336
        do {
337
            check_s(ival - diff);
338
            check_s(ival + diff);
339
        } while ((diff <<= 1) < abs_val);
340
    }
341
}
342
 
343
 
344
int
345
main(void)
346
{
347
    uint     uval;
348
    int      ival;
349
 
350
    check_u_vals(0);
351
    for (uval = 1; uval != 0; uval <<= 1)
352
        check_u_vals(uval);
353
 
354
    check_s_vals(0);
355
    for (ival = 1; ival != 0; ival <<= 1) {
356
        check_s_vals(ival);
357
        if (ival != enc_s_min_int)
358
            check_s_vals(-ival);
359
    }
360
 
361
    fprintf(stderr, "all done\n");
362
    return 0;
363
}
364
 
365
#endif  /* UNIT_TEST */