xref: /plan9/sys/src/cmd/gs/src/ibnum.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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