• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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