1 /* Copyright (C) 2001-2012 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,
8    modified or distributed except as expressly authorized under the terms
9    of the license contained in the file LICENSE in this distribution.
10 
11    Refer to licensing information at http://www.artifex.com or contact
12    Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134, San Rafael,
13    CA  94903, U.S.A., +1(415)492-9861, for further information.
14 */
15 
16 
17 /* Level 2 encoded number reading utilities for Ghostscript */
18 #include "math_.h"
19 #include "memory_.h"
20 #include "ghost.h"
21 #include "opcheck.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     int format;
41 
42     switch (r_type(op)) {
43         case t_string:
44             {
45                 /* Check that this is a legitimate encoded number string. */
46                 const byte *bp = op->value.bytes;
47 
48                 if (r_size(op) < 4 || bp[0] != bt_num_array_value)
49                     return_error(e_typecheck);
50                 format = bp[1];
51                 if (!num_is_valid(format) ||
52                     sdecodeshort(bp + 2, format) !=
53                     (r_size(op) - 4) / encoded_number_bytes(format)
54                     )
55                     return_error(e_rangecheck);
56             }
57             break;
58         case t_array:
59         case t_mixedarray:
60         case t_shortarray:
61             format = num_array;
62             break;
63         default:
64             return_error(e_typecheck);
65     }
66     check_read(*op);
67     return format;
68 }
69 
70 /* Get the number of elements in an encoded number array/string. */
71 uint
num_array_size(const ref * op,int format)72 num_array_size(const ref * op, int format)
73 {
74     return (format == num_array ? r_size(op) :
75             (r_size(op) - 4) / encoded_number_bytes(format));
76 }
77 
78 /* Get an encoded number from an array/string according to the given format. */
79 /* Put the value in np->value.{intval,realval}. */
80 /* Return t_int if integer, t_real if real, t_null if end of stream, */
81 /* or an error if the format is invalid. */
82 int
num_array_get(const gs_memory_t * mem,const ref * op,int format,uint index,ref * np)83 num_array_get(const gs_memory_t *mem, const ref * op, int format, uint index, ref * np)
84 {
85     if (format == num_array) {
86         int code = array_get(mem, op, (long)index, np);
87 
88         if (code < 0)
89             return t_null;
90         switch (r_type(np)) {
91             case t_integer:
92                 return t_integer;
93             case t_real:
94                 return t_real;
95             default:
96                 return_error(e_typecheck);
97         }
98     } else {
99         uint nbytes = encoded_number_bytes(format);
100 
101         if (index >= (r_size(op) - 4) / nbytes)
102             return t_null;
103         return sdecode_number(op->value.bytes + 4 + index * nbytes,
104                               format, np);
105     }
106 }
107 
108 /* Internal routine to decode a number in a given format. */
109 /* Same returns as sget_encoded_number. */
110 static const double binary_scale[32] = {
111 #define EXPN2(n) (0.5 / (1L << (n-1)))
112     1.0, EXPN2(1), EXPN2(2), EXPN2(3),
113     EXPN2(4), EXPN2(5), EXPN2(6), EXPN2(7),
114     EXPN2(8), EXPN2(9), EXPN2(10), EXPN2(11),
115     EXPN2(12), EXPN2(13), EXPN2(14), EXPN2(15),
116     EXPN2(16), EXPN2(17), EXPN2(18), EXPN2(19),
117     EXPN2(20), EXPN2(21), EXPN2(22), EXPN2(23),
118     EXPN2(24), EXPN2(25), EXPN2(26), EXPN2(27),
119     EXPN2(28), EXPN2(29), EXPN2(30), EXPN2(31)
120 #undef EXPN2
121 };
122 int
sdecode_number(const byte * str,int format,ref * np)123 sdecode_number(const byte * str, int format, ref * np)
124 {
125     switch (format & 0x170) {
126         case num_int32:
127         case num_int32 + 16:
128             if ((format & 31) == 0) {
129                 np->value.intval = sdecodeint32(str, format);
130                 return t_integer;
131             } else {
132                 np->value.realval =
133                     (double)sdecodeint32(str, format) *
134                     binary_scale[format & 31];
135                 return t_real;
136             }
137         case num_int16:
138             if ((format & 15) == 0) {
139                 np->value.intval = sdecodeshort(str, format);
140                 return t_integer;
141             } else {
142                 np->value.realval =
143                     sdecodeshort(str, format) *
144                     binary_scale[format & 15];
145                 return t_real;
146             }
147         case num_float:
148             {
149                 float fval;
150                 int code = sdecode_float(str, format, &fval);
151 
152                 if (code < 0)
153                     return code;
154                 np->value.realval = fval;
155                 return t_real;
156             }
157         default:
158             return_error(e_syntaxerror);	/* invalid format?? */
159     }
160 }
161 
162 /* ------ Decode number ------ */
163 
164 /* Decode encoded numbers from a string according to format. */
165 
166 /* Decode a (16-bit, signed or unsigned) short. */
167 uint
sdecodeushort(const byte * p,int format)168 sdecodeushort(const byte * p, int format)
169 {
170     int a = p[0], b = p[1];
171 
172     return (num_is_lsb(format) ? (b << 8) + a : (a << 8) + b);
173 }
174 int
sdecodeshort(const byte * p,int format)175 sdecodeshort(const byte * p, int format)
176 {
177     int v = (int)sdecodeushort(p, format);
178 
179     return (v & 0x7fff) - (v & 0x8000);
180 }
181 
182 /* Decode a (32-bit, signed) long. */
183 int
sdecodeint32(const byte * p,int format)184 sdecodeint32(const byte * p, int format)
185 {
186     int a = p[0], b = p[1], c = p[2], d = p[3];
187     int v = (num_is_lsb(format) ?
188               ((int)d << 24) + ((int)c << 16) + (b << 8) + a :
189               ((int)a << 24) + ((int)b << 16) + (c << 8) + d);
190     return v;
191 }
192 
193 /* Decode a 32-bit number. Return the resukt through a pointer */
194 /* to work around a gcc 4.2.1 bug on PowerPC, bug 689586 */
195 static void
sdecodebits32(const byte * p,int format,bits32 * v)196 sdecodebits32(const byte * p, int format, bits32 *v)
197 {
198   int a = p[0], b = p[1], c = p[2], d = p[3];
199   *v = (num_is_lsb(format) ?
200             ((long)d << 24) + ((long)c << 16) + (b << 8) + a :
201             ((long)a << 24) + ((long)b << 16) + (c << 8) + d);
202 
203 }
204 
205 /* Decode a float.  We assume that native floats occupy 32 bits. */
206 /* If the float is an IEEE NaN or Inf, return e_undefinedresult. */
207 int
sdecode_float(const byte * p,int format,float * pfnum)208 sdecode_float(const byte * p, int format, float *pfnum)
209 {
210     bits32 lnum;
211 
212     if ((format & ~(num_msb | num_lsb)) == num_float_native) {
213         /*
214          * Just read 4 bytes and interpret them as a float, ignoring
215          * any indication of byte ordering.
216          */
217         memcpy(pfnum, p, 4);
218 #if !ARCH_FLOATS_ARE_IEEE
219         return 0;		/* no way to check for anomalies */
220 #endif
221         lnum = *(bits32 *)pfnum;
222     } else {
223         sdecodebits32(p, format, &lnum);
224 
225 #if !ARCH_FLOATS_ARE_IEEE
226         {
227             /* We know IEEE floats take 32 bits. */
228             /* Convert IEEE float to native float. */
229             int sign_expt = lnum >> 23;
230             int expt = sign_expt & 0xff;
231             long mant = lnum & 0x7fffff;
232             float fnum;
233 
234             if (expt == 0 && mant == 0)
235                 fnum = 0;
236             else if (expt == 0xff)
237                 return_error(e_undefinedresult); /* Inf or NaN */
238             else {
239                 mant += 0x800000;
240                 fnum = (float)ldexp((float)mant, expt - 127 - 23);
241             }
242             if (sign_expt & 0x100)
243                 fnum = -fnum;
244             *pfnum = fnum;
245             return 0;		/* checked for Infs and NaNs above */
246         }
247 #else
248         *pfnum = *(float *)&lnum;
249 #endif
250     }
251     /*
252      * Unfortunately, there is no portable way for testing whether a float
253      * is a NaN or Inf.  Do it "by hand" if the input representation is
254      * IEEE (which is the case if control arrives here).
255      */
256     if (!(~lnum & 0x7f800000))	/* i.e. exponent all 1's */
257         return_error(e_undefinedresult); /* Inf or NaN */
258     return 0;
259 }
260