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) 1998 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: gsparam2.c,v 1.6 2002/07/01 14:27:43 jeong Exp $ */
18
/* Serialize and unserialize parameter lists */
19
 
20
/* Initial version 2/1/98 by John Desrosiers (soho@crl.com) */
21
/* 8/8/98 L. Peter Deutsch (ghost@aladdin.com) Rewritten to use streams */
22
 
23
#include "gx.h"
24
#include "memory_.h"
25
#include "gserrors.h"
26
#include "gsparams.h"
27
 
28
#define MAX_PARAM_KEY 255
29
 
30
/* ---------------- Serializer ---------------- */
31
 
32
/* Forward references */
33
private int sput_word(stream *dest, uint value);
34
private int sput_bytes(stream *dest, const byte *data, uint size);
35
 
36
/*
37
 * Serialize the contents of a gs_param_list, including sub-dictionaries,
38
 * onto a stream.  The list must be in READ mode.
39
 */
40
int
41
gs_param_list_puts(stream *dest, gs_param_list *list)
42
{
43
    int code = 0;
44
    gs_param_enumerator_t key_enum;
45
    gs_param_key_t key;
46
 
47
    param_init_enumerator(&key_enum);
48
 
49
    /* Each item is serialized as ("word" means compressed word):
50
     *  word: key sizeof + 1, or 0 if end of list/dict
51
     *  word: data type(gs_param_type_xxx)
52
     *  byte[]: key, including trailing \0 
53
     *  (if simple type)
54
     *    byte[]: unpacked representation of data
55
     *  (if simple array or string)
56
     *    word: # of elements
57
     *    byte[]: data associated with array contents
58
     *  (if string/name array)
59
     *    word: # of elements
60
     *    { word: length of string
61
     *      byte[]: string data
62
     *    } for each string in array
63
     *  (if dict/dict_int_keys/hetero_array)
64
     *    word: # of entries in collection
65
     *    entries follow immediately
66
     */
67
    /* Enumerate all the keys; use keys to get their typed values */
68
    while ((code = param_get_next_key(list, &key_enum, &key)) == 0) {
69
	int value_top_sizeof;
70
	int value_base_sizeof;
71
	const void *data;
72
	uint size;
73
 
74
	/* Get next datum & put its type & key to stream */
75
	gs_param_typed_value value;
76
	char string_key[MAX_PARAM_KEY + 1];
77
 
78
	if (sizeof(string_key) < key.size + 1) {
79
	    code = gs_note_error(gs_error_rangecheck);
80
	    break;
81
	}
82
	memcpy(string_key, key.data, key.size);
83
	string_key[key.size] = 0;
84
	if ((code = param_read_typed(list, string_key, &value)) != 0) {
85
	    if (code > 0)
86
		code = gs_note_error(gs_error_unknownerror);
87
	    break;
88
	}
89
	sput_word(dest, (unsigned)key.size + 1);
90
	sput_word(dest, (unsigned)value.type);
91
	sput_bytes(dest, (byte *)string_key, key.size + 1);
92
 
93
	/* Put value & its size to stream */
94
	value_top_sizeof = gs_param_type_sizes[value.type];
95
	value_base_sizeof = gs_param_type_base_sizes[value.type];
96
	switch (value.type) {
97
	    case gs_param_type_bool:
98
	    case gs_param_type_int:
99
	    case gs_param_type_long:
100
	    case gs_param_type_float:
101
		sput_bytes(dest, (byte *)&value.value, value_top_sizeof);
102
	    case gs_param_type_null:
103
		break;
104
 
105
	    case gs_param_type_string:
106
		data = value.value.s.data, size = value.value.s.size;
107
		goto scalar_array;
108
	    case gs_param_type_name:
109
		data = value.value.n.data, size = value.value.n.size;
110
		goto scalar_array;
111
	    case gs_param_type_int_array:
112
		data = value.value.ia.data, size = value.value.ia.size;
113
		goto scalar_array;
114
	    case gs_param_type_float_array:
115
		data = value.value.fa.data, size = value.value.fa.size;
116
scalar_array:	sput_word(dest, size);
117
		sput_bytes(dest, data, value_base_sizeof * size);
118
		break;
119
 
120
	    case gs_param_type_string_array:
121
		data = value.value.sa.data, size = value.value.sa.size;
122
		goto string_array;
123
	    case gs_param_type_name_array:
124
		data = value.value.na.data, size = value.value.na.size;
125
string_array:	sput_word(dest, size);
126
		{
127
		    uint count;
128
		    const gs_param_string *sa;
129
 
130
		    for (count = size, sa = data; count-- > 0; ++sa) {
131
			sput_word(dest, sa->size);
132
			sput_bytes(dest, sa->data, sa->size);
133
		    }
134
		}
135
		break;
136
 
137
	    case gs_param_type_dict:
138
	    case gs_param_type_dict_int_keys:
139
	    case gs_param_type_array:
140
		sput_word(dest, value.value.d.size);
141
		code = gs_param_list_puts(dest, value.value.d.list);
142
		{
143
		    int end_code =
144
			param_end_read_dict(list, key.data, &value.value.d);
145
 
146
		    if (code >= 0)
147
			code = end_code;
148
		}
149
		break;
150
 
151
	    default:
152
		code = gs_note_error(gs_error_unknownerror);
153
		break;
154
	}
155
	if (code < 0)
156
	    break;
157
    }
158
 
159
    /* Write end marker, which is an (illegal) 0 key length */
160
    return (code < 0 ? code : sput_word(dest, 0));
161
}
162
 
163
/* Put a variable-length value on a stream. */
164
private int
165
sput_word(stream *dest, uint value)
166
{
167
    int code = 0;
168
 
169
    do {
170
	byte chunk = value & 0x7f;
171
 
172
	if ((value >>= 7) != 0)
173
	    chunk |= 0x80;
174
	if ((code = sputc(dest, chunk)) < 0)
175
	    break;
176
    }
177
    while (value != 0);
178
    return code;
179
}
180
 
181
/* Put bytes on a stream. */
182
private int
183
sput_bytes(stream *dest, const byte *data, uint size)
184
{
185
    uint ignore_count;
186
 
187
    return sputs(dest, data, size, &ignore_count);
188
}
189
 
190
/* ---------------- Unserializer ---------------- */
191
 
192
/* Forward references */
193
private int sget_word(stream *src, uint *pvalue);
194
private int sget_bytes(stream *src, byte *data, uint size);
195
 
196
/*
197
 * Unserialize a parameter list from a stream.  The list must be in WRITE
198
 * mode.
199
 */
200
int
201
gs_param_list_gets(stream *src, gs_param_list *list, gs_memory_t *mem)
202
{
203
    int code = 0;
204
 
205
    do {
206
	gs_param_typed_value typed;
207
	uint key_sizeof;
208
	int value_top_sizeof;
209
	int value_base_sizeof;
210
	uint temp;
211
	void *data;
212
	uint size;
213
	gs_param_type type;
214
	char string_key[MAX_PARAM_KEY + 1];
215
 
216
	/* key length 0 indicates end of data */
217
	if ((code = sget_word(src, &key_sizeof)) < 0 ||
218
	    key_sizeof == 0 ||
219
	    /* data type */
220
	    (code = sget_word(src, &temp)) < 0)
221
	    break;
222
 
223
	if (key_sizeof > sizeof(string_key)) {
224
	    code = gs_note_error(gs_error_rangecheck);
225
	    break;
226
	}
227
	/* key */
228
	code = sget_bytes(src, (byte *)string_key, key_sizeof);
229
	if (code < 0)
230
	    break;
231
 
232
	/* Data values */
233
	type = (gs_param_type)temp;
234
	value_top_sizeof = gs_param_type_sizes[type];
235
	value_base_sizeof = gs_param_type_base_sizes[type];
236
	typed.type = type;
237
	switch (type) {
238
	    case gs_param_type_bool:
239
	    case gs_param_type_int:
240
	    case gs_param_type_long:
241
	    case gs_param_type_float:
242
		code = sget_bytes(src, (byte *)&typed.value, value_top_sizeof);
243
	    case gs_param_type_null:
244
		goto put;
245
	    default:
246
		;
247
	}
248
	/* All other data values start with a size. */
249
	code = sget_word(src, &size);
250
	if (code < 0)
251
	    break;
252
 
253
	switch (type) {
254
	    case gs_param_type_string:
255
	    case gs_param_type_name:
256
	    case gs_param_type_int_array:
257
	    case gs_param_type_float_array:
258
		data =
259
		    (value_base_sizeof == 1 ?
260
		     gs_alloc_string(mem, size, "param string/name") :
261
		     gs_alloc_byte_array(mem, size, value_base_sizeof,
262
					 "param scalar array"));
263
		if (data == 0) {
264
		    code = gs_note_error(gs_error_VMerror);
265
		    break;
266
		}
267
		typed.value.s.data = data;
268
		typed.value.s.persistent = false;
269
		typed.value.s.size = size;
270
		code = sget_bytes(src, data, size * value_base_sizeof);
271
		break;
272
 
273
	    case gs_param_type_string_array:
274
	    case gs_param_type_name_array:
275
		/****** SHOULD BE STRUCT ARRAY ******/
276
		data = gs_alloc_byte_array(mem, size, value_top_sizeof,
277
					   "param string/name array");
278
		if (data == 0) {
279
		    code = gs_note_error(gs_error_VMerror);
280
		    break;
281
		}
282
		typed.value.sa.data = data;
283
		typed.value.sa.persistent = false;
284
		typed.value.sa.size = size;
285
		{
286
		    gs_param_string *sa = data;
287
		    byte *str_data;
288
		    uint index, str_size;
289
 
290
		    /* Clean pointers in case we bail out. */
291
		    for (index = 0; index < size; ++index)
292
			sa[index].data = 0, sa[index].size = 0;
293
		    for (index = 0; index < size; ++index, ++sa) {
294
			code = sget_word(src, &str_size);
295
			if (code < 0)
296
			    break;
297
			str_data = gs_alloc_string(mem, str_size,
298
						"param string/name element");
299
			if (str_data == 0) {
300
			    code = gs_note_error(gs_error_VMerror);
301
			    break;
302
			}
303
			code = sget_bytes(src, str_data, str_size);
304
			if (code < 0)
305
			    break;
306
		    }
307
		}
308
		break;
309
 
310
	    case gs_param_type_dict:
311
	    case gs_param_type_dict_int_keys:
312
	    case gs_param_type_array:
313
		typed.value.d.size = size;
314
		code = param_begin_write_collection
315
		    (list, string_key, &typed.value.d,
316
		     type - gs_param_type_dict);
317
		if (code < 0)
318
		    break;
319
		code = gs_param_list_gets(src, typed.value.d.list, mem);
320
		{
321
		    int end_code =
322
			param_end_write_collection(list, string_key,
323
						   &typed.value.d);
324
 
325
		    if (code >= 0)
326
			code = end_code;
327
		}
328
		break;
329
 
330
	    default:
331
		code = gs_note_error(gs_error_unknownerror);
332
		break;
333
	}
334
put:	if (code < 0)
335
	    break;
336
	if (typed.type != gs_param_type_dict &&
337
	    typed.type != gs_param_type_dict_int_keys &&
338
	    typed.type != gs_param_type_array
339
	    )
340
	    code = param_write_typed(list, string_key, &typed);
341
    }
342
    while (code >= 0);
343
 
344
    return code;
345
}
346
 
347
 
348
/* ---------- Utility functions -------- */
349
 
350
/* Get a value stored with sput_word */
351
private int
352
sget_word(stream *src, uint *pvalue)
353
{
354
    uint value = 0;
355
    int chunk;
356
    uint shift = 0;
357
 
358
    do {
359
	chunk = sgetc(src);
360
	if (chunk < 0)
361
	    return chunk;
362
	value |= (chunk & 0x7f) << shift;
363
	shift += 7;
364
    }
365
    while (chunk & 0x80);
366
 
367
    *pvalue = value;
368
    return 0;
369
}
370
 
371
/* Get bytes from a stream */
372
private int
373
sget_bytes(stream *src, byte *data, uint size)
374
{
375
    uint ignore_count;
376
 
377
    int status = sgets(src, data, size, &ignore_count);
378
 
379
    if (status < 0 && status != EOFC)
380
	return_error(gs_error_ioerror);
381
    };
382
 
383
    return 0;
384
}