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