Reformat a bit
[yaz-moved-to-github.git] / src / cqltransform.c
index cd735e4..3163775 100644 (file)
@@ -1,8 +1,7 @@
 /* This file is part of the YAZ toolkit.
- * Copyright (C) 1995-2008 Index Data
+ * Copyright (C) 1995-2011 Index Data
  * See the file LICENSE for details.
  */
-
 /**
  * \file cqltransform.c
  * \brief Implements CQL transform (CQL to RPN conversion).
  * index
  * relationModifier
  */
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
 
 #include <assert.h>
 #include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
-#include <yaz/cql.h>
+#include <yaz/rpn2cql.h>
 #include <yaz/xmalloc.h>
 #include <yaz/diagsrw.h>
 #include <yaz/tokenizer.h>
 #include <yaz/wrbuf.h>
 #include <yaz/z-core.h>
+#include <yaz/matchstr.h>
 #include <yaz/oid_db.h>
 #include <yaz/log.h>
 
-struct cql_rpn_value_entry {
-    Z_AttributeElement *elem;
-    struct cql_rpn_value_entry *next;
-};
-
 struct cql_prop_entry {
     char *pattern;
     char *value;
-    struct cql_rpn_value_entry *attr_values;
+    Z_AttributeList attr_list;
     struct cql_prop_entry *next;
 };
 
@@ -69,11 +66,13 @@ static int cql_transform_parse_tok_line(cql_transform_t ct,
                                         const char *pattern,
                                         yaz_tok_parse_t tp)
 {
+    int ae_num = 0;
+    Z_AttributeElement *ae[20];
     int ret = 0; /* 0=OK, != 0 FAIL */
     int t;
     t = yaz_tok_move(tp);
     
-    while (t == YAZ_TOK_STRING)
+    while (t == YAZ_TOK_STRING && ae_num < 20)
     {
         WRBUF type_str = wrbuf_alloc();
         WRBUF set_str = 0;
@@ -81,28 +80,9 @@ static int cql_transform_parse_tok_line(cql_transform_t ct,
         const char *value_str = 0;
         /* attset type=value  OR  type=value */
         
-        elem = nmem_malloc(ct->nmem, sizeof(*elem));
+        elem = (Z_AttributeElement *) nmem_malloc(ct->nmem, sizeof(*elem));
         elem->attributeSet = 0;
-#if 0
-        struct Z_ComplexAttribute {
-            int num_list;
-            Z_StringOrNumeric **list;
-            int num_semanticAction;
-            int **semanticAction; /* OPT */
-        };
-        
-        struct Z_AttributeElement {
-            Z_AttributeSetId *attributeSet; /* OPT */
-            int *attributeType;
-            int which;
-            union {
-                int *numeric;
-                Z_ComplexAttribute *complex;
-#define Z_AttributeValue_numeric 1
-#define Z_AttributeValue_complex 2
-            } value;
-        };
-#endif
+        ae[ae_num] = elem;
         wrbuf_puts(ct->w, yaz_tok_parse_string(tp));
         wrbuf_puts(type_str, yaz_tok_parse_string(tp));
         t = yaz_tok_move(tp);
@@ -128,7 +108,7 @@ static int cql_transform_parse_tok_line(cql_transform_t ct,
             t = yaz_tok_move(tp);
         }
         elem->attributeType = nmem_intdup(ct->nmem, 0);
-        if (sscanf(wrbuf_cstr(type_str), "%d", elem->attributeType)
+        if (sscanf(wrbuf_cstr(type_str), ODR_INT_PRINTF, elem->attributeType)
             != 1)
         {
             wrbuf_destroy(type_str);
@@ -157,7 +137,7 @@ static int cql_transform_parse_tok_line(cql_transform_t ct,
             break;
         }
         value_str = yaz_tok_parse_string(tp);
-        if (isdigit(*value_str))
+        if (yaz_isdigit(*value_str))
         {
             elem->which = Z_AttributeValue_numeric;
             elem->value.numeric =
@@ -165,7 +145,8 @@ static int cql_transform_parse_tok_line(cql_transform_t ct,
         }
         else
         {
-            Z_ComplexAttribute *ca = nmem_malloc(ct->nmem, sizeof(*ca));
+            Z_ComplexAttribute *ca = (Z_ComplexAttribute *)
+                nmem_malloc(ct->nmem, sizeof(*ca));
             elem->which = Z_AttributeValue_complex;
             elem->value.complex = ca;
             ca->num_list = 1;
@@ -182,6 +163,7 @@ static int cql_transform_parse_tok_line(cql_transform_t ct,
         wrbuf_puts(ct->w, yaz_tok_parse_string(tp));
         t = yaz_tok_move(tp);
         wrbuf_puts(ct->w, " ");
+        ae_num++;
     }
     if (ret == 0) /* OK? */
     {
@@ -191,7 +173,29 @@ static int cql_transform_parse_tok_line(cql_transform_t ct,
         *pp = (struct cql_prop_entry *) xmalloc(sizeof(**pp));
         (*pp)->pattern = xstrdup(pattern);
         (*pp)->value = xstrdup(wrbuf_cstr(ct->w));
+
+        (*pp)->attr_list.num_attributes = ae_num;
+        if (ae_num == 0)
+            (*pp)->attr_list.attributes = 0;
+        else
+        {
+            (*pp)->attr_list.attributes = (Z_AttributeElement **)
+                nmem_malloc(ct->nmem,
+                            ae_num * sizeof(Z_AttributeElement *));
+            memcpy((*pp)->attr_list.attributes, ae, 
+                   ae_num * sizeof(Z_AttributeElement *));
+        }
         (*pp)->next = 0;
+
+        if (0)
+        {
+            ODR pr = odr_createmem(ODR_PRINT);
+            Z_AttributeList *alp = &(*pp)->attr_list;
+            odr_setprint(pr, yaz_log_file());
+            z_AttributeList(pr, &alp, 0, 0);
+            odr_setprint(pr, 0);
+            odr_destroy(pr);
+        }
     }
     return ret;
 }
@@ -281,28 +285,75 @@ cql_transform_t cql_transform_open_fname(const char *fname)
     return ct;
 }
 
-static const char *cql_lookup_reverse(cql_transform_t ct, 
-                                      const char *category,
-                                      const char **attr_list,
-                                      int *matches)
+#if 0
+struct Z_AttributeElement {
+       Z_AttributeSetId *attributeSet; /* OPT */
+       int *attributeType;
+       int which;
+       union {
+               int *numeric;
+               Z_ComplexAttribute *complex;
+#define Z_AttributeValue_numeric 1
+#define Z_AttributeValue_complex 2
+       } value;
+};
+#endif
+
+static int compare_attr(Z_AttributeElement *a, Z_AttributeElement *b)
+{
+    ODR odr_a = odr_createmem(ODR_ENCODE);
+    ODR odr_b = odr_createmem(ODR_ENCODE);
+    int len_a, len_b;
+    char *buf_a, *buf_b;
+    int ret;
+
+    z_AttributeElement(odr_a, &a, 0, 0);
+    z_AttributeElement(odr_b, &b, 0, 0);
+    
+    buf_a = odr_getbuf(odr_a, &len_a, 0);
+    buf_b = odr_getbuf(odr_b, &len_b, 0);
+
+    ret = yaz_memcmp(buf_a, buf_b, len_a, len_b);
+
+    odr_destroy(odr_a);
+    odr_destroy(odr_b);
+    return ret;
+}
+
+const char *cql_lookup_reverse(cql_transform_t ct, 
+                               const char *category,
+                               Z_AttributeList *attributes)
 {
     struct cql_prop_entry *e;
-    size_t cat_len = strlen(category);
-    NMEM nmem = nmem_create();
+    size_t clen = strlen(category);
     for (e = ct->entry; e; e = e->next)
     {
-        const char *dot_str = strchr(e->pattern, '.');
-        int prefix_len = dot_str ? 
-            prefix_len = dot_str - e->pattern : strlen(e->pattern);
-        if (cat_len == prefix_len && !memcmp(category, e->pattern, cat_len))
+        if (!strncmp(e->pattern, category, clen))
         {
-            char **attr_array;
-            int attr_num;
-            nmem_strsplit_blank(nmem, e->value, &attr_array, &attr_num);
-            nmem_reset(nmem);
+            /* category matches.. See if attributes in pattern value
+               are all listed in actual attributes */
+            int i;
+            for (i = 0; i < e->attr_list.num_attributes; i++)
+            {
+                /* entry attribute */
+                Z_AttributeElement *e_ae = e->attr_list.attributes[i];
+                int j;
+                for (j = 0; j < attributes->num_attributes; j++)
+                {
+                    /* actual attribute */
+                    Z_AttributeElement *a_ae = attributes->attributes[j];
+                    int r = compare_attr(e_ae, a_ae);
+                    if (r == 0)
+                        break;
+                }
+                if (j == attributes->num_attributes)
+                    break; /* i was not found at all.. try next pattern */
+                    
+            }
+            if (i == e->attr_list.num_attributes)
+                return e->pattern + clen;
         }
     }
-    nmem_destroy(nmem);
     return 0;
 }
                                       
@@ -385,7 +436,7 @@ int cql_pr_attr_uri(cql_transform_t ct, const char *category,
             int i;
             while (*cp1 && *cp1 != ' ')
                 cp1++;
-            if (cp1 - cp0 >= sizeof(buf))
+            if (cp1 - cp0 >= (ptrdiff_t) sizeof(buf))
                 break;
             memcpy(buf, cp0, cp1 - cp0);
             buf[cp1-cp0] = 0;
@@ -557,11 +608,11 @@ static int has_modifier(struct cql_node *cn, const char *name) {
 }
 
 
-void emit_term(cql_transform_t ct,
-               struct cql_node *cn,
-               const char *term, int length,
-               void (*pr)(const char *buf, void *client_data),
-               void *client_data)
+static void emit_term(cql_transform_t ct,
+                      struct cql_node *cn,
+                      const char *term, int length,
+                      void (*pr)(const char *buf, void *client_data),
+                      void *client_data)
 {
     int i;
     const char *ns = cn->u.st.index_uri;
@@ -683,7 +734,7 @@ void emit_term(cql_transform_t ct,
     }
 
     (*pr)("\"", client_data);
-    for (i = 0; i<length; i++)
+    for (i = 0; i < length; i++)
     {
         /* pr(int) each character */
         /* we do not need to deal with \-sequences because the
@@ -698,11 +749,11 @@ void emit_term(cql_transform_t ct,
     xfree(z3958_mem);
 }
 
-void emit_terms(cql_transform_t ct,
-                struct cql_node *cn,
-                void (*pr)(const char *buf, void *client_data),
-                void *client_data,
-                const char *op)
+static void emit_terms(cql_transform_t ct,
+                       struct cql_node *cn,
+                       void (*pr)(const char *buf, void *client_data),
+                       void *client_data,
+                       const char *op)
 {
     struct cql_node *ne = cn->u.st.extra_terms;
     if (ne)
@@ -726,11 +777,11 @@ void emit_terms(cql_transform_t ct,
     }
 }
 
-void emit_wordlist(cql_transform_t ct,
-                   struct cql_node *cn,
-                   void (*pr)(const char *buf, void *client_data),
-                   void *client_data,
-                   const char *op)
+static void emit_wordlist(cql_transform_t ct,
+                          struct cql_node *cn,
+                          void (*pr)(const char *buf, void *client_data),
+                          void *client_data,
+                          const char *op)
 {
     const char *cp0 = cn->u.st.term;
     const char *cp1;
@@ -825,7 +876,9 @@ void cql_transform_r(cql_transform_t ct,
         cql_transform_r(ct, cn->u.boolean.left, pr, client_data);
         cql_transform_r(ct, cn->u.boolean.right, pr, client_data);
         break;
-
+    case CQL_NODE_SORT:
+        cql_transform_r(ct, cn->u.sort.search, pr, client_data);
+        break;
     default:
         fprintf(stderr, "Fatal: impossible CQL node-type %d\n", cn->which);
         abort();
@@ -861,7 +914,8 @@ int cql_transform_FILE(cql_transform_t ct, struct cql_node *cn, FILE *f)
     return cql_transform(ct, cn, cql_fputs, f);
 }
 
-int cql_transform_buf(cql_transform_t ct, struct cql_node *cn, char *out, int max)
+int cql_transform_buf(cql_transform_t ct, struct cql_node *cn,
+                      char *out, int max)
 {
     struct cql_buf_write_info info;
     int r;
@@ -901,6 +955,7 @@ void cql_transform_set_error(cql_transform_t ct, int error, const char *addinfo)
 /*
  * Local variables:
  * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
  * indent-tabs-mode: nil
  * End:
  * vim: shiftwidth=4 tabstop=8 expandtab