#define SORTSPEC_H
#include <yaz/yconfig.h>
-#include <yaz/proto.h>
+#include <yaz/wrbuf.h>
+#include <yaz/z-core.h>
YAZ_BEGIN_CDECL
-YAZ_EXPORT Z_SortKeySpecList *yaz_sort_spec (ODR out, const char *arg);
+/** \brief parse sort spec string
+ \param odr memory for result
+ \param arg sort spec string
+ \returns Z39.50 SortKeySpecList or NULL on error
+
+ The sort spec list is of the form:
+ (field flags)+
+ where field is either a string or one or more attribute pairs
+ key=value (there must be no blanks in either field of flags).
+ flags is a character list:
+ dD> : descending
+ aA< : ascending (default)
+ iI : ignoreccase / case-insensitive (default)
+ sS : respectcase / case-sensitive
+ ! : abort of key is omitted in result
+ =value : missing value
+
+ Examples:
+
+ title a
+
+ 1=4 ia 1=1003 sd
+*/
+YAZ_EXPORT Z_SortKeySpecList *yaz_sort_spec(ODR odr, const char *arg);
+
+/* \brief converts SortKeySpecList to CQL sortby string
+ \param sksl SortKeySpecList
+ \param w resulting CQL SORTBY string (of string to be appended)
+ \retval 0 successful
+ \retval -1 failure
+*/
+YAZ_EXPORT int yaz_sort_spec_to_cql(Z_SortKeySpecList *sksl, WRBUF w);
+
+/* \brief adds PQF type-7 sorting to existing PQF from SortKeySpecList
+ \param sksl SortKeySpecList
+ \param w original PQF (without the Type-7)
+ \retval 0 successful
+ \retval -1 failure
+
+ If successful, the pqf WRBUF holds the new PQF including the Type-7
+ part.
+*/
+YAZ_EXPORT int yaz_sort_spec_to_type7(Z_SortKeySpecList *sksl, WRBUF pqf);
YAZ_END_CDECL
#include <string.h>
#include <stdlib.h>
-#include <yaz/proto.h>
+#include <yaz/z-core.h>
#include <yaz/sortspec.h>
#include <yaz/oid_db.h>
+#include <yaz/wrbuf.h>
-Z_SortKeySpecList *yaz_sort_spec (ODR out, const char *arg)
+Z_SortKeySpecList *yaz_sort_spec(ODR out, const char *arg)
{
char sort_string_buf[64], sort_flags[64];
Z_SortKeySpecList *sksl = (Z_SortKeySpecList *)
int off;
sksl->num_specs = 0;
- sksl->specs = (Z_SortKeySpec **)odr_malloc (out, sizeof(sksl->specs) * 20);
+ sksl->specs = (Z_SortKeySpec **)odr_malloc(out, sizeof(sksl->specs) * 20);
- while ((sscanf (arg, "%63s %63s%n", sort_string_buf,
- sort_flags, &off)) == 2 && off > 1)
+ while ((sscanf(arg, "%63s %63s%n", sort_string_buf,
+ sort_flags, &off)) == 2 && off > 1)
{
int i;
char *sort_string_sep;
char *sort_string = sort_string_buf;
- Z_SortKeySpec *sks = (Z_SortKeySpec *)odr_malloc (out, sizeof(*sks));
- Z_SortKey *sk = (Z_SortKey *)odr_malloc (out, sizeof(*sk));
+ Z_SortKeySpec *sks = (Z_SortKeySpec *) odr_malloc(out, sizeof(*sks));
+ Z_SortKey *sk = (Z_SortKey *) odr_malloc(out, sizeof(*sk));
arg += off;
sksl->specs[sksl->num_specs++] = sks;
sks->sortElement->which = Z_SortElement_generic;
sks->sortElement->u.generic = sk;
- if ((sort_string_sep = strchr (sort_string, '=')))
+ if ((sort_string_sep = strchr(sort_string, '=')))
{
int i = 0;
sk->which = Z_SortKey_sortAttributes;
sk->u.sortAttributes = (Z_SortAttributes *)
- odr_malloc (out, sizeof(*sk->u.sortAttributes));
+ odr_malloc(out, sizeof(*sk->u.sortAttributes));
sk->u.sortAttributes->id = odr_oiddup(out, yaz_oid_attset_bib_1);
sk->u.sortAttributes->list = (Z_AttributeList *)
- odr_malloc (out, sizeof(*sk->u.sortAttributes->list));
+ odr_malloc(out, sizeof(*sk->u.sortAttributes->list));
sk->u.sortAttributes->list->attributes = (Z_AttributeElement **)
- odr_malloc (out, 10 *
+ odr_malloc(out, 10 *
sizeof(*sk->u.sortAttributes->list->attributes));
while (i < 10 && sort_string && sort_string_sep)
{
odr_malloc (out, sizeof(*el));
sk->u.sortAttributes->list->attributes[i] = el;
el->attributeSet = 0;
- el->attributeType = odr_intdup (out, atoi (sort_string));
+ el->attributeType = odr_intdup(out, atoi(sort_string));
el->which = Z_AttributeValue_numeric;
el->value.numeric =
- odr_intdup (out, atoi (sort_string_sep + 1));
+ odr_intdup(out, odr_atoi(sort_string_sep + 1));
i++;
sort_string = strchr(sort_string, ',');
if (sort_string)
{
sort_string++;
- sort_string_sep = strchr (sort_string, '=');
+ sort_string_sep = strchr(sort_string, '=');
}
}
sk->u.sortAttributes->list->num_attributes = i;
sk->which = Z_SortKey_sortField;
sk->u.sortField = odr_strdup (out, sort_string);
}
- sks->sortRelation = odr_intdup (out, Z_SortKeySpec_ascending);
- sks->caseSensitivity = odr_intdup (out, Z_SortKeySpec_caseSensitive);
+ sks->sortRelation = odr_intdup(out, Z_SortKeySpec_ascending);
+ sks->caseSensitivity = odr_intdup(out, Z_SortKeySpec_caseInsensitive);
sks->which = Z_SortKeySpec_null;
sks->u.null = odr_nullval ();
return 0;
return sksl;
}
+
+int yaz_sort_spec_to_cql(Z_SortKeySpecList *sksl, WRBUF w)
+{
+ int i;
+ for (i = 0; i < sksl->num_specs; i++)
+ {
+ Z_SortKeySpec *sks = sksl->specs[i];
+ Z_SortKey *sk;
+
+ if (sks->sortElement->which != Z_SortElement_generic)
+ return -1;
+
+ sk = sks->sortElement->u.generic;
+ if (i)
+ wrbuf_puts(w, " ");
+ else
+ wrbuf_puts(w, " SORTBY ");
+ if (sk->which == Z_SortKey_sortAttributes)
+ return -1;
+ else if (sk->which == Z_SortKey_sortField)
+ wrbuf_puts(w, sk->u.sortField);
+ switch (*sks->sortRelation)
+ {
+ case Z_SortKeySpec_ascending:
+ wrbuf_puts(w, "/ascending");
+ break;
+ case Z_SortKeySpec_descending:
+ wrbuf_puts(w, "/descending");
+ break;
+ }
+ switch (*sks->caseSensitivity)
+ {
+ case Z_SortKeySpec_caseSensitive:
+ wrbuf_puts(w, "/respectCase");
+ break;
+ case Z_SortKeySpec_caseInsensitive:
+ wrbuf_puts(w, "/ignoreCase");
+ break;
+ }
+ switch (sks->which)
+ {
+ case Z_SortKeySpec_null:
+ break;
+ case Z_SortKeySpec_abort:
+ wrbuf_puts(w, "/missingFail");
+ break;
+ case Z_SortKeySpec_missingValueData:
+ wrbuf_puts(w, "/missingValue=");
+ wrbuf_write(w, (const char *) sks->u.missingValueData->buf,
+ sks->u.missingValueData->len);
+ }
+ }
+ return 0;
+}
+
+int yaz_sort_spec_to_type7(Z_SortKeySpecList *sksl, WRBUF pqf)
+{
+ int i;
+ for (i = 0; i < sksl->num_specs; i++)
+ {
+ Z_SortKeySpec *sks = sksl->specs[i];
+ Z_SortKey *sk;
+
+ if (sks->sortElement->which != Z_SortElement_generic)
+ return -1;
+
+ sk = sks->sortElement->u.generic;
+
+ wrbuf_insert(pqf, 0, "@or ", 4);
+
+ if (sk->which == Z_SortKey_sortAttributes)
+ {
+ int j;
+ for (j = 0; j < sk->u.sortAttributes->list->num_attributes; j++)
+ {
+ Z_AttributeElement *el =
+ sk->u.sortAttributes->list->attributes[j];
+ if (el->which != Z_AttributeValue_numeric)
+ return -1;
+ wrbuf_printf(pqf, " @attr " ODR_INT_PRINTF "=" ODR_INT_PRINTF,
+ *el->attributeType, *el->value.numeric);
+ }
+ }
+ else if (sk->which == Z_SortKey_sortField)
+ {
+ wrbuf_puts(pqf, " @attr 1=");
+ wrbuf_puts(pqf, sk->u.sortField);
+ }
+ switch (*sks->sortRelation)
+ {
+ case Z_SortKeySpec_ascending:
+ wrbuf_puts(pqf, " @attr 7=1 ");
+ break;
+ case Z_SortKeySpec_descending:
+ wrbuf_puts(pqf, " @attr 7=2 ");
+ break;
+ }
+ wrbuf_printf(pqf, "%d", i);
+ }
+ return 0;
+}
+
+
/*
* Local variables:
* c-basic-offset: 4
## This file is part of the YAZ toolkit.
## Copyright (C) 1995-2011 Index Data
-check_PROGRAMS = test_cql2ccl \
- test_xmalloc test_iconv test_nmem test_matchstr test_wrbuf \
- test_odr test_ccl test_log test_mutex \
- test_soap1 test_soap2 test_solr test_odrstack test_log_thread \
- test_xmlquery test_pquery \
- test_comstack test_filepath test_record_conv test_retrieval test_tpath \
- test_timing test_query_charset test_oid test_icu test_match_glob \
- test_rpn2cql test_rpn2solr test_json test_xml_include test_file_glob \
- test_shared_ptr test_libstemmer
+check_PROGRAMS = test_ccl test_comstack test_cql2ccl \
+ test_filepath test_file_glob \
+ test_iconv test_icu test_json \
+ test_libstemmer test_log test_log_thread \
+ test_match_glob test_matchstr test_mutex \
+ test_nmem test_odr test_odrstack test_oid \
+ test_pquery test_query_charset \
+ test_record_conv test_rpn2cql test_rpn2solr test_retrieval \
+ test_shared_ptr test_soap1 test_soap2 test_solr test_sortspec \
+ test_timing test_tpath test_wrbuf \
+ test_xmalloc test_xml_include test_xmlquery
check_SCRIPTS = test_marc.sh test_marccol.sh test_cql2xcql.sh \
test_cql2pqf.sh test_icu.sh
test_soap1_SOURCES = test_soap1.c
test_soap2_SOURCES = test_soap2.c
test_solr_SOURCES = test_solr.c
+test_sortspec_SOURCES = test_sortspec.c
test_log_thread_SOURCES = test_log_thread.c
test_xmlquery_SOURCES = test_xmlquery.c
test_pquery_SOURCES = test_pquery.c
--- /dev/null
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) 1995-2011 Index Data
+ * See the file LICENSE for details.
+ */
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <yaz/wrbuf.h>
+#include <yaz/sortspec.h>
+#include <yaz/log.h>
+#include <yaz/test.h>
+
+static int cql(const char *arg, const char *expected_result)
+{
+ ODR odr = odr_createmem(ODR_ENCODE);
+ Z_SortKeySpecList *sort_spec = yaz_sort_spec(odr, arg);
+ int ret = 0;
+
+ if (!sort_spec)
+ {
+ yaz_log(YLOG_WARN, "yaz_sort_spec : parse error: %s", arg);
+ }
+ else
+ {
+ WRBUF w = wrbuf_alloc();
+ int r = yaz_sort_spec_to_cql(sort_spec, w);
+
+ if (!expected_result && r)
+ ret = 1;
+ else if (expected_result && r == 0)
+ {
+ if (strcmp(wrbuf_cstr(w), expected_result) == 0)
+ ret = 1;
+ else
+ {
+ yaz_log(YLOG_WARN, "sort: diff: %s", arg);
+ yaz_log(YLOG_WARN, " expected %s", expected_result);
+ yaz_log(YLOG_WARN, " got %s", wrbuf_cstr(w));
+ }
+ }
+ else if (r)
+ {
+ yaz_log(YLOG_WARN, "sort: diff %s", arg);
+ yaz_log(YLOG_WARN, " expected %s", expected_result);
+ yaz_log(YLOG_WARN, " got error %d", r);
+ }
+ else if (r == 0)
+ {
+ yaz_log(YLOG_WARN, "sort: diff %s", arg);
+ yaz_log(YLOG_WARN, " expected error");
+ yaz_log(YLOG_WARN, " got %s", wrbuf_cstr(w));
+ }
+ wrbuf_destroy(w);
+ }
+ odr_destroy(odr);
+ return ret;
+}
+
+static int type7(const char *arg, const char *expected_result)
+{
+ ODR odr = odr_createmem(ODR_ENCODE);
+ Z_SortKeySpecList *sort_spec = yaz_sort_spec(odr, arg);
+ int ret = 0;
+
+ if (!sort_spec)
+ {
+ yaz_log(YLOG_WARN, "yaz_sort_spec : parse error: %s", arg);
+ }
+ else
+ {
+ WRBUF w = wrbuf_alloc();
+ int r;
+
+ wrbuf_puts(w, "q");
+ r = yaz_sort_spec_to_type7(sort_spec, w);
+
+ if (!expected_result && r)
+ ret = 1;
+ else if (expected_result && r == 0)
+ {
+ if (strcmp(wrbuf_cstr(w), expected_result) == 0)
+ ret = 1;
+ else
+ {
+ yaz_log(YLOG_WARN, "sort: diff: %s", arg);
+ yaz_log(YLOG_WARN, " expected %s", expected_result);
+ yaz_log(YLOG_WARN, " got %s", wrbuf_cstr(w));
+ }
+ }
+ else if (r)
+ {
+ yaz_log(YLOG_WARN, "sort: diff %s", arg);
+ yaz_log(YLOG_WARN, " expected %s", expected_result);
+ yaz_log(YLOG_WARN, " got error %d", r);
+ }
+ else if (r == 0)
+ {
+ yaz_log(YLOG_WARN, "sort: diff %s", arg);
+ yaz_log(YLOG_WARN, " expected error");
+ yaz_log(YLOG_WARN, " got %s", wrbuf_cstr(w));
+ }
+ wrbuf_destroy(w);
+ }
+ odr_destroy(odr);
+ return ret;
+}
+
+static void tst(void)
+{
+ YAZ_CHECK(cql("title a",
+ " SORTBY title/ascending/ignoreCase"));
+ YAZ_CHECK(cql("title a date ds",
+ " SORTBY title/ascending/ignoreCase"
+ " date/descending/respectCase"));
+ YAZ_CHECK(cql("1=4,2=3 a", 0));
+
+ YAZ_CHECK(type7("title a",
+ "@or q @attr 1=title @attr 7=1 0"));
+ YAZ_CHECK(type7("title a date ds",
+ "@or @or q @attr 1=title @attr 7=1 0"
+ " @attr 1=date @attr 7=2 1"));
+ YAZ_CHECK(type7("1=4,2=3 a",
+ "@or q @attr 1=4 @attr 2=3 @attr 7=1 0"));
+}
+
+int main(int argc, char **argv)
+{
+ YAZ_CHECK_INIT(argc, argv);
+ YAZ_CHECK_LOG();
+ tst();
+ YAZ_CHECK_TERM;
+}
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+