]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cups/array.c
Merge changes from CUPS 1.4svn-r7696.
[thirdparty/cups.git] / cups / array.c
index b792c465c5c9d8a14cd66a4885d3537197756e60..ae45eeba09a5739a9444b90eef396a44b90ad835 100644 (file)
@@ -1,25 +1,16 @@
 /*
- * "$Id: array.c 6123 2006-11-21 15:36:04Z mike $"
+ * "$Id: array.c 7616 2008-05-28 00:34:13Z mike $"
  *
  *   Sorted array routines for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 1997-2006 by Easy Software Products.
+ *   Copyright 2007-2008 by Apple Inc.
+ *   Copyright 1997-2007 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
- *   property of Easy Software Products and are protected by Federal
- *   copyright law.  Distribution and use rights are outlined in the file
- *   "LICENSE.txt" which should have been included with this file.  If this
- *   file is missing or damaged please contact Easy Software Products
- *   at:
- *
- *       Attn: CUPS Licensing Information
- *       Easy Software Products
- *       44141 Airport View Drive, Suite 204
- *       Hollywood, Maryland 20636 USA
- *
- *       Voice: (301) 373-9600
- *       EMail: cups-info@cups.org
- *         WWW: http://www.cups.org
+ *   property of Apple Inc. and are protected by Federal copyright
+ *   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
+ *   which should have been included with this file.  If this file is
+ *   file is missing or damaged, see the license at "http://www.cups.org/".
  *
  *   This file is subject to the Apple OS-Developed Software exception.
  *
@@ -90,6 +81,9 @@ struct _cups_array_s                  /**** CUPS array structure ****/
   void                 **elements;     /* Array elements */
   cups_array_func_t    compare;        /* Element comparison function */
   void                 *data;          /* User data passed to compare */
+  cups_ahash_func_t    hashfunc;       /* Hash function */
+  int                  hashsize,       /* Size of hash */
+                       *hash;          /* Hash array */
 };
 
 
@@ -105,8 +99,10 @@ static int  cups_array_find(cups_array_t *a, void *e, int prev, int *rdiff);
  * 'cupsArrayAdd()' - Add an element to the array.
  *
  * When adding an element to a sorted array, non-unique elements are
- * appended at the end of the run.  For unsorted arrays, the element
- * is inserted at the end of the array.
+ * appended at the end of the run of identical elements.  For unsorted arrays,
+ * the element is appended to the end of the array.
+ *
+ * @since CUPS 1.2@
  */
 
 int                                    /* O - 1 on success, 0 on failure */
@@ -135,6 +131,12 @@ cupsArrayAdd(cups_array_t *a,              /* I - Array */
 
 /*
  * 'cupsArrayClear()' - Clear the array.
+ *
+ * This function is equivalent to removing all elements in the array.
+ * The caller is responsible for freeing the memory used by the
+ * elements themselves.
+ *
+ * @since CUPS 1.2@
  */
 
 void
@@ -162,6 +164,8 @@ cupsArrayClear(cups_array_t *a)             /* I - Array */
 
 /*
  * 'cupsArrayCount()' - Get the number of elements in the array.
+ *
+ * @since CUPS 1.2@
  */
 
 int                                    /* O - Number of elements */
@@ -184,6 +188,11 @@ cupsArrayCount(cups_array_t *a)            /* I - Array */
 
 /*
  * 'cupsArrayCurrent()' - Return the current element in the array.
+ *
+ * The current element is undefined until you call @link cupsArrayFind@,
+ * @link cupsArrayFirst@, or @link cupsArrayIndex@, or @link cupsArrayLast@.
+ *
+ * @since CUPS 1.2@
  */
 
 void *                                 /* O - Element */
@@ -209,6 +218,11 @@ cupsArrayCurrent(cups_array_t *a)  /* I - Array */
 
 /*
  * 'cupsArrayDelete()' - Free all memory used by the array.
+ *
+ * The caller is responsible for freeing the memory used by the
+ * elements themselves.
+ *
+ * @since CUPS 1.2@
  */
 
 void
@@ -229,12 +243,17 @@ cupsArrayDelete(cups_array_t *a)  /* I - Array */
   if (a->alloc_elements)
     free(a->elements);
 
+  if (a->hashsize)
+    free(a->hash);
+
   free(a);
 }
 
 
 /*
  * 'cupsArrayDup()' - Duplicate the array.
+ *
+ * @since CUPS 1.2@
  */
 
 cups_array_t *                         /* O - Duplicate array */
@@ -299,14 +318,17 @@ cupsArrayDup(cups_array_t *a)             /* I - Array */
 
 /*
  * 'cupsArrayFind()' - Find an element in the array.
+ *
+ * @since CUPS 1.2@
  */
 
-void *                                 /* O - Element found or NULL */
+void *                                 /* O - Element found or @code NULL@ */
 cupsArrayFind(cups_array_t *a,         /* I - Array */
               void         *e)         /* I - Element */
 {
   int  current,                        /* Current element */
-       diff;                           /* Difference */
+       diff,                           /* Difference */
+       hash;                           /* Hash index */
 
 
  /*
@@ -327,7 +349,30 @@ cupsArrayFind(cups_array_t *a,             /* I - Array */
   * Yes, look for a match...
   */
 
-  current = cups_array_find(a, e, a->current, &diff);
+  if (a->hash)
+  {
+    hash = (*(a->hashfunc))(e, a->data);
+
+    if (hash < 0 || hash >= a->hashsize)
+    {
+      current = a->current;
+      hash    = -1;
+    }
+    else
+    {
+      current = a->hash[hash];
+
+      if (current < 0 || current >= a->num_elements)
+        current = a->current;
+    }
+  }
+  else
+  {
+    current = a->current;
+    hash    = -1;
+  }
+
+  current = cups_array_find(a, e, current, &diff);
   if (!diff)
   {
    /*
@@ -348,6 +393,9 @@ cupsArrayFind(cups_array_t *a,              /* I - Array */
 
     a->current = current;
 
+    if (hash >= 0)
+      a->hash[hash] = current;
+
     return (a->elements[current]);
   }
   else
@@ -365,9 +413,11 @@ cupsArrayFind(cups_array_t *a,             /* I - Array */
 
 /*
  * 'cupsArrayFirst()' - Get the first element in the array.
+ *
+ * @since CUPS 1.2@
  */
 
-void *                                 /* O - First element or NULL */
+void *                                 /* O - First element or @code NULL@ if the array is empty */
 cupsArrayFirst(cups_array_t *a)                /* I - Array */
 {
  /*
@@ -390,10 +440,13 @@ cupsArrayFirst(cups_array_t *a)           /* I - Array */
 /*
  * 'cupsArrayGetIndex()' - Get the index of the current element.
  *
+ * The current element is undefined until you call @link cupsArrayFind@,
+ * @link cupsArrayFirst@, or @link cupsArrayIndex@, or @link cupsArrayLast@.
+ *
  * @since CUPS 1.3@
  */
 
-int                                    /* O - Index of the current element */
+int                                    /* O - Index of the current element, starting at 0 */
 cupsArrayGetIndex(cups_array_t *a)     /* I - Array */
 {
   if (!a)
@@ -409,7 +462,7 @@ cupsArrayGetIndex(cups_array_t *a)  /* I - Array */
  * @since CUPS 1.3@
  */
 
-int                                    /* O - Index of the last inserted element */
+int                                    /* O - Index of the last inserted element, starting at 0 */
 cupsArrayGetInsert(cups_array_t *a)    /* I - Array */
 {
   if (!a)
@@ -421,9 +474,11 @@ cupsArrayGetInsert(cups_array_t *a)        /* I - Array */
 
 /*
  * 'cupsArrayIndex()' - Get the N-th element in the array.
+ *
+ * @since CUPS 1.2@
  */
 
-void *                                 /* O - N-th element or NULL */
+void *                                 /* O - N-th element or @code NULL@ */
 cupsArrayIndex(cups_array_t *a,                /* I - Array */
                int          n)         /* I - Index into array, starting at 0 */
 {
@@ -440,8 +495,10 @@ cupsArrayIndex(cups_array_t *a,            /* I - Array */
  * 'cupsArrayInsert()' - Insert an element in the array.
  *
  * When inserting an element in a sorted array, non-unique elements are
- * inserted at the beginning of the run.  For unsorted arrays, the element
- * is inserted at the beginning of the array.
+ * inserted at the beginning of the run of identical elements.  For unsorted
+ * arrays, the element is inserted at the beginning of the array.
+ *
+ * @since CUPS 1.2@
  */
 
 int                                    /* O - 0 on failure, 1 on success */
@@ -470,9 +527,11 @@ cupsArrayInsert(cups_array_t *a,   /* I - Array */
 
 /*
  * 'cupsArrayLast()' - Get the last element in the array.
+ *
+ * @since CUPS 1.2@
  */
 
-void *                                 /* O - Last element or NULL */
+void *                                 /* O - Last element or @code NULL@ if the array is empty */
 cupsArrayLast(cups_array_t *a)         /* I - Array */
 {
  /*
@@ -494,11 +553,42 @@ cupsArrayLast(cups_array_t *a)            /* I - Array */
 
 /*
  * 'cupsArrayNew()' - Create a new array.
+ *
+ * The comparison function ("f") is used to create a sorted array. The function
+ * receives pointers to two elements and the user data pointer ("d") - the user
+ * data pointer argument can safely be omitted when not required so functions
+ * like @code strcmp@ can be used for sorted string arrays.
+ *
+ * @since CUPS 1.2@
  */
 
 cups_array_t *                         /* O - Array */
-cupsArrayNew(cups_array_func_t f,      /* I - Comparison function */
-             void              *d)     /* I - User data */
+cupsArrayNew(cups_array_func_t f,      /* I - Comparison function or @code NULL@ for an unsorted array */
+             void              *d)     /* I - User data pointer or @code NULL@ */
+{
+  return (cupsArrayNew2(f, d, 0, 0));
+}
+
+
+/*
+ * 'cupsArrayNew2()' - Create a new array with hash.
+ *
+ * The comparison function ("f") is used to create a sorted array. The function
+ * receives pointers to two elements and the user data pointer ("d") - the user
+ * data pointer argument can safely be omitted when not required so functions
+ * like @code strcmp@ can be used for sorted string arrays.
+ *
+ * The hash function ("h") is used to implement cached lookups with the
+ * specified hash size ("hsize").
+ *
+ * @since CUPS 1.3@
+ */
+
+cups_array_t *                         /* O - Array */
+cupsArrayNew2(cups_array_func_t  f,    /* I - Comparison function or @code NULL@ for an unsorted array */
+              void               *d,   /* I - User data or @code NULL@ */
+              cups_ahash_func_t  h,    /* I - Hash function or @code NULL@ for unhashed lookups */
+             int                hsize) /* I - Hash size (>= 0) */
 {
   cups_array_t *a;                     /* Array  */
 
@@ -518,15 +608,38 @@ cupsArrayNew(cups_array_func_t f, /* I - Comparison function */
   a->num_saved = 0;
   a->unique    = 1;
 
+  if (hsize > 0 && h)
+  {
+    a->hashfunc  = h;
+    a->hashsize  = hsize;
+    a->hash      = malloc(hsize * sizeof(int));
+
+    if (!a->hash)
+    {
+      free(a);
+      return (NULL);
+    }
+
+    memset(a->hash, -1, hsize * sizeof(int));
+  }
+
   return (a);
 }
 
 
 /*
  * 'cupsArrayNext()' - Get the next element in the array.
+ *
+ * This function is equivalent to "cupsArrayIndex(a, cupsArrayGetIndex(a) + 1)".
+ *
+ * The next element is undefined until you call @link cupsArrayFind@,
+ * @link cupsArrayFirst@, or @link cupsArrayIndex@, or @link cupsArrayLast@
+ * to set the current element.
+ *
+ * @since CUPS 1.2@
  */
 
-void *                                 /* O - Next element or NULL */
+void *                                 /* O - Next element or @code NULL@ */
 cupsArrayNext(cups_array_t *a)         /* I - Array */
 {
  /*
@@ -549,9 +662,17 @@ cupsArrayNext(cups_array_t *a)             /* I - Array */
 
 /*
  * 'cupsArrayPrev()' - Get the previous element in the array.
+ *
+ * This function is equivalent to "cupsArrayIndex(a, cupsArrayGetIndex(a) - 1)".
+ *
+ * The previous element is undefined until you call @link cupsArrayFind@,
+ * @link cupsArrayFirst@, or @link cupsArrayIndex@, or @link cupsArrayLast@
+ * to set the current element.
+ *
+ * @since CUPS 1.2@
  */
 
-void *                                 /* O - Previous element or NULL */
+void *                                 /* O - Previous element or @code NULL@ */
 cupsArrayPrev(cups_array_t *a)         /* I - Array */
 {
  /*
@@ -574,6 +695,14 @@ cupsArrayPrev(cups_array_t *a)             /* I - Array */
 
 /*
  * 'cupsArrayRemove()' - Remove an element from the array.
+ *
+ * If more than one element matches "e", only the first matching element is
+ * removed.
+ *
+ * The caller is responsible for freeing the memory used by the
+ * removed element.
+ *
+ * @since CUPS 1.2@
  */
 
 int                                    /* O - 1 on success, 0 on failure */
@@ -633,7 +762,9 @@ cupsArrayRemove(cups_array_t *a,    /* I - Array */
 
 
 /*
- * 'cupsArrayRestore()' - Reset the current element to the last cupsArraySave.
+ * 'cupsArrayRestore()' - Reset the current element to the last @link cupsArraySave@.
+ *
+ * @since CUPS 1.2@
  */
 
 void *                                 /* O - New current element */
@@ -656,9 +787,15 @@ cupsArrayRestore(cups_array_t *a)  /* I - Array */
 
 
 /*
- * 'cupsArraySave()' - Mark the current element for a later cupsArrayRestore.
+ * 'cupsArraySave()' - Mark the current element for a later @link cupsArrayRestore@.
+ *
+ * The current element is undefined until you call @link cupsArrayFind@,
+ * @link cupsArrayFirst@, or @link cupsArrayIndex@, or @link cupsArrayLast@
+ * to set the current element.
  *
  * The save/restore stack is guaranteed to be at least 32 elements deep.
+ *
+ * @since CUPS 1.2@
  */
 
 int                                    /* O - 1 on success, 0 on failure */
@@ -679,6 +816,8 @@ cupsArraySave(cups_array_t *a)              /* I - Array */
 
 /*
  * 'cupsArrayUserData()' - Return the user data for an array.
+ *
+ * @since CUPS 1.2@
  */
 
 void *                                 /* O - User data */
@@ -693,6 +832,8 @@ cupsArrayUserData(cups_array_t *a)  /* I - Array */
 
 /*
  * 'cups_array_add()' - Insert or append an element to the array...
+ *
+ * @since CUPS 1.2@
  */
 
 static int                             /* O - 1 on success, 0 on failure */
@@ -841,7 +982,7 @@ cups_array_add(cups_array_t *a,             /* I - Array */
   }
 #ifdef DEBUG
   else
-    printf("cups_array_add: append element at %d...\n", current);
+    DEBUG_printf(("cups_array_add: append element at %d...\n", current));
 #endif /* DEBUG */
 
   a->elements[current] = e;
@@ -850,7 +991,8 @@ cups_array_add(cups_array_t *a,             /* I - Array */
 
 #ifdef DEBUG
   for (current = 0; current < a->num_elements; current ++)
-    printf("cups_array_add: a->elements[%d]=%p\n", current, a->elements[current]);
+    DEBUG_printf(("cups_array_add: a->elements[%d]=%p\n", current,
+                  a->elements[current]));
 #endif /* DEBUG */
 
   DEBUG_puts("cups_array_add: returning 1");
@@ -861,6 +1003,8 @@ cups_array_add(cups_array_t *a,            /* I - Array */
 
 /*
  * 'cups_array_find()' - Find an element in the array...
+ *
+ * @since CUPS 1.2@
  */
 
 static int                             /* O - Index of match */
@@ -998,5 +1142,5 @@ cups_array_find(cups_array_t *a,   /* I - Array */
 
 
 /*
- * End of "$Id: array.c 6123 2006-11-21 15:36:04Z mike $".
+ * End of "$Id: array.c 7616 2008-05-28 00:34:13Z mike $".
  */