2 |
- |
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
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
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 |
}
|