summaryrefslogtreecommitdiff
path: root/base/gsparamx.c
blob: 2e88d3e6a5261aeeb00d890bc1c12252d2f339e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/* Copyright (C) 2001-2023 Artifex Software, Inc.
   All Rights Reserved.

   This software is provided AS-IS with no warranty, either express or
   implied.

   This software is distributed under license and may not be copied,
   modified or distributed except as expressly authorized under the terms
   of the license contained in the file LICENSE in this distribution.

   Refer to licensing information at http://www.artifex.com or contact
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
   CA 94129, USA, for further information.
*/


/* Extended parameter dictionary utilities */
#include "string_.h"
#include "gserrors.h"
#include "gstypes.h"
#include "gsmemory.h"
#include "gsparam.h"
#include "gsparamx.h"

/* Compare a C string and a gs_param_string. */
bool
gs_param_string_eq(const gs_param_string * pcs, const char *str)
{
    return (strlen(str) == pcs->size &&
            !strncmp(str, (const char *)pcs->data, pcs->size));
}

/* Put an enumerated value. */
int
param_put_enum(gs_param_list * plist, gs_param_name param_name,
               int *pvalue, const char *const pnames[], int ecode)
{
    gs_param_string ens;
    int code = param_read_name(plist, param_name, &ens);

    switch (code) {
        case 1:
            return ecode;
        case 0:
            {
                int i;

                for (i = 0; pnames[i] != 0; ++i)
                    if (gs_param_string_eq(&ens, pnames[i])) {
                        *pvalue = i;
                        return 0;
                    }
            }
            code = gs_error_rangecheck;
            /* fall through */
        default:
            ecode = code;
            param_signal_error(plist, param_name, code);
    }
    return ecode;
}

/* Put a Boolean value. */
int
param_put_bool(gs_param_list * plist, gs_param_name param_name,
               bool * pval, int ecode)
{
    int code;

    switch (code = param_read_bool(plist, param_name, pval)) {
        default:
            ecode = code;
            param_signal_error(plist, param_name, ecode);
        case 0:
        case 1:
            break;
    }
    return ecode;
}

/* Put an integer value. */
int
param_put_int(gs_param_list * plist, gs_param_name param_name,
              int *pval, int ecode)
{
    int code;

    switch (code = param_read_int(plist, param_name, pval)) {
        default:
            ecode = code;
            param_signal_error(plist, param_name, ecode);
        case 0:
        case 1:
            break;
    }
    return ecode;
}

/* Put a long value. */
int
param_put_long(gs_param_list * plist, gs_param_name param_name,
               long *pval, int ecode)
{
    int code;

    switch (code = param_read_long(plist, param_name, pval)) {
        default:
            ecode = code;
            param_signal_error(plist, param_name, ecode);
        case 0:
        case 1:
            break;
    }
    return ecode;
}

/* Copy one parameter list to another, recursively if necessary. */
int
param_list_copy(gs_param_list *plto, gs_param_list *plfrom)
{
    gs_param_enumerator_t key_enum;
    gs_param_key_t key;
    /*
     * If plfrom and plto use different allocators, we must copy
     * aggregate values even if they are "persistent".
     */
    bool copy_persists = plto->memory == plfrom->memory;
    int code;

    param_init_enumerator(&key_enum);
    while ((code = param_get_next_key(plfrom, &key_enum, &key)) == 0) {
        char string_key[256];	/* big enough for any reasonable key */
        gs_param_typed_value value;
        gs_param_collection_type_t coll_type;
        gs_param_typed_value copy;

        if (key.size > sizeof(string_key) - 1) {
            code = gs_note_error(gs_error_rangecheck);
            break;
        }
        memcpy(string_key, key.data, key.size);
        string_key[key.size] = 0;
        if ((code = param_read_typed(plfrom, string_key, &value)) != 0) {
            code = (code > 0 ? gs_note_error(gs_error_unknownerror) : code);
            break;
        }
        /* We used to use 'key.persistent' to determine whether we needed to copy the
         * key (by setting persistent_keys in the param list to false), but that isn't
         * correct! We are going to use the heap buffer 'string_key', not the original
         * key, and since that's on the heap it is NOT persistent....
         */
        gs_param_list_set_persistent_keys(plto, false);
        switch (value.type) {
        case gs_param_type_dict:
            coll_type = gs_param_collection_dict_any;
            goto cc;
        case gs_param_type_dict_int_keys:
            coll_type = gs_param_collection_dict_int_keys;
            goto cc;
        case gs_param_type_array:
            coll_type = gs_param_collection_array;
        cc:
            copy.value.d.size = value.value.d.size;
            /* FIXME: RJW: I suspect that this will go wrong, if size == 0.
             * We should probably spot size == 0 and break. */
            if ((code = param_begin_write_collection(plto, string_key,
                                                     &copy.value.d,
                                                     coll_type)) < 0 ||
                (code = param_list_copy(copy.value.d.list,
                                        value.value.d.list)) < 0 ||
                (code = param_end_write_collection(plto, string_key,
                                                   &copy.value.d)) < 0)
                break;
            code = param_end_read_collection(plfrom, string_key,
                                             &value.value.d);
            break;
        case gs_param_type_string:
            value.value.s.persistent &= copy_persists; goto ca;
        case gs_param_type_name:
            value.value.n.persistent &= copy_persists; goto ca;
        case gs_param_type_int_array:
            value.value.ia.persistent &= copy_persists; goto ca;
        case gs_param_type_float_array:
            value.value.fa.persistent &= copy_persists; goto ca;
        case gs_param_type_string_array:
            value.value.sa.persistent &= copy_persists;
            /* fall through */
        ca:
        default:
            code = param_write_typed(plto, string_key, &value);
        }
        if (code < 0)
            break;
    }
    return code;
}