From df0a3ba592afe51a91a54152c3add5d1b51604a8 Mon Sep 17 00:00:00 2001 From: Dennis Schafroth Date: Thu, 15 Jul 2010 14:33:46 +0200 Subject: [PATCH] New Facet helpers Use for extraction of values from the ASN.1 structures in C. --- include/yaz/Makefile.am | 2 +- include/yaz/facet.h | 51 ++++++++++++++++++++ src/Makefile.am | 2 +- src/facet.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 include/yaz/facet.h create mode 100644 src/facet.c diff --git a/include/yaz/Makefile.am b/include/yaz/Makefile.am index 1ee66ac..f4e6548 100644 --- a/include/yaz/Makefile.am +++ b/include/yaz/Makefile.am @@ -5,7 +5,7 @@ noinst_HEADERS = icu_I18N.h pkginclude_HEADERS= backend.h ccl.h ccl_xml.h cql.h rpn2cql.h comstack.h \ diagbib1.h diagsrw.h diagsru_update.h sortspec.h log.h logrpn.h marcdisp.h \ - nmem.h nmem_xml.h odr.h errno.h \ + nmem.h nmem_xml.h odr.h errno.h facet.h \ options.h otherinfo.h pquery.h prt-ext.h querytowrbuf.h \ readconf.h record_conv.h retrieval.h statserv.h \ tcpip.h test.h timing.h unix.h tpath.h wrbuf.h xmalloc.h \ diff --git a/include/yaz/facet.h b/include/yaz/facet.h new file mode 100644 index 0000000..687ce54 --- /dev/null +++ b/include/yaz/facet.h @@ -0,0 +1,51 @@ + +#ifndef YAZ_FACET_H +#define YAZ_FACET_H + +#include +#include +#include + +YAZ_BEGIN_CDECL + + +/* + * Helper function for extracting facet values from the ASN structures. + * + */ + +/* A helper structure to extract all the attribute stuff + from one Z_AttributesList. The pointers will all be to + the Z-structures, or to constants, so there is no need to + worry about freeing them */ +struct attrvalues { + int errcode; /* set in case of errors */ + char *errstring; /* opt */ + const char *useattr; /* @attr 1, from a string attr */ + /* or number converted to a string */ + /* defaults to 'any' */ + char useattrbuff[30]; /* for converting numbers to strings */ + char *relation; /* @attr 2, defaults to '=' */ + int limit; /* for facet attributes */ +}; + + +/* Use attribute, @attr1, can be numeric or string */ +YAZ_EXPORT +void useattr ( Z_AttributeElement *ae, struct attrvalues *av ); + +YAZ_EXPORT +void relationattr ( Z_AttributeElement *ae, struct attrvalues *av ); + +YAZ_EXPORT +void limitattr ( Z_AttributeElement *ae, struct attrvalues *av ); + +YAZ_EXPORT +void limitattr ( Z_AttributeElement *ae, struct attrvalues *av ); + +YAZ_EXPORT +void facetattrs( Z_AttributeList *attributes, struct attrvalues *av ); + + + +#endif diff --git a/src/Makefile.am b/src/Makefile.am index 2e5cec2..e79d237 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -77,7 +77,7 @@ libyaz_la_SOURCES=version.c options.c log.c \ wrbuf.c oid_db.c errno.c \ nmemsdup.c xmalloc.c readconf.c tpath.c nmem.c matchstr.c atoin.c \ siconv.c iconv-p.h utf8.c ucs4.c iso5428.c advancegreek.c \ - odr_bool.c ber_bool.c ber_len.c ber_tag.c odr_util.c \ + odr_bool.c ber_bool.c ber_len.c ber_tag.c odr_util.c facet.c \ odr_null.c ber_null.c odr_int.c ber_int.c odr_tag.c odr_cons.c \ odr_seq.c odr_oct.c ber_oct.c odr_bit.c ber_bit.c odr_oid.c \ ber_oid.c odr_use.c odr_choice.c odr_any.c ber_any.c odr.c odr_mem.c \ diff --git a/src/facet.c b/src/facet.c new file mode 100644 index 0000000..7baee6b --- /dev/null +++ b/src/facet.c @@ -0,0 +1,120 @@ + + +#include +#include + +/* Little helper to extract a string attribute */ +/* Gets the first string, there is usually only one */ +/* in case of errors, returns null */ +const char *stringattr( Z_ComplexAttribute *c ) { + int i; + Z_StringOrNumeric *son; + for ( i = 0; i < c->num_list; i++ ) { + son = c->list[i]; + if ( son->which == Z_StringOrNumeric_string ) + return son->u.string; + } + return 0; +} + +/* Use attribute, @attr1, can be numeric or string */ +void useattr ( Z_AttributeElement *ae, + struct attrvalues *av ) +{ + const char *s; + if ( ae->which == Z_AttributeValue_complex ) { + s = stringattr( ae->value.complex ); + if (s) { + if (!av->useattr) + av->useattr = s; + else { /* already seen one, can't have duplicates */ + av->errcode = YAZ_BIB1_UNSUPP_ATTRIBUTE_COMBI; + av->errstring = "multiple use attributes"; + } + } else { /* complex that did not return a string */ + av->errcode = YAZ_BIB1_UNSUPP_ATTRIBUTE_COMBI; + av->errstring = "non-string complex attribute"; + } + } else { /* numeric - could translate 4 to 'title' etc */ + sprintf(av->useattrbuff, ODR_INT_PRINTF, *ae->value.numeric ); + av->useattr = av->useattrbuff; + } +} /* useattr */ + + +/* TODO rename to sortorder attr */ +void relationattr ( Z_AttributeElement *ae, + struct attrvalues *av ) +{ + if ( ae->which == Z_AttributeValue_numeric ) { + if ( *ae->value.numeric == 0 ) + av->relation = "desc"; + else if ( *ae->value.numeric == 1 ) + av->relation = "asc"; + else + if ( *ae->value.numeric == 3 ) { + av->relation = "unknown/unordered"; + } else { + av->errcode = YAZ_BIB1_UNSUPP_RELATION_ATTRIBUTE; + sprintf(av->useattrbuff, ODR_INT_PRINTF, + *ae-> attributeType); + av->errstring = av->useattrbuff; + } + } else { + av->errcode = YAZ_BIB1_UNSUPP_RELATION_ATTRIBUTE; + av->errstring = "non-numeric relation attribute"; + } +} /* relationattr */ + +void limitattr ( Z_AttributeElement *ae, + struct attrvalues *av ) +{ + /* TODO - check numeric first, then value! */ + if ( ae->which == Z_AttributeValue_numeric ) { + av->limit = *ae->value.numeric; + } else { + av->errcode = YAZ_BIB1_UNSUPP_ATTRIBUTE; + av->errstring = "non-numeric limit attribute"; + } +} /* relationattr */ + +/* Get the index to be searched from the attributes. + @attr 1 + can be either "string", or some well-known value like + 4 for title + Returns a null and sets errors in rr, + emtpy string if no attr found, + or the string itself - always a pointer to the Z-structs, + so no need to free that string! +*/ + +void facetattrs( Z_AttributeList *attributes, + struct attrvalues *av ) +{ + int i; + Z_AttributeElement *ae; + for ( i=0; i < attributes->num_attributes; i++ ) { + ae = attributes->attributes[i]; + /* ignoring the attributeSet here */ + if ( *ae->attributeType == 1 ) { /* use attribute */ + useattr(ae, av); + } else if ( *ae->attributeType == 2 ) { /* sortorder */ + relationattr(ae, av); + } else if ( *ae->attributeType == 3 ) { /* limit */ + limitattr(ae, av); + } else { /* unknown attribute */ + av->errcode = YAZ_BIB1_UNSUPP_ATTRIBUTE_TYPE; + sprintf(av->useattrbuff, ODR_INT_PRINTF, + *ae-> attributeType); + av->errstring = av->useattrbuff; + yaz_log(YLOG_DEBUG,"Unsupported attribute type %s", + av->useattrbuff); + /* would like to give a better message, but the standard */ + /* tells me to return the attribute type */ + } + if ( av->errcode ) + return; /* no need to dig deeper, return on first error */ + } + return; +} /* facetattrs */ + -- 1.7.10.4