kopia lustrzana https://gitlab.com/sane-project/backends
				
				
				
			
		
			
				
	
	
		
			308 wiersze
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			308 wiersze
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
/* sane - Scanner Access Now Easy.
 | 
						|
   Copyright (C) 1996, 1997 David Mosberger-Tang and Andreas Beck
 | 
						|
   This file is part of the SANE package.
 | 
						|
 | 
						|
   This program is free software; you can redistribute it and/or
 | 
						|
   modify it under the terms of the GNU General Public License as
 | 
						|
   published by the Free Software Foundation; either version 2 of the
 | 
						|
   License, or (at your option) any later version.
 | 
						|
 | 
						|
   This program is distributed in the hope that it will be useful, but
 | 
						|
   WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
   General Public License for more details.
 | 
						|
 | 
						|
   You should have received a copy of the GNU General Public License
 | 
						|
   along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
						|
 | 
						|
   As a special exception, the authors of SANE give permission for
 | 
						|
   additional uses of the libraries contained in this release of SANE.
 | 
						|
 | 
						|
   The exception is that, if you link a SANE library with other files
 | 
						|
   to produce an executable, this does not by itself cause the
 | 
						|
   resulting executable to be covered by the GNU General Public
 | 
						|
   License.  Your use of that executable is in no way restricted on
 | 
						|
   account of linking the SANE library code into it.
 | 
						|
 | 
						|
   This exception does not, however, invalidate any other reasons why
 | 
						|
   the executable file might be covered by the GNU General Public
 | 
						|
   License.
 | 
						|
 | 
						|
   If you submit changes to SANE to the maintainers to be included in
 | 
						|
   a subsequent release, you agree by submitting the changes that
 | 
						|
   those changes may be distributed with this exception intact.
 | 
						|
 | 
						|
   If you write modifications of your own for SANE, it is your choice
 | 
						|
   whether to permit this exception to apply to your modifications.
 | 
						|
   If you do not wish that, delete this exception notice.  */
 | 
						|
 | 
						|
#include "../include/sane/config.h"
 | 
						|
 | 
						|
#include <string.h>
 | 
						|
 | 
						|
#include <sys/types.h>
 | 
						|
#include <stdlib.h>
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
 | 
						|
#include "../include/sane/sane.h"
 | 
						|
#include "../include/sane/sanei.h"
 | 
						|
 | 
						|
SANE_Status
 | 
						|
sanei_check_value (const SANE_Option_Descriptor * opt, void *value)
 | 
						|
{
 | 
						|
  const SANE_String_Const *string_list;
 | 
						|
  const SANE_Word *word_list;
 | 
						|
  int i, count;
 | 
						|
  const SANE_Range *range;
 | 
						|
  SANE_Word w, v, *array;
 | 
						|
  SANE_Bool *barray;
 | 
						|
  size_t len;
 | 
						|
 | 
						|
  switch (opt->constraint_type)
 | 
						|
    {
 | 
						|
    case SANE_CONSTRAINT_RANGE:
 | 
						|
 | 
						|
      /* single values are treated as arrays of length 1 */
 | 
						|
      array = (SANE_Word *) value;
 | 
						|
 | 
						|
      /* compute number of elements */
 | 
						|
      if (opt->size > 0)
 | 
						|
	{
 | 
						|
	  count = opt->size / sizeof (SANE_Word);
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  count = 1;
 | 
						|
	}
 | 
						|
 | 
						|
      range = opt->constraint.range;
 | 
						|
      /* for each element of the array, we check according to the constraint */
 | 
						|
      for (i = 0; i < count; i++)
 | 
						|
	{
 | 
						|
	  /* test for min and max */
 | 
						|
	  if (array[i] < range->min || array[i] > range->max)
 | 
						|
	    return SANE_STATUS_INVAL;
 | 
						|
 | 
						|
	  /* check quantization */
 | 
						|
	  if (range->quant)
 | 
						|
	    {
 | 
						|
	      v =
 | 
						|
		(unsigned int) (array[i] - range->min +
 | 
						|
				range->quant / 2) / range->quant;
 | 
						|
	      v = v * range->quant + range->min;
 | 
						|
	      if (v != array[i])
 | 
						|
		return SANE_STATUS_INVAL;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
      break;
 | 
						|
 | 
						|
    case SANE_CONSTRAINT_WORD_LIST:
 | 
						|
      w = *(SANE_Word *) value;
 | 
						|
      word_list = opt->constraint.word_list;
 | 
						|
      for (i = 1; w != word_list[i]; ++i)
 | 
						|
	if (i >= word_list[0])
 | 
						|
	  return SANE_STATUS_INVAL;
 | 
						|
      break;
 | 
						|
 | 
						|
    case SANE_CONSTRAINT_STRING_LIST:
 | 
						|
      string_list = opt->constraint.string_list;
 | 
						|
      len = strlen (value);
 | 
						|
 | 
						|
      for (i = 0; string_list[i]; ++i)
 | 
						|
	if (strncmp (value, string_list[i], len) == 0
 | 
						|
	    && len == strlen (string_list[i]))
 | 
						|
	  return SANE_STATUS_GOOD;
 | 
						|
      return SANE_STATUS_INVAL;
 | 
						|
 | 
						|
    case SANE_CONSTRAINT_NONE:
 | 
						|
      switch (opt->type)
 | 
						|
	{
 | 
						|
	case SANE_TYPE_BOOL:
 | 
						|
	  /* single values are treated as arrays of length 1 */
 | 
						|
	  array = (SANE_Word *) value;
 | 
						|
 | 
						|
	  /* compute number of elements */
 | 
						|
	  if (opt->size > 0)
 | 
						|
	    {
 | 
						|
	      count = opt->size / sizeof (SANE_Bool);
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      count = 1;
 | 
						|
	    }
 | 
						|
 | 
						|
	  barray = (SANE_Bool *) value;
 | 
						|
 | 
						|
	  /* test each boolean value in the array */
 | 
						|
	  for (i = 0; i < count; i++)
 | 
						|
	    {
 | 
						|
	      if (barray[i] != SANE_TRUE && barray[i] != SANE_FALSE)
 | 
						|
		return SANE_STATUS_INVAL;
 | 
						|
	    }
 | 
						|
	  break;
 | 
						|
	default:
 | 
						|
	  break;
 | 
						|
	}
 | 
						|
 | 
						|
    default:
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * This function apply the constraint defined by the option descriptor
 | 
						|
 * to the given value, and update the info flags holder if needed. It
 | 
						|
 * return SANE_STATUS_INVAL if the constraint cannot be applied, else
 | 
						|
 * it returns SANE_STATUS_GOOD.
 | 
						|
 */
 | 
						|
SANE_Status
 | 
						|
sanei_constrain_value (const SANE_Option_Descriptor * opt, void *value,
 | 
						|
		       SANE_Word * info)
 | 
						|
{
 | 
						|
  const SANE_String_Const *string_list;
 | 
						|
  const SANE_Word *word_list;
 | 
						|
  int i, k, num_matches, match;
 | 
						|
  const SANE_Range *range;
 | 
						|
  SANE_Word w, v, *array;
 | 
						|
  SANE_Bool b;
 | 
						|
  size_t len;
 | 
						|
 | 
						|
  switch (opt->constraint_type)
 | 
						|
    {
 | 
						|
    case SANE_CONSTRAINT_RANGE:
 | 
						|
 | 
						|
      /* single values are treated as arrays of length 1 */
 | 
						|
      array = (SANE_Word *) value;
 | 
						|
 | 
						|
      /* compute number of elements */
 | 
						|
      if (opt->size > 0)
 | 
						|
	{
 | 
						|
	  k = opt->size / sizeof (SANE_Word);
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  k = 1;
 | 
						|
	}
 | 
						|
 | 
						|
      range = opt->constraint.range;
 | 
						|
      /* for each element of the array, we apply the constraint */
 | 
						|
      for (i = 0; i < k; i++)
 | 
						|
	{
 | 
						|
	  /* constrain min */
 | 
						|
	  if (array[i] < range->min)
 | 
						|
	    {
 | 
						|
	      array[i] = range->min;
 | 
						|
	      if (info)
 | 
						|
		{
 | 
						|
		  *info |= SANE_INFO_INEXACT;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
 | 
						|
	  /* constrain max */
 | 
						|
	  if (array[i] > range->max)
 | 
						|
	    {
 | 
						|
	      array[i] = range->max;
 | 
						|
	      if (info)
 | 
						|
		{
 | 
						|
		  *info |= SANE_INFO_INEXACT;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
 | 
						|
	  /* quantization */
 | 
						|
	  if (range->quant)
 | 
						|
	    {
 | 
						|
	      v =
 | 
						|
		(unsigned int) (array[i] - range->min +
 | 
						|
				range->quant / 2) / range->quant;
 | 
						|
	      v = v * range->quant + range->min;
 | 
						|
	      /* due to rounding issues with sane 'fixed' values,
 | 
						|
	       * the computed value may exceed max */
 | 
						|
	      if (v > range->max)
 | 
						|
	        {
 | 
						|
		  v = range->max;
 | 
						|
	        }
 | 
						|
	      if (v != array[i])
 | 
						|
		{
 | 
						|
		  array[i] = v;
 | 
						|
		  if (info)
 | 
						|
		    *info |= SANE_INFO_INEXACT;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
      break;
 | 
						|
 | 
						|
    case SANE_CONSTRAINT_WORD_LIST:
 | 
						|
      /* If there is no exact match in the list, use the nearest value */
 | 
						|
      w = *(SANE_Word *) value;
 | 
						|
      word_list = opt->constraint.word_list;
 | 
						|
      for (i = 1, k = 1, v = abs (w - word_list[1]); i <= word_list[0]; i++)
 | 
						|
	{
 | 
						|
	  SANE_Word vh;
 | 
						|
	  if ((vh = abs (w - word_list[i])) < v)
 | 
						|
	    {
 | 
						|
	      v = vh;
 | 
						|
	      k = i;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
      if (w != word_list[k])
 | 
						|
	{
 | 
						|
	  *(SANE_Word *) value = word_list[k];
 | 
						|
	  if (info)
 | 
						|
	    *info |= SANE_INFO_INEXACT;
 | 
						|
	}
 | 
						|
      break;
 | 
						|
 | 
						|
    case SANE_CONSTRAINT_STRING_LIST:
 | 
						|
      /* Matching algorithm: take the longest unique match ignoring
 | 
						|
         case.  If there is an exact match, it is admissible even if
 | 
						|
         the same string is a prefix of a longer option name. */
 | 
						|
      string_list = opt->constraint.string_list;
 | 
						|
      len = strlen (value);
 | 
						|
 | 
						|
      /* count how many matches of length LEN characters we have: */
 | 
						|
      num_matches = 0;
 | 
						|
      match = -1;
 | 
						|
      for (i = 0; string_list[i]; ++i)
 | 
						|
	if (strncasecmp (value, string_list[i], len) == 0
 | 
						|
	    && len <= strlen (string_list[i]))
 | 
						|
	  {
 | 
						|
	    match = i;
 | 
						|
	    if (len == strlen (string_list[i]))
 | 
						|
	      {
 | 
						|
		/* exact match... */
 | 
						|
		if (strcmp (value, string_list[i]) != 0)
 | 
						|
		  /* ...but case differs */
 | 
						|
		  strcpy (value, string_list[match]);
 | 
						|
		return SANE_STATUS_GOOD;
 | 
						|
	      }
 | 
						|
	    ++num_matches;
 | 
						|
	  }
 | 
						|
 | 
						|
      if (num_matches > 1)
 | 
						|
	return SANE_STATUS_INVAL;
 | 
						|
      else if (num_matches == 1)
 | 
						|
	{
 | 
						|
	  strcpy (value, string_list[match]);
 | 
						|
	  return SANE_STATUS_GOOD;
 | 
						|
	}
 | 
						|
      return SANE_STATUS_INVAL;
 | 
						|
 | 
						|
    case SANE_CONSTRAINT_NONE:
 | 
						|
      switch (opt->type)
 | 
						|
	{
 | 
						|
	case SANE_TYPE_BOOL:
 | 
						|
	  b = *(SANE_Bool *) value;
 | 
						|
	  if (b != SANE_TRUE && b != SANE_FALSE)
 | 
						|
	    return SANE_STATUS_INVAL;
 | 
						|
	  break;
 | 
						|
	default:
 | 
						|
	  break;
 | 
						|
	}
 | 
						|
    default:
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 |