--- /dev/null
+
+#ifndef YAZ_FACET_H
+#define YAZ_FACET_H
+
+#include <yaz/yconfig.h>
+#include <yaz/z-core.h>
+#include <yaz/log.h>
+
+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
--- /dev/null
+
+
+#include <yaz/facet.h>
+#include <yaz/diagbib1.h>
+
+/* 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 */
+