1 /* Copyright (C) 1990, 1996, 1998, 1999 Aladdin Enterprises. 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
17 /* $Id: ibnum.c,v 1.8 2004/08/04 19:36:12 stefan Exp $ */
18 /* Level 2 encoded number reading utilities for Ghostscript */
19 #include "math_.h"
20 #include "memory_.h"
21 #include "ghost.h"
22 #include "ierrors.h"
23 #include "stream.h"
24 #include "ibnum.h"
25 #include "imemory.h" /* for iutil.h */
26 #include "iutil.h"
27
28 /* Define the number of bytes for a given format of encoded number. */
29 const byte enc_num_bytes[] = {
30 enc_num_bytes_values
31 };
32
33 /* ------ Encoded number reading ------ */
34
35 /* Set up to read from an encoded number array/string. */
36 /* Return <0 for error, or a number format. */
37 int
num_array_format(const ref * op)38 num_array_format(const ref * op)
39 {
40 switch (r_type(op)) {
41 case t_string:
42 {
43 /* Check that this is a legitimate encoded number string. */
44 const byte *bp = op->value.bytes;
45 int format;
46
47 if (r_size(op) < 4 || bp[0] != bt_num_array_value)
48 return_error(e_rangecheck);
49 format = bp[1];
50 if (!num_is_valid(format) ||
51 sdecodeshort(bp + 2, format) !=
52 (r_size(op) - 4) / encoded_number_bytes(format)
53 )
54 return_error(e_rangecheck);
55 return format;
56 }
57 case t_array:
58 case t_mixedarray:
59 case t_shortarray:
60 return num_array;
61 default:
62 return_error(e_typecheck);
63 }
64 }
65
66 /* Get the number of elements in an encoded number array/string. */
67 uint
num_array_size(const ref * op,int format)68 num_array_size(const ref * op, int format)
69 {
70 return (format == num_array ? r_size(op) :
71 (r_size(op) - 4) / encoded_number_bytes(format));
72 }
73
74 /* Get an encoded number from an array/string according to the given format. */
75 /* Put the value in np->value.{intval,realval}. */
76 /* Return t_int if integer, t_real if real, t_null if end of stream, */
77 /* or an error if the format is invalid. */
78 int
num_array_get(const gs_memory_t * mem,const ref * op,int format,uint index,ref * np)79 num_array_get(const gs_memory_t *mem, const ref * op, int format, uint index, ref * np)
80 {
81 if (format == num_array) {
82 int code = array_get(mem, op, (long)index, np);
83
84 if (code < 0)
85 return t_null;
86 switch (r_type(np)) {
87 case t_integer:
88 return t_integer;
89 case t_real:
90 return t_real;
91 default:
92 return_error(e_rangecheck);
93 }
94 } else {
95 uint nbytes = encoded_number_bytes(format);
96
97 if (index >= (r_size(op) - 4) / nbytes)
98 return t_null;
99 return sdecode_number(op->value.bytes + 4 + index * nbytes,
100 format, np);
101 }
102 }
103
104 /* Internal routine to decode a number in a given format. */
105 /* Same returns as sget_encoded_number. */
106 static const double binary_scale[32] = {
107 #define EXPN2(n) (0.5 / (1L << (n-1)))
108 1.0, EXPN2(1), EXPN2(2), EXPN2(3),
109 EXPN2(4), EXPN2(5), EXPN2(6), EXPN2(7),
110 EXPN2(8), EXPN2(9), EXPN2(10), EXPN2(11),
111 EXPN2(12), EXPN2(13), EXPN2(14), EXPN2(15),
112 EXPN2(16), EXPN2(17), EXPN2(18), EXPN2(19),
113 EXPN2(20), EXPN2(21), EXPN2(22), EXPN2(23),
114 EXPN2(24), EXPN2(25), EXPN2(26), EXPN2(27),
115 EXPN2(28), EXPN2(29), EXPN2(30), EXPN2(31)
116 #undef EXPN2
117 };
118 int
sdecode_number(const byte * str,int format,ref * np)119 sdecode_number(const byte * str, int format, ref * np)
120 {
121 switch (format & 0x170) {
122 case num_int32:
123 case num_int32 + 16:
124 if ((format & 31) == 0) {
125 np->value.intval = sdecodelong(str, format);
126 return t_integer;
127 } else {
128 np->value.realval =
129 (double)sdecodelong(str, format) *
130 binary_scale[format & 31];
131 return t_real;
132 }
133 case num_int16:
134 if ((format & 15) == 0) {
135 np->value.intval = sdecodeshort(str, format);
136 return t_integer;
137 } else {
138 np->value.realval =
139 sdecodeshort(str, format) *
140 binary_scale[format & 15];
141 return t_real;
142 }
143 case num_float:
144 np->value.realval = sdecodefloat(str, format);
145 return t_real;
146 default:
147 return_error(e_syntaxerror); /* invalid format?? */
148 }
149 }
150
151 /* ------ Decode number ------ */
152
153 /* Decode encoded numbers from a string according to format. */
154
155 /* Decode a (16-bit, signed or unsigned) short. */
156 uint
sdecodeushort(const byte * p,int format)157 sdecodeushort(const byte * p, int format)
158 {
159 int a = p[0], b = p[1];
160
161 return (num_is_lsb(format) ? (b << 8) + a : (a << 8) + b);
162 }
163 int
sdecodeshort(const byte * p,int format)164 sdecodeshort(const byte * p, int format)
165 {
166 int v = (int)sdecodeushort(p, format);
167
168 return (v & 0x7fff) - (v & 0x8000);
169 }
170
171 /* Decode a (32-bit, signed) long. */
172 long
sdecodelong(const byte * p,int format)173 sdecodelong(const byte * p, int format)
174 {
175 int a = p[0], b = p[1], c = p[2], d = p[3];
176 long v = (num_is_lsb(format) ?
177 ((long)d << 24) + ((long)c << 16) + (b << 8) + a :
178 ((long)a << 24) + ((long)b << 16) + (c << 8) + d);
179
180 #if arch_sizeof_long > 4
181 /* Propagate bit 31 as the sign. */
182 v = (v ^ 0x80000000L) - 0x80000000L;
183 #endif
184 return v;
185 }
186
187 /* Decode a float. We assume that native floats occupy 32 bits. */
188 float
sdecodefloat(const byte * p,int format)189 sdecodefloat(const byte * p, int format)
190 {
191 bits32 lnum;
192 float fnum;
193
194 if ((format & ~(num_msb | num_lsb)) == num_float_native) {
195 /*
196 * Just read 4 bytes and interpret them as a float, ignoring
197 * any indication of byte ordering.
198 */
199 memcpy(&lnum, p, 4);
200 fnum = *(float *)&lnum;
201 } else {
202 lnum = (bits32) sdecodelong(p, format);
203 #if !arch_floats_are_IEEE
204 {
205 /* We know IEEE floats take 32 bits. */
206 /* Convert IEEE float to native float. */
207 int sign_expt = lnum >> 23;
208 int expt = sign_expt & 0xff;
209 long mant = lnum & 0x7fffff;
210
211 if (expt == 0 && mant == 0)
212 fnum = 0;
213 else {
214 mant += 0x800000;
215 fnum = (float)ldexp((float)mant, expt - 127 - 23);
216 }
217 if (sign_expt & 0x100)
218 fnum = -fnum;
219 }
220 #else
221 fnum = *(float *)&lnum;
222 #endif
223 }
224 return fnum;
225 }
226