1 /* sane - Scanner Access Now Easy.
2 Copyright (C) 1996, 1997 David Mosberger-Tang and Andreas Beck
3 This file is part of the SANE package.
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
17
18 As a special exception, the authors of SANE give permission for
19 additional uses of the libraries contained in this release of SANE.
20
21 The exception is that, if you link a SANE library with other files
22 to produce an executable, this does not by itself cause the
23 resulting executable to be covered by the GNU General Public
24 License. Your use of that executable is in no way restricted on
25 account of linking the SANE library code into it.
26
27 This exception does not, however, invalidate any other reasons why
28 the executable file might be covered by the GNU General Public
29 License.
30
31 If you submit changes to SANE to the maintainers to be included in
32 a subsequent release, you agree by submitting the changes that
33 those changes may be distributed with this exception intact.
34
35 If you write modifications of your own for SANE, it is your choice
36 whether to permit this exception to apply to your modifications.
37 If you do not wish that, delete this exception notice. */
38
39 #include "../include/sane/config.h"
40
41 #include <string.h>
42
43 #include <sys/types.h>
44 #include <stdlib.h>
45
46 #include <stdio.h>
47
48 #include "../include/sane/sane.h"
49 #include "../include/sane/sanei.h"
50
51 SANE_Status
sanei_check_value(const SANE_Option_Descriptor * opt,void * value)52 sanei_check_value (const SANE_Option_Descriptor * opt, void *value)
53 {
54 const SANE_String_Const *string_list;
55 const SANE_Word *word_list;
56 int i, count;
57 const SANE_Range *range;
58 SANE_Word w, v, *array;
59 SANE_Bool *barray;
60 size_t len;
61
62 switch (opt->constraint_type)
63 {
64 case SANE_CONSTRAINT_RANGE:
65
66 /* single values are treated as arrays of length 1 */
67 array = (SANE_Word *) value;
68
69 /* compute number of elements */
70 if (opt->size > 0)
71 {
72 count = opt->size / sizeof (SANE_Word);
73 }
74 else
75 {
76 count = 1;
77 }
78
79 range = opt->constraint.range;
80 /* for each element of the array, we check according to the constraint */
81 for (i = 0; i < count; i++)
82 {
83 /* test for min and max */
84 if (array[i] < range->min || array[i] > range->max)
85 return SANE_STATUS_INVAL;
86
87 /* check quantization */
88 if (range->quant)
89 {
90 v =
91 (unsigned int) (array[i] - range->min +
92 range->quant / 2) / range->quant;
93 v = v * range->quant + range->min;
94 if (v != array[i])
95 return SANE_STATUS_INVAL;
96 }
97 }
98 break;
99
100 case SANE_CONSTRAINT_WORD_LIST:
101 w = *(SANE_Word *) value;
102 word_list = opt->constraint.word_list;
103 for (i = 1; w != word_list[i]; ++i)
104 if (i >= word_list[0])
105 return SANE_STATUS_INVAL;
106 break;
107
108 case SANE_CONSTRAINT_STRING_LIST:
109 string_list = opt->constraint.string_list;
110 len = strlen (value);
111
112 for (i = 0; string_list[i]; ++i)
113 if (strncmp (value, string_list[i], len) == 0
114 && len == strlen (string_list[i]))
115 return SANE_STATUS_GOOD;
116 return SANE_STATUS_INVAL;
117
118 case SANE_CONSTRAINT_NONE:
119 switch (opt->type)
120 {
121 case SANE_TYPE_BOOL:
122 /* single values are treated as arrays of length 1 */
123 array = (SANE_Word *) value;
124
125 /* compute number of elements */
126 if (opt->size > 0)
127 {
128 count = opt->size / sizeof (SANE_Bool);
129 }
130 else
131 {
132 count = 1;
133 }
134
135 barray = (SANE_Bool *) value;
136
137 /* test each boolean value in the array */
138 for (i = 0; i < count; i++)
139 {
140 if (barray[i] != SANE_TRUE && barray[i] != SANE_FALSE)
141 return SANE_STATUS_INVAL;
142 }
143 break;
144 default:
145 break;
146 }
147
148 default:
149 break;
150 }
151 return SANE_STATUS_GOOD;
152 }
153
154 /**
155 * This function apply the constraint defined by the option descriptor
156 * to the given value, and update the info flags holder if needed. It
157 * return SANE_STATUS_INVAL if the constraint cannot be applied, else
158 * it returns SANE_STATUS_GOOD.
159 */
160 SANE_Status
sanei_constrain_value(const SANE_Option_Descriptor * opt,void * value,SANE_Word * info)161 sanei_constrain_value (const SANE_Option_Descriptor * opt, void *value,
162 SANE_Word * info)
163 {
164 const SANE_String_Const *string_list;
165 const SANE_Word *word_list;
166 int i, k, num_matches, match;
167 const SANE_Range *range;
168 SANE_Word w, v, *array;
169 SANE_Bool b;
170 size_t len;
171
172 switch (opt->constraint_type)
173 {
174 case SANE_CONSTRAINT_RANGE:
175
176 /* single values are treated as arrays of length 1 */
177 array = (SANE_Word *) value;
178
179 /* compute number of elements */
180 if (opt->size > 0)
181 {
182 k = opt->size / sizeof (SANE_Word);
183 }
184 else
185 {
186 k = 1;
187 }
188
189 range = opt->constraint.range;
190 /* for each element of the array, we apply the constraint */
191 for (i = 0; i < k; i++)
192 {
193 /* constrain min */
194 if (array[i] < range->min)
195 {
196 array[i] = range->min;
197 if (info)
198 {
199 *info |= SANE_INFO_INEXACT;
200 }
201 }
202
203 /* constrain max */
204 if (array[i] > range->max)
205 {
206 array[i] = range->max;
207 if (info)
208 {
209 *info |= SANE_INFO_INEXACT;
210 }
211 }
212
213 /* quantization */
214 if (range->quant)
215 {
216 v =
217 (unsigned int) (array[i] - range->min +
218 range->quant / 2) / range->quant;
219 v = v * range->quant + range->min;
220 /* due to rounding issues with sane 'fixed' values,
221 * the computed value may exceed max */
222 if (v > range->max)
223 {
224 v = range->max;
225 }
226 if (v != array[i])
227 {
228 array[i] = v;
229 if (info)
230 *info |= SANE_INFO_INEXACT;
231 }
232 }
233 }
234 break;
235
236 case SANE_CONSTRAINT_WORD_LIST:
237 /* If there is no exact match in the list, use the nearest value */
238 w = *(SANE_Word *) value;
239 word_list = opt->constraint.word_list;
240 for (i = 1, k = 1, v = abs (w - word_list[1]); i <= word_list[0]; i++)
241 {
242 SANE_Word vh;
243 if ((vh = abs (w - word_list[i])) < v)
244 {
245 v = vh;
246 k = i;
247 }
248 }
249 if (w != word_list[k])
250 {
251 *(SANE_Word *) value = word_list[k];
252 if (info)
253 *info |= SANE_INFO_INEXACT;
254 }
255 break;
256
257 case SANE_CONSTRAINT_STRING_LIST:
258 /* Matching algorithm: take the longest unique match ignoring
259 case. If there is an exact match, it is admissible even if
260 the same string is a prefix of a longer option name. */
261 string_list = opt->constraint.string_list;
262 len = strlen (value);
263
264 /* count how many matches of length LEN characters we have: */
265 num_matches = 0;
266 match = -1;
267 for (i = 0; string_list[i]; ++i)
268 if (strncasecmp (value, string_list[i], len) == 0
269 && len <= strlen (string_list[i]))
270 {
271 match = i;
272 if (len == strlen (string_list[i]))
273 {
274 /* exact match... */
275 if (strcmp (value, string_list[i]) != 0)
276 /* ...but case differs */
277 strcpy (value, string_list[match]);
278 return SANE_STATUS_GOOD;
279 }
280 ++num_matches;
281 }
282
283 if (num_matches > 1)
284 return SANE_STATUS_INVAL;
285 else if (num_matches == 1)
286 {
287 strcpy (value, string_list[match]);
288 return SANE_STATUS_GOOD;
289 }
290 return SANE_STATUS_INVAL;
291
292 case SANE_CONSTRAINT_NONE:
293 switch (opt->type)
294 {
295 case SANE_TYPE_BOOL:
296 b = *(SANE_Bool *) value;
297 if (b != SANE_TRUE && b != SANE_FALSE)
298 return SANE_STATUS_INVAL;
299 break;
300 default:
301 break;
302 }
303 default:
304 break;
305 }
306 return SANE_STATUS_GOOD;
307 }
308