1 /* Copyright (C) 1999 artofcode LLC.  All rights reserved.
2 
3   This program is free software; you can redistribute it and/or modify it
4   under the terms of the GNU General Public License as published by the
5   Free Software Foundation; either version 2 of the License, or (at your
6   option) any later version.
7 
8   This program is distributed in the hope that it will be useful, but
9   WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   General Public License for more details.
12 
13   You should have received a copy of the GNU General Public License along
14   with this program; if not, write to the Free Software Foundation, Inc.,
15   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16 
17 */
18 
19 /*$Id: gsparamx.c,v 1.4.2.1.2.1 2003/01/17 00:49:03 giles Exp $ */
20 /* Extended parameter dictionary utilities */
21 #include "string_.h"
22 #include "gserror.h"
23 #include "gserrors.h"
24 #include "gstypes.h"
25 #include "gsmemory.h"
26 #include "gsparam.h"
27 #include "gsparamx.h"
28 
29 /* Compare a C string and a gs_param_string. */
30 bool
gs_param_string_eq(const gs_param_string * pcs,const char * str)31 gs_param_string_eq(const gs_param_string * pcs, const char *str)
32 {
33     return (strlen(str) == pcs->size &&
34 	    !strncmp(str, (const char *)pcs->data, pcs->size));
35 }
36 
37 /* Put an enumerated value. */
38 int
param_put_enum(gs_param_list * plist,gs_param_name param_name,int * pvalue,const char * const pnames[],int ecode)39 param_put_enum(gs_param_list * plist, gs_param_name param_name,
40 	       int *pvalue, const char *const pnames[], int ecode)
41 {
42     gs_param_string ens;
43     int code = param_read_name(plist, param_name, &ens);
44 
45     switch (code) {
46 	case 1:
47 	    return ecode;
48 	case 0:
49 	    {
50 		int i;
51 
52 		for (i = 0; pnames[i] != 0; ++i)
53 		    if (gs_param_string_eq(&ens, pnames[i])) {
54 			*pvalue = i;
55 			return 0;
56 		    }
57 	    }
58 	    code = gs_error_rangecheck;
59 	default:
60 	    ecode = code;
61 	    param_signal_error(plist, param_name, code);
62     }
63     return code;
64 }
65 
66 /* Put a Boolean value. */
67 int
param_put_bool(gs_param_list * plist,gs_param_name param_name,bool * pval,int ecode)68 param_put_bool(gs_param_list * plist, gs_param_name param_name,
69 	       bool * pval, int ecode)
70 {
71     int code;
72 
73     switch (code = param_read_bool(plist, param_name, pval)) {
74 	default:
75 	    ecode = code;
76 	    param_signal_error(plist, param_name, ecode);
77 	case 0:
78 	case 1:
79 	    break;
80     }
81     return ecode;
82 }
83 
84 /* Put an integer value. */
85 int
param_put_int(gs_param_list * plist,gs_param_name param_name,int * pval,int ecode)86 param_put_int(gs_param_list * plist, gs_param_name param_name,
87 	      int *pval, int ecode)
88 {
89     int code;
90 
91     switch (code = param_read_int(plist, param_name, pval)) {
92 	default:
93 	    ecode = code;
94 	    param_signal_error(plist, param_name, ecode);
95 	case 0:
96 	case 1:
97 	    break;
98     }
99     return ecode;
100 }
101 
102 /* Put a long value. */
103 int
param_put_long(gs_param_list * plist,gs_param_name param_name,long * pval,int ecode)104 param_put_long(gs_param_list * plist, gs_param_name param_name,
105 	       long *pval, int ecode)
106 {
107     int code;
108 
109     switch (code = param_read_long(plist, param_name, pval)) {
110 	default:
111 	    ecode = code;
112 	    param_signal_error(plist, param_name, ecode);
113 	case 0:
114 	case 1:
115 	    break;
116     }
117     return ecode;
118 }
119 
120 /* Copy one parameter list to another, recursively if necessary. */
121 int
param_list_copy(gs_param_list * plto,gs_param_list * plfrom)122 param_list_copy(gs_param_list *plto, gs_param_list *plfrom)
123 {
124     gs_param_enumerator_t key_enum;
125     gs_param_key_t key;
126     /*
127      * If plfrom and plto use different allocators, we must copy
128      * aggregate values even if they are "persistent".
129      */
130     bool copy_persists = plto->memory == plfrom->memory;
131     int code;
132 
133     param_init_enumerator(&key_enum);
134     while ((code = param_get_next_key(plfrom, &key_enum, &key)) == 0) {
135 	char string_key[256];	/* big enough for any reasonable key */
136 	gs_param_typed_value value;
137 	gs_param_collection_type_t coll_type;
138 	gs_param_typed_value copy;
139 
140 	if (key.size > sizeof(string_key) - 1) {
141 	    code = gs_note_error(gs_error_rangecheck);
142 	    break;
143 	}
144 	memcpy(string_key, key.data, key.size);
145 	string_key[key.size] = 0;
146 	if ((code = param_read_typed(plfrom, string_key, &value)) != 0) {
147 	    code = (code > 0 ? gs_note_error(gs_error_unknownerror) : code);
148 	    break;
149 	}
150 	gs_param_list_set_persistent_keys(plto, key.persistent);
151 	switch (value.type) {
152 	case gs_param_type_dict:
153 	    coll_type = gs_param_collection_dict_any;
154 	    goto cc;
155 	case gs_param_type_dict_int_keys:
156 	    coll_type = gs_param_collection_dict_int_keys;
157 	    goto cc;
158 	case gs_param_type_array:
159 	    coll_type = gs_param_collection_array;
160 	cc:
161 	    copy.value.d.size = value.value.d.size;
162 	    if ((code = param_begin_write_collection(plto, string_key,
163 						     &copy.value.d,
164 						     coll_type)) < 0 ||
165 		(code = param_list_copy(copy.value.d.list,
166 					value.value.d.list)) < 0 ||
167 		(code = param_end_write_collection(plto, string_key,
168 						   &copy.value.d)) < 0)
169 		break;
170 	    code = param_end_read_collection(plfrom, string_key,
171 					     &value.value.d);
172 	    break;
173 	case gs_param_type_string:
174 	    value.value.s.persistent &= copy_persists; goto ca;
175 	case gs_param_type_name:
176 	    value.value.n.persistent &= copy_persists; goto ca;
177 	case gs_param_type_int_array:
178 	    value.value.ia.persistent &= copy_persists; goto ca;
179 	case gs_param_type_float_array:
180 	    value.value.fa.persistent &= copy_persists; goto ca;
181 	case gs_param_type_string_array:
182 	    value.value.sa.persistent &= copy_persists;
183 	ca:
184 	default:
185 	    code = param_write_typed(plto, string_key, &value);
186 	}
187 	if (code < 0)
188 	    break;
189     }
190     return code;
191 }
192