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.h,v 1.1 2002/08/22 07:12:29 henrys Exp $ */ 17 /* some general structures useful for converting objects to serial form */ 18 19 #ifndef gsserial_INCLUDED 20 # define gsserial_INCLUDED 21 22 /* 23 * A variable-length, little-endian format for encoding (unsigned) 24 * integers. 25 * 26 * This format represents integers is a base-128 form that is quite 27 * compact for parameters whose values are typically small. 28 * 29 * A number x is represented by the string of bytes s[0], ... s[n], 30 * where: 31 * 32 * s[i] & 0x80 == 0x80 for i = 0, ..., n - 1, 33 * s[n] & 0x80 == 0x00 34 * 35 * and 36 * 37 * x == s[0] + (s[1] << 7) + (s[2] << 14) + ... (s[n] << (n * 7)) 38 * 39 * In words, the high-order bit is used as a continue bit; it is off 40 * only for the last byte of the string. The low-order 7 bits of each 41 * byte for the base-128 digit, with the low-order digits preceding 42 * the high-order digits. 43 * 44 * The encoding considers all numbers as unsigned. It may be used with 45 * signed quantities (just change the interpretation), though obviously 46 * it is inefficient with negative numbers. 47 * 48 * This code was originally part of the command list device module. 49 * Though the names used here differ from those used from those used in 50 * that module, they follow the same pattern, which accounts for certain 51 * peculiarities. 52 */ 53 #define enc_u_shift 7 54 #define enc_u_lim_1b (1U << enc_u_shift) 55 #define enc_u_lim_2b (1U << (2 * enc_u_shift)) 56 57 /* determine the encoded size of an (unsigned) integer */ 58 extern int enc_u_size_uint(uint); 59 60 #define enc_u_sizew(w) \ 61 ( (uint)(w) < enc_u_lim_1b \ 62 ? 1 \ 63 : (uint)(w) < enc_u_lim_2b ? 2 : enc_u_size_uint(w) ) 64 65 /* similarly, for a pair of values (frequently used for points) */ 66 #define enc_u_size2w(w1, w2) \ 67 ( ((uint)(w1) | (uint)(w2)) < enc_u_lim_1b \ 68 ? 2 \ 69 : enc_u_size_uint(w1) + enc_u_size_uint(w2) ) 70 71 #define enc_u_sizexy(xy) enc_u_size2w((xy).x, (xy).y) 72 73 /* the maximum size of an encoded uint */ 74 #define enc_u_sizew_max ((8 * sizeof(uint) + enc_u_shift - 1) / enc_u_shift) 75 76 /* encode and decode an unsigned integer; note special handling of const */ 77 extern byte * enc_u_put_uint(uint, byte *); 78 extern const byte * enc_u_get_uint(uint *, const byte *); 79 extern byte * enc_u_get_uint_nc(uint *, byte *); 80 81 #define enc_u_putw(w, p) \ 82 BEGIN \ 83 if ((uint)(w) < enc_u_lim_1b) \ 84 *(p)++ = (byte)(w); \ 85 else if ((uint)(w) < enc_u_lim_2b) { \ 86 *(p)++ = enc_u_lim_1b | ((w) & (enc_u_lim_1b - 1)); \ 87 *(p)++ = (w) >> enc_u_shift; \ 88 } else \ 89 (p) = enc_u_put_uint((w), (p)); \ 90 END 91 92 /* encode a pair of integers; this is often used with points */ 93 #define enc_u_put2w(w1, w2, p) \ 94 BEGIN \ 95 if (((uint)(w1) | (uint)(w2)) < enc_u_lim_1b) { \ 96 *(p)++ = (w1); \ 97 *(p)++ = (w2); \ 98 } else { \ 99 (p) = enc_u_put_uint((w1), (p)); \ 100 (p) = enc_u_put_uint((w2), (p)); \ 101 } \ 102 END 103 104 #define enc_u_putxy(xy, p) enc_u_put2w((xy).x, (xy).y, (p)) 105 106 107 /* decode an unsigned integer */ 108 #define enc_u_getw(w, p) \ 109 BEGIN \ 110 if (((w) = *(p)) >= enc_u_lim_1b) { \ 111 uint tmp_w; \ 112 \ 113 (p) = enc_u_get_uint(&tmp_w, (p)); \ 114 (w) = tmp_w; \ 115 } else \ 116 ++(p); \ 117 END 118 119 #define enc_u_getw_nc(w, p) \ 120 BEGIN \ 121 if (((w) = *(p)) >= enc_u_lim_1b) { \ 122 uint tmp_w; \ 123 \ 124 (p) = enc_u_get_uint_nc(&tmp_w, (p)); \ 125 (w) = tmp_w; \ 126 } else \ 127 ++(p); \ 128 END 129 130 /* decode a pair of unsigned integers; this is often used for points */ 131 #define enc_u_get2w(w1, w2, p) \ 132 BEGIN \ 133 enc_u_getw((w1), (p)); \ 134 enc_u_getw((w2), (p)); \ 135 END 136 137 #define enc_u_get2w_nc(w1, w2, p) \ 138 BEGIN \ 139 enc_u_getw_nc((w1), (p)); \ 140 enc_u_getw_nc((w2), (p)); \ 141 END 142 143 #define enc_u_getxy(xy, p) enc_u_get2w((xy).x, (xy).y, (p)) 144 #define enc_u_getxy_nc(xy, p) enc_u_get2w_nc((xy).x, (xy).y, (p)) 145 146 147 /* 148 * An encoding mechanism similar to that above for signed integers. This 149 * makes use of the next-to-highest order bit of the first byte to encode 150 * the sign of the number. Thus, the number x is represented by the bytes 151 * s[0], ... s[n], where: 152 * 153 * s[i] & 0x80 == 0x80 for i = 0, ..., n - 1, 154 * s[n] & 0x80 == 0x00, 155 * 156 * s[0] & 0x40 == 0x40 if x < 0, 157 * s[0] & 0x40 == 0x00 if x >- 0, 158 * 159 * and 160 * 161 * abs(x) = s[0] + (s[1] << 6) + (s[2] << 13) + ... (s[n] * (n * 7 - 1)) 162 * 163 * This encoding is less efficient than the unsigned encoding for non- 164 * negative numbers but is much more efficient for numbers that might be 165 * negative. 166 * 167 * There are no special 2-value versions of these macros, as it is not 168 * possible to test both values against the limit simultaneously. We do, 169 * however, provide point encoding macros. 170 */ 171 #define enc_s_shift0 6 172 #define enc_s_shift1 (enc_s_shift0 + 1) 173 #define enc_s_max_1b ((1U << enc_s_shift0) - 1) 174 #define enc_s_min_1b (-(int)enc_s_max_1b) 175 #define enc_s_max_2b ((1U << (enc_s_shift0 + enc_s_shift1) - 1)) 176 #define enc_s_min_2b (-enc_s_max_2b) 177 #define enc_s_min_int ((int)(1U << (8 * sizeof(int) - 1))) 178 179 /* determine the encoded size of a signed integer */ 180 extern int enc_s_size_int(int); 181 182 /* the maximum size of encoded integer */ 183 #define enc_s_sizew_max ((8 * sizeof(int)) / enc_s_shift1 + 1) 184 185 #define enc_s_sizew(v) \ 186 ( (v) >= 0 ? enc_u_sizew((uint)(v) << 1) \ 187 : (v) != enc_s_min_int ? enc_u_sizew((uint)-(v) << 1) \ 188 : enc_s_sizew_max ) 189 190 #define enc_s_sizexy(xy) (enc_s_sizew((xy).x) + enc_s_sizew((xy).y)) 191 192 193 /* encode and decode a signed integfer; note special handling of const */ 194 extern byte * enc_s_put_int(int, byte *); 195 extern const byte * enc_s_get_int(int *, const byte *); 196 extern byte * enc_s_get_int_nc(int *, byte *); 197 198 #define enc_s_putw(v, p) \ 199 BEGIN \ 200 if ((int)(v) <= enc_s_max_1b && (int)(v) >= enc_s_min_1b) \ 201 *(p)++ = ((v) & enc_s_max_1b) \ 202 | ((v) < 0 ? (enc_s_max_1b + 1) : 0); \ 203 else \ 204 (p) = enc_s_put_int((v), (p)); \ 205 END 206 207 #define enc_s_putxy(xy, p) \ 208 BEGIN \ 209 enc_s_putw((xy).x, (p)); \ 210 enc_s_putw((xy).y, (p)); \ 211 END 212 213 #define enc_s_getw(v, p) \ 214 BEGIN \ 215 if (((v = *p) & (1U << enc_s_shift1)) != 0) { \ 216 int tmp_v; \ 217 \ 218 (p) = enc_s_get_int(&tmp_v, (p)); \ 219 (v) = tmp_v; \ 220 } else { \ 221 if (((v) & (1U << enc_s_shift0)) != 0) \ 222 (v) = -((v) & enc_s_max_1b); \ 223 ++(p); \ 224 } \ 225 END 226 227 #define enc_s_getw_nc(v, p) \ 228 BEGIN \ 229 if (((v = *p) & (1U << enc_s_shift1)) != 0) { \ 230 int tmp_v; \ 231 \ 232 (p) = enc_s_get_int_nc(&tmp_v, (p)); \ 233 (v) = tmp_v; \ 234 } else { \ 235 if (((v) & (1U << enc_s_shift0)) != 0) \ 236 (v) = -((v) & enc_s_max_1b); \ 237 ++(p); \ 238 } \ 239 END 240 241 #define enc_s_getxy(xy, p) \ 242 BEGIN \ 243 enc_s_getw((xy).x, (p)); \ 244 enc_s_getw((xy).y, (p)); \ 245 END 246 247 #define enc_s_getxy_nc(xy, p) \ 248 BEGIN \ 249 enc_s_getw_nc((xy).x, (p)); \ 250 enc_s_getw_nc((xy).y, (p)); \ 251 END 252 253 #endif /* gsserial_INCLUDED */ 254