Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
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
}