gsserial.c 9.3 KB

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