3be267407c1c32ce3a42a9c4ac1f94c83bbffd48
[yaz-moved-to-github.git] / zutil / sortspec.c
1 /*
2  * Copyright (c) 1995-2001, Index Data.
3  * See the file LICENSE for details.
4  *
5  * $Id: sortspec.c,v 1.3 2001-09-24 21:51:56 adam Exp $
6  */
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11
12 #include <yaz/proto.h>
13 #include <yaz/oid.h>
14 #include <yaz/sortspec.h>
15
16 Z_SortKeySpecList *yaz_sort_spec (ODR out, const char *arg)
17 {
18     char sort_string_buf[32], sort_flags[32];
19     Z_SortKeySpecList *sksl = (Z_SortKeySpecList *)
20         odr_malloc (out, sizeof(*sksl));
21     int off;
22     
23     sksl->num_specs = 0;
24     sksl->specs = (Z_SortKeySpec **)odr_malloc (out, sizeof(sksl->specs) * 20);
25     
26     while ((sscanf (arg, "%31s %31s%n", sort_string_buf,
27                     sort_flags, &off)) == 2  && off > 1)
28     {
29         int i;
30         char *sort_string_sep;
31         char *sort_string = sort_string_buf;
32         Z_SortKeySpec *sks = (Z_SortKeySpec *)odr_malloc (out, sizeof(*sks));
33         Z_SortKey *sk = (Z_SortKey *)odr_malloc (out, sizeof(*sk));
34         
35         arg += off;
36         sksl->specs[sksl->num_specs++] = sks;
37         sks->sortElement = (Z_SortElement *)
38             odr_malloc (out, sizeof(*sks->sortElement));
39         sks->sortElement->which = Z_SortElement_generic;
40         sks->sortElement->u.generic = sk;
41         
42         if ((sort_string_sep = strchr (sort_string, '=')))
43         {
44             int i = 0;
45             sk->which = Z_SortKey_sortAttributes;
46             sk->u.sortAttributes = (Z_SortAttributes *)
47                 odr_malloc (out, sizeof(*sk->u.sortAttributes));
48             sk->u.sortAttributes->id = 
49                 yaz_oidval_to_z3950oid(out, CLASS_ATTSET, VAL_BIB1);
50             sk->u.sortAttributes->list = (Z_AttributeList *)
51                 odr_malloc (out, sizeof(*sk->u.sortAttributes->list));
52             sk->u.sortAttributes->list->attributes = (Z_AttributeElement **)
53                 odr_malloc (out, 10 * 
54                             sizeof(*sk->u.sortAttributes->list->attributes));
55             while (i < 10 && sort_string && sort_string_sep)
56             {
57                 Z_AttributeElement *el = (Z_AttributeElement *)
58                     odr_malloc (out, sizeof(*el));
59                 sk->u.sortAttributes->list->attributes[i] = el;
60                 el->attributeSet = 0;
61                 el->attributeType = odr_intdup (out, atoi (sort_string));
62                 el->which = Z_AttributeValue_numeric;
63                 el->value.numeric =
64                     odr_intdup (out, atoi (sort_string_sep + 1));
65                 i++;
66                 sort_string = strchr(sort_string, ',');
67                 if (sort_string)
68                 {
69                     sort_string++;
70                     sort_string_sep = strchr (sort_string, '=');
71                 }
72             }
73             sk->u.sortAttributes->list->num_attributes = i;
74         }
75         else
76         {
77             sk->which = Z_SortKey_sortField;
78             sk->u.sortField = odr_strdup (out, sort_string);
79         }
80         sks->sortRelation = odr_intdup (out, Z_SortRelation_ascending);
81         sks->caseSensitivity = odr_intdup (out, Z_SortCase_caseSensitive);
82
83 #ifdef ASN_COMPILED
84         sks->which = Z_SortKeySpec_null;
85         sks->u.null = odr_nullval ();
86 #else
87         sks->missingValueAction = NULL;
88 #endif
89         
90         for (i = 0; sort_flags[i]; i++)
91         {
92             switch (sort_flags[i])
93             {
94             case 'd':
95             case 'D':
96             case '>':
97                 *sks->sortRelation = Z_SortRelation_descending;
98                 break;
99             case 'a':
100             case 'A':
101             case '<':
102                 *sks->sortRelation = Z_SortRelation_ascending;
103                 break;
104             case 'i':
105             case 'I':
106                 *sks->caseSensitivity = Z_SortCase_caseInsensitive;
107                 break;
108             case 'S':
109             case 's':
110                 *sks->caseSensitivity = Z_SortCase_caseSensitive;
111                 break;
112             }
113         }
114     }
115     if (!sksl->num_specs)
116         return 0;
117     return sksl;
118 }