]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Merge ppdConflicts() optimizations and new hashed array support
authormike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Wed, 25 Apr 2007 19:55:45 +0000 (19:55 +0000)
committermike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Wed, 25 Apr 2007 19:55:45 +0000 (19:55 +0000)
(STR #2358)

cups/array.c:
    - Add hash data to _cups_array_s.
    - cupsArrayDelete(): Free hash array.
    - cupsArrayFind(): Use hash array.
    - cupsArrayNew(): Call cupsArrayNew2().
    - cupsArrayNew2(): Added.

cups/array.h:
    - Add cups_ahash_func_t definition for hash functions.
    - Add cupsArrayNew2() with hash function and hash size
      arguments.

cups/mark.c:
    - ppdConflicts(): Cache the last

cups/ppd.c:
    - ppdClose(): Destroy "marked" array.
    - ppdOpen2(): Create "marked" array for marked options, use a
      hash for the options array for faster lookups, and sort the
      UIConstraints.
    - ppd_compare_choices(): Added.
    - ppd_compare_consts(): Added.
    - ppd_hash_option(): Added.

cups/ppd.h:
    - Add "marked" array to ppd_file_t.

git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@6477 7a7537e8-13f0-0310-91df-b6672ffda945

CHANGES.txt
cups/array.c
cups/array.h
cups/mark.c
cups/ppd.c
cups/ppd.h

index 45602a84df6244dca41e5325d552231da28bed7c..65d9cab749ea15facb2712cdd9c8d79e847744e2 100644 (file)
@@ -1,9 +1,12 @@
-CHANGES.txt - 2007-04-04
+CHANGES.txt - 2007-04-25
 ------------------------
 
 CHANGES IN CUPS V1.3
 
        - Documentation updates (STR #1775, STR #2130, STR #2131)
+        - Add new cupsArrayNew2() API to support hashed lookups
+          of array elements (STR #2358)
+        - ppdConflicts() optimizations (STR #2358)
        - The cupstestppd program now tests for existing filters,
          icons, profiles, and dialog extensions (STR #2326)
        - The web interface no longer lists new printers on the
index 259d1089db5f1b2b98c42da940e00d49c890cec8..dc796d6e2109d38c580e87252510c79c0de4ed1f 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Sorted array routines for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 1997-2006 by Easy Software Products.
+ *   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
@@ -90,6 +90,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 */
 };
 
 
@@ -229,6 +232,9 @@ cupsArrayDelete(cups_array_t *a)    /* I - Array */
   if (a->alloc_elements)
     free(a->elements);
 
+  if (a->hashsize)
+    free(a->hash);
+
   free(a);
 }
 
@@ -306,7 +312,8 @@ cupsArrayFind(cups_array_t *a,              /* I - Array */
               void         *e)         /* I - Element */
 {
   int  current,                        /* Current element */
-       diff;                           /* Difference */
+       diff,                           /* Difference */
+       hash;                           /* Hash index */
 
 
  /*
@@ -327,7 +334,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 +378,9 @@ cupsArrayFind(cups_array_t *a,              /* I - Array */
 
     a->current = current;
 
+    if (hash >= 0)
+      a->hash[hash] = current;
+
     return (a->elements[current]);
   }
   else
@@ -499,6 +532,22 @@ cupsArrayLast(cups_array_t *a)             /* I - Array */
 cups_array_t *                         /* O - Array */
 cupsArrayNew(cups_array_func_t f,      /* I - Comparison function */
              void              *d)     /* I - User data */
+{
+  return (cupsArrayNew2(f, d, 0, 0));
+}
+
+
+/*
+ * 'cupsArrayNew2()' - Create a new array with hash.
+ *
+ * @since CUPS 1.3@
+ */
+
+cups_array_t *                         /* O - Array */
+cupsArrayNew2(cups_array_func_t  f,    /* I - Comparison function */
+              void               *d,   /* I - User data */
+              cups_ahash_func_t  h,    /* I - Hash function*/
+             int                hsize) /* I - Hash size */
 {
   cups_array_t *a;                     /* Array  */
 
@@ -518,6 +567,21 @@ 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);
 }
 
index 5a81ee85412029be8c9fae0ef1e4187fb2c17c3a..2e089a268a434990901a6eb10f12f2778c9957a1 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Sorted array definitions for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 1997-2006 by Easy Software Products.
+ *   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
@@ -51,6 +51,9 @@ typedef struct _cups_array_s cups_array_t;
                                        /**** CUPS array type ****/
 typedef int (*cups_array_func_t)(void *first, void *second, void *data);
                                        /**** Array comparison function ****/
+typedef int (*cups_ahash_func_t)(void *element, void *data);
+                                       /**** Array hash function ****/
+
 
 /*
  * Functions...
@@ -70,6 +73,8 @@ extern void           *cupsArrayIndex(cups_array_t *a, int n);
 extern int             cupsArrayInsert(cups_array_t *a, void *e);
 extern void            *cupsArrayLast(cups_array_t *a);
 extern cups_array_t    *cupsArrayNew(cups_array_func_t f, void *d);
+extern cups_array_t    *cupsArrayNew2(cups_array_func_t f, void *d,
+                                      cups_ahash_func_t h, int hsize);
 extern void            *cupsArrayNext(cups_array_t *a);
 extern void            *cupsArrayPrev(cups_array_t *a);
 extern int             cupsArrayRemove(cups_array_t *a, void *e);
index 02183fb4987fa2e36cdbd5481a9e4c55c6a9f295..77ef17d5dd9a462a522378d228cf7e09ae3c792d 100644 (file)
@@ -59,14 +59,15 @@ static void ppd_defaults(ppd_file_t *ppd, ppd_group_t *g);
  * 'ppdConflicts()' - Check to see if there are any conflicts.
  */
 
-int                            /* O - Number of conflicts found */
-ppdConflicts(ppd_file_t *ppd)  /* I - PPD to check */
+int                                    /* O - Number of conflicts found */
+ppdConflicts(ppd_file_t *ppd)          /* I - PPD to check */
 {
-  int          i, j,           /* Looping variables */
-               conflicts;      /* Number of conflicts */
-  ppd_const_t  *c;             /* Current constraint */
-  ppd_option_t *o1, *o2;       /* Options */
-  ppd_choice_t *c1, *c2;       /* Choices */
+  int          i,                      /* Looping variable */
+               conflicts;              /* Number of conflicts */
+  ppd_const_t  *c;                     /* Current constraint */
+  ppd_option_t *o1, *o2;               /* Options */
+  ppd_choice_t *c1, *c2;               /* Choices */
+  ppd_choice_t key;                    /* Search key */
 
 
   if (!ppd)
@@ -86,38 +87,45 @@ ppdConflicts(ppd_file_t *ppd)       /* I - PPD to check */
   * that conflict...
   */
 
-  for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++)
+  for (i = ppd->num_consts, c = ppd->consts, o1 = o2 = NULL, c1 = c2 = NULL;
+       i > 0;
+       i --, c ++)
   {
    /*
     * Grab pointers to the first option...
     */
 
-    o1 = ppdFindOption(ppd, c->option1);
+    if (!o1 || strcmp(c->option1, o1->keyword))
+    {
+      o1 = ppdFindOption(ppd, c->option1);
+      c1 = NULL;
+    }
 
     if (!o1)
       continue;
-    else if (c->choice1[0])
+    else if (c->choice1[0] && (!c1 || strcmp(c->choice1, c1->choice)))
     {
      /*
       * This constraint maps to a specific choice.
       */
 
-      c1 = ppdFindChoice(o1, c->choice1);
+      key.option = o1;
+
+      if ((c1 = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL &&
+          !c1->marked)
+        c1 = NULL;
     }
-    else
+    else if (!c1)
     {
      /*
       * This constraint applies to any choice for this option.
       */
 
-      for (j = o1->num_choices, c1 = o1->choices; j > 0; j --, c1 ++)
-        if (c1->marked)
-         break;
+      key.option = o1;
 
-      if (!j ||
-          !strcasecmp(c1->choice, "None") ||
-          !strcasecmp(c1->choice, "Off") ||
-          !strcasecmp(c1->choice, "False"))
+      if ((c1 = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL &&
+          (!strcasecmp(c1->choice, "None") || !strcasecmp(c1->choice, "Off") ||
+           !strcasecmp(c1->choice, "False")))
         c1 = NULL;
     }
 
@@ -125,32 +133,37 @@ ppdConflicts(ppd_file_t *ppd)     /* I - PPD to check */
     * Grab pointers to the second option...
     */
 
-    o2 = ppdFindOption(ppd, c->option2);
+    if (!o2 || strcmp(c->option2, o2->keyword))
+    {
+      o2 = ppdFindOption(ppd, c->option2);
+      c2 = NULL;
+    }
 
     if (!o2)
       continue;
-    else if (c->choice2[0])
+    else if (c->choice2[0] && (!c2 || strcmp(c->choice2, c2->choice)))
     {
      /*
       * This constraint maps to a specific choice.
       */
 
-      c2 = ppdFindChoice(o2, c->choice2);
+      key.option = o2;
+
+      if ((c2 = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL &&
+          !c2->marked)
+        c2 = NULL;
     }
-    else
+    else if (!c2)
     {
      /*
       * This constraint applies to any choice for this option.
       */
 
-      for (j = o2->num_choices, c2 = o2->choices; j > 0; j --, c2 ++)
-        if (c2->marked)
-         break;
+      key.option = o2;
 
-      if (!j ||
-          !strcasecmp(c2->choice, "None") ||
-          !strcasecmp(c2->choice, "Off") ||
-          !strcasecmp(c2->choice, "False"))
+      if ((c2 = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL &&
+          (!strcasecmp(c2->choice, "None") || !strcasecmp(c2->choice, "Off") ||
+           !strcasecmp(c2->choice, "False")))
         c2 = NULL;
     }
 
@@ -185,8 +198,8 @@ ppd_choice_t *                              /* O - Choice pointer or NULL */
 ppdFindChoice(ppd_option_t *o,         /* I - Pointer to option */
               const char   *choice)    /* I - Name of choice */
 {
-  int          i;              /* Looping var */
-  ppd_choice_t *c;             /* Current choice */
+  int          i;                      /* Looping var */
+  ppd_choice_t *c;                     /* Current choice */
 
 
   if (o == NULL || choice == NULL)
@@ -208,19 +221,13 @@ ppd_choice_t *                            /* O - Pointer to choice or NULL */
 ppdFindMarkedChoice(ppd_file_t *ppd,   /* I - PPD file */
                     const char *option)        /* I - Keyword/option name */
 {
-  int          i;              /* Looping var */
-  ppd_option_t *o;             /* Pointer to option */
-  ppd_choice_t *c;             /* Pointer to choice */
+  ppd_choice_t key;                    /* Search key for choice */
 
 
-  if ((o = ppdFindOption(ppd, option)) == NULL)
+  if ((key.option = ppdFindOption(ppd, option)) == NULL)
     return (NULL);
 
-  for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
-    if (c->marked)
-      return (c);
-
-  return (NULL);
+  return ((ppd_choice_t *)cupsArrayFind(ppd->marked, &key));
 }
 
 
@@ -279,25 +286,25 @@ ppdFindOption(ppd_file_t *ppd,            /* I - PPD file data */
  * 'ppdIsMarked()' - Check to see if an option is marked...
  */
 
-int                            /* O - Non-zero if option is marked */
-ppdIsMarked(ppd_file_t *ppd,   /* I - PPD file data */
-            const char *option,        /* I - Option/Keyword name */
-            const char *choice)        /* I - Choice name */
+int                                    /* O - Non-zero if option is marked */
+ppdIsMarked(ppd_file_t *ppd,           /* I - PPD file data */
+            const char *option,                /* I - Option/Keyword name */
+            const char *choice)                /* I - Choice name */
 {
-  ppd_option_t *o;             /* Option pointer */
-  ppd_choice_t *c;             /* Choice pointer */
+  ppd_choice_t key,                    /* Search key */
+               *c;                     /* Choice pointer */
 
 
-  if (ppd == NULL)
+  if (!ppd)
     return (0);
 
-  if ((o = ppdFindOption(ppd, option)) == NULL)
+  if ((key.option = ppdFindOption(ppd, option)) == NULL)
     return (0);
 
-  if ((c = ppdFindChoice(o, choice)) == NULL)
+  if ((c = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) == NULL)
     return (0);
 
-  return (c->marked);
+  return (!strcmp(c->choice, choice));
 }
 
 
@@ -306,15 +313,29 @@ ppdIsMarked(ppd_file_t *ppd,      /* I - PPD file data */
  */
 
 void
-ppdMarkDefaults(ppd_file_t *ppd)/* I - PPD file record */
+ppdMarkDefaults(ppd_file_t *ppd)       /* I - PPD file record */
 {
-  int          i;              /* Looping variables */
-  ppd_group_t  *g;             /* Current group */
+  int          i;                      /* Looping variables */
+  ppd_group_t  *g;                     /* Current group */
+  ppd_choice_t *c;                     /* Current choice */
 
 
-  if (ppd == NULL)
+  if (!ppd)
     return;
 
+ /*
+  * Clean out the marked array...
+  */
+
+  for (c = (ppd_choice_t *)cupsArrayFirst(ppd->marked);
+       c;
+       c = (ppd_choice_t *)cupsArrayNext(ppd->marked))
+    cupsArrayRemove(ppd->marked, c);
+
+ /*
+  * Then repopulate it with the defaults...
+  */
+
   for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++)
     ppd_defaults(ppd, g);
 }
@@ -336,7 +357,9 @@ ppdMarkOption(ppd_file_t *ppd,              /* I - PPD file record */
 {
   int          i, j;                   /* Looping vars */
   ppd_option_t *o;                     /* Option pointer */
-  ppd_choice_t *c;                     /* Choice pointer */
+  ppd_choice_t *c,                     /* Choice pointer */
+               *oldc,                  /* Old choice pointer */
+               key;                    /* Search key for choice */
   struct lconv *loc;                   /* Locale data */
 
 
@@ -358,8 +381,14 @@ ppdMarkOption(ppd_file_t *ppd,             /* I - PPD file record */
   if (!strcasecmp(option, "AP_D_InputSlot"))
   {
     if ((o = ppdFindOption(ppd, "InputSlot")) != NULL)
-      for (i = 0; i < o->num_choices; i ++)
-       o->choices[i].marked = 0;
+    {
+      key.option = o;
+      if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
+      {
+        oldc->marked = 0;
+        cupsArrayRemove(ppd->marked, oldc);
+      }
+    }
   }
 
  /*
@@ -542,73 +571,98 @@ ppdMarkOption(ppd_file_t *ppd,            /* I - PPD file record */
   * Option found; mark it and then handle unmarking any other options.
   */
 
-  c->marked = 1;
-
   if (o->ui != PPD_UI_PICKMANY)
   {
    /*
     * Unmark all other choices...
     */
 
-    for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
-      if (strcasecmp(c->choice, choice))
+    if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, c)) != NULL)
+    {
+      oldc->marked = 0;
+      cupsArrayRemove(ppd->marked, oldc);
+    }
+
+    if (!strcasecmp(option, "PageSize") || !strcasecmp(option, "PageRegion"))
+    {
+     /*
+      * Mark current page size...
+      */
+
+      for (j = 0; j < ppd->num_sizes; j ++)
+       ppd->sizes[j].marked = !strcasecmp(ppd->sizes[j].name,
+                                          choice);
+
+     /*
+      * Unmark the current PageSize or PageRegion setting, as
+      * appropriate...
+      */
+
+      if (!strcasecmp(option, "PageSize"))
       {
-        c->marked = 0;
+       if ((o = ppdFindOption(ppd, "PageRegion")) != NULL)
+        {
+          key.option = o;
+          if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
+          {
+            oldc->marked = 0;
+            cupsArrayRemove(ppd->marked, oldc);
+          }
+        }
+      }
+      else
+      {
+       if ((o = ppdFindOption(ppd, "PageSize")) != NULL)
+        {
+          key.option = o;
+          if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
+          {
+            oldc->marked = 0;
+            cupsArrayRemove(ppd->marked, oldc);
+          }
+        }
+      }
+    }
+    else if (!strcasecmp(option, "InputSlot"))
+    {
+     /*
+      * Unmark ManualFeed True and possibly mark ManualFeed False
+      * option...
+      */
 
-       if (!strcasecmp(option, "PageSize") ||
-           !strcasecmp(option, "PageRegion"))
-       {
-        /*
-         * Mark current page size...
-         */
-
-         for (j = 0; j < ppd->num_sizes; j ++)
-           ppd->sizes[j].marked = !strcasecmp(ppd->sizes[j].name,
-                                              choice);
-
-        /*
-         * Unmark the current PageSize or PageRegion setting, as
-         * appropriate...
-         */
-
-         if (!strcasecmp(option, "PageSize"))
-         {
-           if ((o = ppdFindOption(ppd, "PageRegion")) != NULL)
-             for (j = 0; j < o->num_choices; j ++)
-               o->choices[j].marked = 0;
-         }
-         else
-         {
-           if ((o = ppdFindOption(ppd, "PageSize")) != NULL)
-             for (j = 0; j < o->num_choices; j ++)
-               o->choices[j].marked = 0;
-         }
-       }
-       else if (!strcasecmp(option, "InputSlot"))
-       {
-        /*
-         * Unmark ManualFeed True and possibly mark ManualFeed False
-         * option...
-         */
-
-         if ((o = ppdFindOption(ppd, "ManualFeed")) != NULL)
-           for (j = 0; j < o->num_choices; j ++)
-              o->choices[j].marked = !strcasecmp(o->choices[j].choice, "False");
-       }
-       else if (!strcasecmp(option, "ManualFeed") &&
-                !strcasecmp(choice, "True"))
-       {
-        /*
-         * Unmark InputSlot option...
-         */
+      if ((o = ppdFindOption(ppd, "ManualFeed")) != NULL)
+      {
+        key.option = o;
+        if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
+        {
+          oldc->marked = 0;
+          cupsArrayRemove(ppd->marked, oldc);
+        }
+      }
+    }
+    else if (!strcasecmp(option, "ManualFeed") &&
+            !strcasecmp(choice, "True"))
+    {
+     /*
+      * Unmark InputSlot option...
+      */
 
-         if ((o = ppdFindOption(ppd, "InputSlot")) != NULL)
-           for (j = 0; j < o->num_choices; j ++)
-              o->choices[j].marked = 0;
-       }
+      if ((o = ppdFindOption(ppd, "InputSlot")) != NULL)
+      {
+        key.option = o;
+        if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
+        {
+          oldc->marked = 0;
+          cupsArrayRemove(ppd->marked, oldc);
+        }
       }
+    }
   }
 
+  c->marked = 1;
+
+  cupsArrayAdd(ppd->marked, c);
+
  /*
   * Return the number of conflicts...
   */
@@ -666,9 +720,6 @@ ppd_defaults(ppd_file_t  *ppd,      /* I - PPD file */
   ppd_group_t  *sg;            /* Current sub-group */
 
 
-  if (g == NULL)
-    return;
-
   for (i = g->num_options, o = g->options; i > 0; i --, o ++)
     if (strcasecmp(o->keyword, "PageRegion") != 0)
       ppdMarkOption(ppd, o->keyword, o->defchoice);
index 4f0d900a4d5ac1c0f6f8f5617314422606018c9a..cda1d02b42102ac65c05fde886997b484d07eaf9 100644 (file)
@@ -48,6 +48,8 @@
  *   ppd_add_choice()       - Add a choice to an option.
  *   ppd_add_size()         - Add a page size.
  *   ppd_compare_attrs()    - Compare two attributes.
+ *   ppd_compare_choices()  - Compare two choices...
+ *   ppd_compare_consts()   - Compare two constraints.
  *   ppd_compare_coptions() - Compare two custom options.
  *   ppd_compare_cparams()  - Compare two custom parameters.
  *   ppd_compare_options()  - Compare two options.
@@ -58,6 +60,7 @@
  *   ppd_get_cparam()       - Get a custom parameter record.
  *   ppd_get_group()        - Find or create the named group as needed.
  *   ppd_get_option()       - Find or create the named option as needed.
+ *   ppd_hash_option()      - Generate a hash of the option name...
  *   ppd_read()             - Read a line from a PPD file, skipping comment
  *                            lines as necessary.
  */
@@ -90,6 +93,8 @@
 #define PPD_TEXT       4               /* Line contained human-readable text */
 #define PPD_STRING     8               /* Line contained a string or code */
 
+#define PPD_HASHSIZE   512             /* Size of hash */
+
 
 /*
  * Local functions...
@@ -101,6 +106,8 @@ static ppd_attr_t   *ppd_add_attr(ppd_file_t *ppd, const char *name,
 static ppd_choice_t    *ppd_add_choice(ppd_option_t *option, const char *name);
 static ppd_size_t      *ppd_add_size(ppd_file_t *ppd, const char *name);
 static int             ppd_compare_attrs(ppd_attr_t *a, ppd_attr_t *b);
+static int             ppd_compare_choices(ppd_choice_t *a, ppd_choice_t *b);
+static int             ppd_compare_consts(ppd_const_t *a, ppd_const_t *b);
 static int             ppd_compare_coptions(ppd_coption_t *a,
                                             ppd_coption_t *b);
 static int             ppd_compare_cparams(ppd_cparam_t *a, ppd_cparam_t *b);
@@ -116,6 +123,7 @@ static ppd_group_t  *ppd_get_group(ppd_file_t *ppd, const char *name,
                                       const char *text, _cups_globals_t *cg,
                                       cups_encoding_t encoding);
 static ppd_option_t    *ppd_get_option(ppd_group_t *group, const char *name);
+static int             ppd_hash_option(ppd_option_t *option);
 static int             ppd_read(cups_file_t *fp, char *keyword, char *option,
                                 char *text, char **string, int ignoreblank,
                                 _cups_globals_t *cg);
@@ -184,6 +192,7 @@ ppdClose(ppd_file_t *ppd)           /* I - PPD file record */
   }
 
   cupsArrayDelete(ppd->options);
+  cupsArrayDelete(ppd->marked);
 
  /*
   * Free any page sizes...
@@ -1892,7 +1901,9 @@ ppdOpen2(cups_file_t *fp)         /* I - File to read from */
   * each choice and custom option...
   */
 
-  ppd->options = cupsArrayNew((cups_array_func_t)ppd_compare_options, NULL);
+  ppd->options = cupsArrayNew2((cups_array_func_t)ppd_compare_options, NULL,
+                               (cups_ahash_func_t)ppd_hash_option,
+                              PPD_HASHSIZE);
 
   for (i = ppd->num_groups, group = ppd->groups;
        i > 0;
@@ -1915,6 +1926,20 @@ ppdOpen2(cups_file_t *fp)                /* I - File to read from */
     }
   }
 
+ /*
+  * Sort the constraints...
+  */
+
+  if (ppd->num_consts > 1)
+    qsort(ppd->consts, ppd->num_consts, sizeof(ppd_const_t),
+          (int (*)(const void *, const void *))ppd_compare_consts);
+
+ /*
+  * Create an array to track the marked choices...
+  */
+
+  ppd->marked = cupsArrayNew((cups_array_func_t)ppd_compare_choices, NULL);
+
  /*
   * Return the PPD file structure...
   */
@@ -2208,6 +2233,40 @@ ppd_compare_attrs(ppd_attr_t *a, /* I - First attribute */
 }
 
 
+/*
+ * 'ppd_compare_choices()' - Compare two choices...
+ */
+
+static int                             /* O - Result of comparison */
+ppd_compare_choices(ppd_choice_t *a,   /* I - First choice */
+                    ppd_choice_t *b)   /* I - Second choice */
+{
+  return (a->option - b->option);
+}
+
+
+/*
+ * 'ppd_compare_consts()' - Compare two constraints.
+ */
+
+static int                             /* O - Result of comparison */
+ppd_compare_consts(ppd_const_t *a,     /* I - First constraint */
+                   ppd_const_t *b)     /* I - Second constraint */
+{
+  int  ret;                            /* Result of comparison */
+
+
+  if ((ret = strcmp(a->option1, b->option1)) != 0)
+    return (ret);
+  else if ((ret = strcmp(a->choice1, b->choice1)) != 0)
+    return (ret);
+  else if ((ret = strcmp(a->option2, b->option2)) != 0)
+    return (ret);
+  else
+    return (strcmp(a->choice2, b->choice2));
+}
+
+
 /*
  * 'ppd_compare_coptions()' - Compare two custom options.
  */
@@ -2545,6 +2604,24 @@ ppd_get_option(ppd_group_t *group,       /* I - Group */
 }
 
 
+/*
+ * 'ppd_hash_option()' - Generate a hash of the option name...
+ */
+
+static int                             /* O - Hash index */
+ppd_hash_option(ppd_option_t *option)  /* I - Option */
+{
+  int          hash = 0;               /* Hash index */
+  const char   *k;                     /* Pointer into keyword */
+
+
+  for (hash = option->keyword[0], k = option->keyword + 1; *k;)
+    hash = 33 * hash + *k++;
+
+  return (hash & 511);
+}
+
+
 /*
  * 'ppd_read()' - Read a line from a PPD file, skipping comment lines as
  *                necessary.
index d24db5afd4369350ab08982afcc915e5906ba2f1..6d34d6043aade29d1d74724c74bbf2be493162e0 100644 (file)
@@ -4,7 +4,7 @@
  *   PostScript Printer Description definitions for the Common UNIX Printing
  *   System (CUPS).
  *
- *   Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
  *   property of Easy Software Products and are protected by Federal
@@ -331,6 +331,9 @@ typedef struct ppd_file_s           /**** PPD File ****/
   cups_array_t *sorted_attrs;          /* Attribute lookup array @since CUPS 1.2@ @private@ */
   cups_array_t *options;               /* Option lookup array @since CUPS 1.2@ @private@ */
   cups_array_t *coptions;              /* Custom options array @since CUPS 1.2@ @private@ */
+
+  /**** New in CUPS 1.3 ****/
+  cups_array_t *marked;                /* Marked choices @since CUPS 1.3@ @private@ */
 } ppd_file_t;