YAZ  5.23.1
sortspec.c
Go to the documentation of this file.
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12 
13 #include <stdio.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include <yaz/matchstr.h>
17 
18 #include <yaz/z-core.h>
19 #include <yaz/sortspec.h>
20 #include <yaz/oid_db.h>
21 #include <yaz/wrbuf.h>
22 
23 Z_SortKeySpecList *yaz_sort_spec(ODR out, const char *arg)
24 {
25  char sort_string_buf[64], sort_flags[64];
27  odr_malloc(out, sizeof(*sksl));
28  int off;
29 
30  sksl->num_specs = 0;
31  sksl->specs = (Z_SortKeySpec **)odr_malloc(out, sizeof(sksl->specs) * 20);
32 
33  while ((sscanf(arg, "%63s %63s%n", sort_string_buf,
34  sort_flags, &off)) == 2 && off > 1)
35  {
36  int i;
37  char *sort_string_sep;
38  char *sort_string = sort_string_buf;
39  Z_SortKeySpec *sks = (Z_SortKeySpec *) odr_malloc(out, sizeof(*sks));
40  Z_SortKey *sk = (Z_SortKey *) odr_malloc(out, sizeof(*sk));
41 
42  arg += off;
43  sksl->specs[sksl->num_specs++] = sks;
44  sks->sortElement = (Z_SortElement *)
45  odr_malloc(out, sizeof(*sks->sortElement));
47  sks->sortElement->u.generic = sk;
48 
49  if ((sort_string_sep = strchr(sort_string, '=')))
50  {
51  int i = 0;
54  odr_malloc(out, sizeof(*sk->u.sortAttributes));
57  odr_malloc(out, sizeof(*sk->u.sortAttributes->list));
59  odr_malloc(out, 10 *
60  sizeof(*sk->u.sortAttributes->list->attributes));
61  while (i < 10 && sort_string && sort_string_sep)
62  {
64  odr_malloc(out, sizeof(*el));
65  sk->u.sortAttributes->list->attributes[i] = el;
66  el->attributeSet = 0;
67  el->attributeType = odr_intdup(out, atoi(sort_string));
69  el->value.numeric =
70  odr_intdup(out, odr_atoi(sort_string_sep + 1));
71  i++;
72  sort_string = strchr(sort_string, ',');
73  if (sort_string)
74  {
75  sort_string++;
76  sort_string_sep = strchr(sort_string, '=');
77  }
78  }
80  }
81  else
82  {
84  sk->u.sortField = odr_strdup (out, sort_string);
85  }
88 
90  sks->u.null = odr_nullval ();
91 
92  for (i = 0; sort_flags[i]; i++)
93  {
94  switch (sort_flags[i])
95  {
96  case 'd':
97  case 'D':
98  case '>':
100  break;
101  case 'a':
102  case 'A':
103  case '<':
105  break;
106  case 'i':
107  case 'I':
109  break;
110  case 'S':
111  case 's':
113  break;
114  case '!':
115  sks->which = Z_SortKeySpec_abort;
116  sks->u.abort = odr_nullval();
117  break;
118  case '=':
120  sks->u.missingValueData = (Odr_oct*)
121  odr_malloc(out, sizeof(Odr_oct));
122  i++;
123  sks->u.missingValueData->len = strlen(sort_flags+i);
124  sks->u.missingValueData->buf = odr_strdup(out, sort_flags+i);
125  i += strlen(sort_flags+i) - 1;
126  break;
127  }
128  }
129  }
130  if (!sksl->num_specs)
131  return 0;
132  return sksl;
133 }
134 
136 {
137  int i;
138  for (i = 0; i < sksl->num_specs; i++)
139  {
140  Z_SortKeySpec *sks = sksl->specs[i];
141  Z_SortKey *sk;
142 
144  return -1;
145 
146  sk = sks->sortElement->u.generic;
147  if (i)
148  wrbuf_puts(w, " ");
149  else
150  wrbuf_puts(w, " SORTBY ");
151  if (sk->which == Z_SortKey_sortAttributes)
152  return -1;
153  else if (sk->which == Z_SortKey_sortField)
154  wrbuf_puts(w, sk->u.sortField);
155  switch (*sks->sortRelation)
156  {
158  wrbuf_puts(w, "/ascending");
159  break;
161  wrbuf_puts(w, "/descending");
162  break;
163  }
164  switch (*sks->caseSensitivity)
165  {
167  wrbuf_puts(w, "/respectCase");
168  break;
170  wrbuf_puts(w, "/ignoreCase");
171  break;
172  }
173  switch (sks->which)
174  {
175  case Z_SortKeySpec_null:
176  break;
177  case Z_SortKeySpec_abort:
178  wrbuf_puts(w, "/missingFail");
179  break;
181  wrbuf_puts(w, "/missingValue=");
182  wrbuf_write(w, (const char *) sks->u.missingValueData->buf,
183  sks->u.missingValueData->len);
184  break;
185  }
186  }
187  return 0;
188 }
189 
191 {
192  int i;
193  for (i = 0; i < sksl->num_specs; i++)
194  {
195  Z_SortKeySpec *sks = sksl->specs[i];
196  Z_SortKey *sk;
197 
199  return -1;
200 
201  sk = sks->sortElement->u.generic;
202 
203  wrbuf_insert(pqf, 0, "@or ", 4);
204 
205  if (sk->which == Z_SortKey_sortAttributes)
206  {
207  int j;
208  for (j = 0; j < sk->u.sortAttributes->list->num_attributes; j++)
209  {
210  Z_AttributeElement *el =
211  sk->u.sortAttributes->list->attributes[j];
212  if (el->which != Z_AttributeValue_numeric)
213  return -1;
214  wrbuf_printf(pqf, " @attr " ODR_INT_PRINTF "=" ODR_INT_PRINTF,
215  *el->attributeType, *el->value.numeric);
216  }
217  }
218  else if (sk->which == Z_SortKey_sortField)
219  {
220  wrbuf_puts(pqf, " @attr 1=");
221  wrbuf_puts(pqf, sk->u.sortField);
222  }
223  switch (*sks->sortRelation)
224  {
226  wrbuf_puts(pqf, " @attr 7=1 ");
227  break;
229  wrbuf_puts(pqf, " @attr 7=2 ");
230  break;
231  }
232  wrbuf_printf(pqf, "%d", i);
233  }
234  return 0;
235 }
236 
238 {
239  int i;
240  for (i = 0; i < sksl->num_specs; i++)
241  {
242  Z_SortKeySpec *sks = sksl->specs[i];
243  Z_SortKey *sk;
244 
246  return -1;
247 
248  sk = sks->sortElement->u.generic;
249 
250  if (i)
251  wrbuf_puts(w, " ");
252 
253  if (sk->which == Z_SortKey_sortAttributes)
254  return -1;
255  else if (sk->which == Z_SortKey_sortField)
256  {
257  wrbuf_puts(w, sk->u.sortField);
258  }
259  wrbuf_puts(w, ",,"); /* path is absent */
260  switch (*sks->sortRelation)
261  {
263  wrbuf_puts(w, "1");
264  break;
266  wrbuf_puts(w, "0");
267  break;
268  }
269  wrbuf_puts(w, ",");
270  switch (*sks->caseSensitivity)
271  {
273  wrbuf_puts(w, "1");
274  break;
276  wrbuf_puts(w, "0");
277  break;
278  }
279  wrbuf_puts(w, ",");
280  switch (sks->which)
281  {
282  case Z_SortKeySpec_null:
283  wrbuf_puts(w, "highValue");
284  break;
285  case Z_SortKeySpec_abort:
286  wrbuf_puts(w, "abort");
287  break;
289  wrbuf_write(w, (const char *) sks->u.missingValueData->buf,
290  sks->u.missingValueData->len);
291  break;
292  }
293  }
294  return 0;
295 }
296 
298 {
299  int i;
300  for (i = 0; i < sksl->num_specs; i++)
301  {
302  Z_SortKeySpec *sks = sksl->specs[i];
303  Z_SortKey *sk;
304 
306  return -1;
307 
308  sk = sks->sortElement->u.generic;
309 
310  if (i)
311  wrbuf_puts(w, ",");
312 
313  if (sk->which == Z_SortKey_sortAttributes)
314  return -1;
315  else if (sk->which == Z_SortKey_sortField)
316  {
317  wrbuf_puts(w, sk->u.sortField);
318  }
319  switch (*sks->sortRelation)
320  {
322  wrbuf_puts(w, " asc");
323  break;
325  wrbuf_puts(w, " desc");
326  break;
327  }
328  }
329  return 0;
330 }
331 
332 
333 int yaz_srw_sortkeys_to_sort_spec(const char *srw_sortkeys, WRBUF w)
334 {
335  /* sru sortkey layout: path,schema,ascending,caseSensitive,missingValue */
336  /* see cql_sortby_to_sortkeys of YAZ. */
337  char **sortspec;
338  int num_sortspec = 0;
339  int i;
340  NMEM nmem = nmem_create();
341 
342  if (srw_sortkeys)
343  nmem_strsplit_blank(nmem, srw_sortkeys, &sortspec, &num_sortspec);
344  for (i = 0; i < num_sortspec; i++)
345  {
346  char **arg;
347  int num_arg;
348  int ascending = 1;
349  int case_sensitive = 0;
350  const char *missing = 0;
351  nmem_strsplitx(nmem, ",", sortspec[i], &arg, &num_arg, 0);
352 
353  if (num_arg > 2 && arg[2][0])
354  ascending = atoi(arg[2]);
355  if (num_arg > 3 && arg[3][0])
356  case_sensitive = atoi(arg[3]);
357  if (num_arg > 4 && arg[4][0])
358  missing = arg[4];
359 
360  if (i)
361  wrbuf_puts(w, " ");
362 
363  wrbuf_puts(w, arg[0]); /* field */
364  wrbuf_puts(w, " ");
365 
366  wrbuf_puts(w, ascending ? "a" : "d");
367  wrbuf_puts(w, case_sensitive ? "s" : "i");
368  if (missing)
369  {
370  if (!strcmp(missing, "omit")) {
371  ;
372  }
373  else if (!strcmp(missing, "abort"))
374  wrbuf_puts(w, "!");
375  else if (!strcmp(missing, "lowValue")) {
376  ;
377  }
378  else if (!strcmp(missing, "highValue")) {
379  ;
380  }
381  else
382  {
383  wrbuf_puts(w, "=");
384  wrbuf_puts(w, missing);
385  }
386  }
387  }
388  nmem_destroy(nmem);
389  return 0;
390 }
391 
392 int yaz_solr_sortkeys_to_sort_spec(const char *solr_sortkeys, WRBUF w)
393 {
394  /* Solr sortkey layout: field order[, field order] */
395  /* see cql_sortby_to_sortkeys of YAZ. */
396  char **sortspec;
397  int num_sortspec = 0;
398  int i;
399  NMEM nmem = nmem_create();
400 
401  if (solr_sortkeys)
402  nmem_strsplit(nmem, ",", solr_sortkeys, &sortspec, &num_sortspec);
403  for (i = 0; i < num_sortspec; i++)
404  {
405  char **arg;
406  int num_arg;
407  char order = 'a';
408  int case_sensitive = 0;
409  nmem_strsplitx(nmem, " ", sortspec[i], &arg, &num_arg, 0);
410 
411  if (num_arg != 2)
412  return -1;
413 
414  if (!yaz_matchstr(arg[1], "asc"))
415  order = 'a';
416  else if (!yaz_matchstr(arg[1], "desc"))
417  order = 'd';
418  else
419  return -1;
420 
421  if (i)
422  wrbuf_puts(w, " ");
423 
424  wrbuf_puts(w, arg[0]); /* field */
425  wrbuf_puts(w, " ");
426 
427  wrbuf_putc(w, order);
428  // Always in-sensitive
429  wrbuf_puts(w, case_sensitive ? "s" : "i");
430  }
431  nmem_destroy(nmem);
432  return 0;
433 }
434 
435 
436 /*
437  * Local variables:
438  * c-basic-offset: 4
439  * c-file-style: "Stroustrup"
440  * indent-tabs-mode: nil
441  * End:
442  * vim: shiftwidth=4 tabstop=8 expandtab
443  */
444 
#define Z_AttributeValue_numeric
Definition: z-core.h:586
#define Z_SortKeySpec_caseSensitive
Definition: z-core.h:1068
void nmem_strsplit(NMEM nmem, const char *delim, const char *dstr, char ***darray, int *num)
allocates sub strings out of string using certain delimitors
Definition: nmemsdup.c:61
char * buf
Definition: odr.h:101
ASN.1 Module Z39-50-APDU-1995.
union Z_SortElement::@69 u
Header for SortSpec parsing.
char * odr_strdup(ODR o, const char *str)
Definition: odr_mem.c:36
Header for WRBUF (growing buffer)
union Z_SortKeySpec::@68 u
Odr_int * sortRelation
Definition: z-core.h:1067
Odr_int * numeric
Definition: z-core.h:584
void nmem_destroy(NMEM n)
destroys NMEM handle and memory associated with it
Definition: nmem.c:204
void nmem_strsplit_blank(NMEM nmem, const char *dstr, char ***darray, int *num)
splits string into sub strings delimited by blanks
Definition: nmemsdup.c:55
Z_SortKey * generic
Definition: z-core.h:1095
void wrbuf_puts(WRBUF b, const char *buf)
appends C-string to WRBUF
Definition: wrbuf.c:89
#define Z_SortKeySpec_abort
Definition: z-core.h:1076
void wrbuf_write(WRBUF b, const char *buf, size_t size)
append constant size buffer to WRBUF
Definition: wrbuf.c:68
string buffer
Definition: wrbuf.h:42
Z_SortElement * sortElement
Definition: z-core.h:1062
Z_AttributeElement ** attributes
Definition: z-core.h:533
#define Z_SortKeySpec_missingValueData
Definition: z-core.h:1078
Z_SortAttributes * sortAttributes
Definition: z-core.h:1112
void * odr_malloc(ODR o, size_t size)
Definition: odr_mem.c:31
union Z_SortKey::@70 u
Header for YAZ iconv interface.
Z_AttributeSetId * attributeSet
Definition: z-core.h:580
Z_SortKeySpecList * yaz_sort_spec(ODR out, const char *arg)
parse sort spec string
Definition: sortspec.c:23
Header for OID database.
void wrbuf_insert(WRBUF b, size_t pos, const char *buf, size_t size)
inserts buffer into WRBUF at some position
Definition: wrbuf.c:78
int yaz_srw_sortkeys_to_sort_spec(const char *srw_sortkeys, WRBUF w)
Definition: sortspec.c:333
Odr_null * odr_nullval(void)
Definition: odr.c:30
Z_SortKeySpec ** specs
Definition: z-core.h:1032
#define Z_SortKey_sortAttributes
Definition: z-core.h:1115
union Z_AttributeElement::@53 value
void wrbuf_printf(WRBUF b, const char *fmt,...)
writes printf result to WRBUF
Definition: wrbuf.c:178
#define Z_SortKeySpec_null
Definition: z-core.h:1077
Odr_null * abort
Definition: z-core.h:1073
Odr_int * attributeType
Definition: z-core.h:581
Definition: odr.h:99
#define ODR_INT_PRINTF
Definition: odr.h:49
int yaz_solr_sortkeys_to_sort_spec(const char *solr_sortkeys, WRBUF w)
Definition: sortspec.c:392
int yaz_sort_spec_to_srw_sortkeys(Z_SortKeySpecList *sksl, WRBUF w)
Definition: sortspec.c:237
Odr_int * odr_intdup(ODR o, Odr_int v)
Definition: odr_mem.c:51
Definition: odr.h:124
int yaz_sort_spec_to_type7(Z_SortKeySpecList *sksl, WRBUF pqf)
Definition: sortspec.c:190
int yaz_matchstr(const char *s1, const char *s2)
match strings - independent of case and &#39;-&#39;
Definition: matchstr.c:42
#define Z_SortKeySpec_caseInsensitive
Definition: z-core.h:1069
#define wrbuf_putc(b, c)
Definition: wrbuf.h:268
Odr_oid * odr_oiddup(ODR odr, const Odr_oid *o)
Definition: odr_util.c:60
void nmem_strsplitx(NMEM nmem, const char *delim, const char *dstr, char ***darray, int *num, int collapse)
allocates sub strings out of string using certain delimitors
Definition: nmemsdup.c:67
Odr_null * null
Definition: z-core.h:1074
NMEM nmem_create(void)
returns new NMEM handle
Definition: nmem.c:181
int num_attributes
Definition: z-core.h:532
int which
Definition: z-core.h:1108
#define Z_SortKey_sortField
Definition: z-core.h:1113
#define Z_SortKeySpec_ascending
Definition: z-core.h:1063
const Odr_oid yaz_oid_attset_bib_1[]
Definition: oid_std.c:13
Z_AttributeSetId * id
Definition: z-core.h:1103
Odr_int odr_atoi(const char *s)
Definition: odr_mem.c:146
Odr_int * caseSensitivity
Definition: z-core.h:1070
Z_AttributeList * list
Definition: z-core.h:1104
int yaz_sort_spec_to_solr_sortkeys(Z_SortKeySpecList *sksl, WRBUF w)
Definition: sortspec.c:297
Z_InternationalString * sortField
Definition: z-core.h:1110
#define Z_SortElement_generic
Definition: z-core.h:1097
Odr_oct * missingValueData
Definition: z-core.h:1075
int yaz_sort_spec_to_cql(Z_SortKeySpecList *sksl, WRBUF w)
Definition: sortspec.c:135
#define Z_SortKeySpec_descending
Definition: z-core.h:1064
int len
Definition: odr.h:102