From: msweet Date: Mon, 31 Mar 2014 14:10:13 +0000 (+0000) Subject: Add support for hierarchical searches (STR #4395) X-Git-Tag: v2.2b1~674 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f2a31e21814028ede8a66221ce04ecb35c38a696;p=thirdparty%2Fcups.git Add support for hierarchical searches (STR #4395) - Add "atend" and "curindex" members to ipp_t to track position in search. - Update ippFindAttribute and ippFindNextAttribute to search collections. - Add unit tests to testipp for it. git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@11783 a1ca3aef-8c08-0410-bb20-df032aa958be --- diff --git a/CHANGES.txt b/CHANGES.txt index bb17aaed41..3e38539875 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,4 @@ -CHANGES.txt - 2.0b1 - 2014-03-28 +CHANGES.txt - 2.0b1 - 2014-03-31 -------------------------------- CHANGES IN CUPS V2.0b1 @@ -31,3 +31,5 @@ CHANGES IN CUPS V2.0b1 definition in printers.conf (STR #4153) - The scheduler now allows run-as-root backends to have group read and execute permissions (STR #2935) + - The ippFindAttribute and ippFindNextAttribute functions now support + hierarchical searches (STR #4395) diff --git a/cups/ipp.c b/cups/ipp.c index e83bfd4de2..debc0e0445 100644 --- a/cups/ipp.c +++ b/cups/ipp.c @@ -1983,6 +1983,10 @@ ippDeleteValues( /* * 'ippFindAttribute()' - Find a named attribute in a request. + * + * Starting with CUPS 2.0, the attribute name can contain a hierarchical list + * of attribute and member names separated by slashes, for example + * "media-col/media-size". */ ipp_attribute_t * /* O - Matching attribute */ @@ -2001,6 +2005,7 @@ ippFindAttribute(ipp_t *ipp, /* I - IPP message */ */ ipp->current = NULL; + ipp->atend = 0; /* * Search for the attribute... @@ -2012,6 +2017,10 @@ ippFindAttribute(ipp_t *ipp, /* I - IPP message */ /* * 'ippFindNextAttribute()' - Find the next named attribute in a request. + * + * Starting with CUPS 2.0, the attribute name can contain a hierarchical list + * of attribute and member names separated by slashes, for example + * "media-col/media-size". */ ipp_attribute_t * /* O - Matching attribute */ @@ -2019,8 +2028,11 @@ ippFindNextAttribute(ipp_t *ipp, /* I - IPP message */ const char *name, /* I - Name of attribute */ ipp_tag_t type) /* I - Type of attribute */ { - ipp_attribute_t *attr; /* Current atttribute */ + ipp_attribute_t *attr, /* Current atttribute */ + *childattr; /* Child attribute */ ipp_tag_t value_tag; /* Value tag */ + char parent[1024], /* Parent attribute name */ + *child; /* Child attribute name */ DEBUG_printf(("2ippFindNextAttribute(ipp=%p, name=\"%s\", type=%02x(%s))", @@ -2029,7 +2041,60 @@ ippFindNextAttribute(ipp_t *ipp, /* I - IPP message */ if (!ipp || !name) return (NULL); - if (ipp->current) + DEBUG_printf(("3ippFindNextAttribute: atend=%d", ipp->atend)); + + if (ipp->atend) + return (NULL); + + if (strchr(name, '/')) + { + /* + * Search for child attribute... + */ + + strlcpy(parent, name, sizeof(parent)); + if ((child = strchr(parent, '/')) == NULL) + { + DEBUG_puts("3ippFindNextAttribute: Attribute name too long."); + return (NULL); + } + + *child++ = '\0'; + + if (ipp->current && ipp->current->name && ipp->current->value_tag == IPP_TAG_BEGIN_COLLECTION && !strcmp(parent, ipp->current->name)) + { + while (ipp->curindex < ipp->current->num_values) + { + if ((childattr = ippFindNextAttribute(ipp->current->values[ipp->curindex].collection, child, type)) != NULL) + return (childattr); + + ipp->curindex ++; + if (ipp->curindex < ipp->current->num_values && ipp->current->values[ipp->curindex].collection) + ipp->current->values[ipp->curindex].collection->current = NULL; + } + + ipp->prev = ipp->current; + ipp->current = ipp->current->next; + ipp->curindex = 0; + + if (!ipp->current) + { + ipp->atend = 1; + return (NULL); + } + } + + if (!ipp->current) + { + ipp->prev = NULL; + ipp->current = ipp->attrs; + ipp->curindex = 0; + } + + name = parent; + attr = ipp->current; + } + else if (ipp->current) { ipp->prev = ipp->current; attr = ipp->current->next; @@ -2048,18 +2113,33 @@ ippFindNextAttribute(ipp_t *ipp, /* I - IPP message */ value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_CUPS_MASK); if (attr->name != NULL && _cups_strcasecmp(attr->name, name) == 0 && - (value_tag == type || type == IPP_TAG_ZERO || + (value_tag == type || type == IPP_TAG_ZERO || name == parent || (value_tag == IPP_TAG_TEXTLANG && type == IPP_TAG_TEXT) || (value_tag == IPP_TAG_NAMELANG && type == IPP_TAG_NAME))) { ipp->current = attr; - return (attr); + if (name == parent && attr->value_tag == IPP_TAG_BEGIN_COLLECTION) + { + int i; /* Looping var */ + + for (i = 0; i < attr->num_values; i ++) + { + if ((childattr = ippFindAttribute(attr->values[i].collection, child, type)) != NULL) + { + attr->values[0].collection->curindex = i; + return (childattr); + } + } + } + else + return (attr); } } ipp->current = NULL; ipp->prev = NULL; + ipp->atend = 1; return (NULL); } diff --git a/cups/ipp.h b/cups/ipp.h index a55ed40350..38e7c4b55a 100644 --- a/cups/ipp.h +++ b/cups/ipp.h @@ -804,6 +804,9 @@ struct _ipp_s /**** IPP Request/Response/Notification ****/ /**** New in CUPS 1.4.4 ****/ int use; /* Use count @since CUPS 1.4.4/OS X 10.6.?@ */ +/**** New in CUPS 2.0 ****/ + int atend, /* At end of list? */ + curindex; /* Current attribute index for hierarchical search */ }; # endif /* _IPP_PRIVATE_STRUCTURES */ diff --git a/cups/testipp.c b/cups/testipp.c index abb56036be..6303738b74 100644 --- a/cups/testipp.c +++ b/cups/testipp.c @@ -542,6 +542,53 @@ main(int argc, /* I - Number of command-line arguments */ } } + /* + * Test hierarchical find... + */ + + fputs("ippFindAttribute(media-col/media-size/x-dimension): ", stdout); + if ((attr = ippFindAttribute(request, "media-col/media-size/x-dimension", IPP_TAG_INTEGER)) != NULL) + { + if (ippGetInteger(attr, 0) != 21590) + { + printf("FAIL (wrong value for x-dimension - %d)\n", ippGetInteger(attr, 0)); + status = 1; + } + else + puts("PASS"); + } + else + { + puts("FAIL (not found)"); + status = 1; + } + + fputs("ippFindNextAttribute(media-col/media-size/x-dimension): ", stdout); + if ((attr = ippFindNextAttribute(request, "media-col/media-size/x-dimension", IPP_TAG_INTEGER)) != NULL) + { + if (ippGetInteger(attr, 0) != 21000) + { + printf("FAIL (wrong value for x-dimension - %d)\n", ippGetInteger(attr, 0)); + status = 1; + } + else + puts("PASS"); + } + else + { + puts("FAIL (not found)"); + status = 1; + } + + fputs("ippFindNextAttribute(media-col/media-size/x-dimension) again: ", stdout); + if ((attr = ippFindNextAttribute(request, "media-col/media-size/x-dimension", IPP_TAG_INTEGER)) != NULL) + { + printf("FAIL (got %d, expected nothing)\n", ippGetInteger(attr, 0)); + status = 1; + } + else + puts("PASS"); + ippDelete(request); /*