2e32ef44ac1dade774cfc00ef365e069224444e9
[idzebra-moved-to-github.git] / data1 / d1_tagset.c
1 /* $Id: d1_tagset.c,v 1.6 2005-01-15 19:38:18 adam Exp $
2    Copyright (C) 1995-2005
3    Index Data ApS
4
5 This file is part of the Zebra server.
6
7 Zebra is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Zebra; see the file LICENSE.zebra.  If not, write to the
19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <yaz/log.h>
28 #include <idzebra/data1.h>
29
30 /*
31  * We'll probably want to add some sort of hashed index to these lookup-
32  * functions eventually.
33  */
34
35 data1_datatype data1_maptype (data1_handle dh, char *t)
36 {
37     static struct
38     {
39         char *tname;
40         data1_datatype type;
41     } types[] =
42     {
43         {"structured", DATA1K_structured},
44         {"string", DATA1K_string},
45         {"numeric", DATA1K_numeric},
46         {"oid", DATA1K_oid},
47         {"bool", DATA1K_bool},
48         {"generalizedtime", DATA1K_generalizedtime},
49         {"intunit", DATA1K_intunit},
50         {"int", DATA1K_int},
51         {"octetstring", DATA1K_octetstring},
52         {"null", DATA1K_null},
53         {NULL, (data1_datatype) -1}
54     };
55     int i;
56
57     for (i = 0; types[i].tname; i++)
58         if (!data1_matchstr(types[i].tname, t))
59             return types[i].type;
60     return DATA1K_unknown;
61 }
62
63 data1_tag *data1_gettagbynum (data1_handle dh, data1_tagset *s,
64                               int type, int value)
65 {
66     data1_tag *r;
67     
68     for (; s; s = s->next)
69     {
70         /* scan local set */
71         if (type == s->type)
72             for (r = s->tags; r; r = r->next)
73                 if (r->which == DATA1T_numeric && r->value.numeric == value)
74                     return r;
75         /* scan included sets */
76         if (s->children &&
77             (r = data1_gettagbynum (dh, s->children, type, value)))
78             return r;
79     }
80     return 0;
81 }
82
83 data1_tag *data1_gettagbyname (data1_handle dh, data1_tagset *s,
84                                const char *name)
85 {
86     data1_tag *r;
87
88     for (; s; s = s->next)
89     {
90         /* scan local set */
91         for (r = s->tags; r; r = r->next)
92         {
93             data1_name *np;
94
95             for (np = r->names; np; np = np->next)
96                 if (!data1_matchstr(np->name, name))
97                     return r;
98         }
99         /* scan included sets */
100         if (s->children && (r = data1_gettagbyname (dh, s->children, name)))
101             return r;
102     }
103     return 0;
104 }
105
106 data1_tagset *data1_empty_tagset (data1_handle dh)
107 {
108     data1_tagset *res =
109         (data1_tagset *) nmem_malloc(data1_nmem_get (dh), sizeof(*res));
110     res->name = 0;
111     res->reference = VAL_NONE;
112     res->tags = 0;
113     res->type = 0;
114     res->children = 0;
115     res->next = 0;
116     return res;
117 }
118
119 data1_tagset *data1_read_tagset (data1_handle dh, const char *file, int type)
120 {
121     NMEM mem = data1_nmem_get (dh);
122     data1_tagset *res = 0;
123     data1_tagset **childp;
124     data1_tag **tagp;
125     FILE *f;
126     int lineno = 0;
127     int argc;
128     char *argv[50], line[512];
129
130     if (!(f = data1_path_fopen(dh, file, "r")))
131     {
132         yaz_log(YLOG_WARN|YLOG_ERRNO, "%s", file);
133         return 0;
134     }
135     res = data1_empty_tagset (dh);
136     res->type = type;
137     childp = &res->children;
138     tagp = &res->tags;
139
140     while ((argc = readconf_line(f, &lineno, line, 512, argv, 50)))
141     {
142         char *cmd = *argv;
143         if (!strcmp(cmd, "tag"))
144         {
145             int value;
146             char *names, *type, *nm;
147             data1_tag *rr;
148             data1_name **npp;
149
150             if (argc != 4)
151             {
152                 yaz_log(YLOG_WARN, "%s:%d: Bad # args to tag", file, lineno);
153                 continue;
154             }
155             value = atoi(argv[1]);
156             names = argv[2];
157             type = argv[3];
158
159             rr = *tagp = (data1_tag *)nmem_malloc(mem, sizeof(*rr));
160             rr->tagset = res;
161             rr->next = 0;
162             rr->which = DATA1T_numeric;
163             rr->value.numeric = value;
164             /*
165              * how to deal with local numeric tags?
166              */
167
168             if (!(rr->kind = data1_maptype(dh, type)))
169             {
170                 yaz_log(YLOG_WARN, "%s:%d: Unknown datatype %s",
171                      file, lineno, type);
172                 fclose(f);
173                 return 0;
174             }
175             
176             /* read namelist */
177             nm = names;
178             npp = &rr->names;
179             do
180             {
181                 char *e;
182
183                 *npp = (data1_name *)nmem_malloc(mem, sizeof(**npp));
184                 if ((e = strchr(nm, '/')))
185                     *(e++) = '\0';
186                 (*npp)->name = nmem_strdup(mem, nm);
187                 (*npp)->next = 0;
188                 npp = &(*npp)->next;
189                 nm = e;
190             }
191             while (nm);
192             tagp = &rr->next;
193         }
194         else if (!strcmp(cmd, "name"))
195         {
196             if (argc != 2)
197             {
198                 yaz_log(YLOG_WARN, "%s:%d: Bad # args to name", file, lineno);
199                 continue;
200             }
201             res->name = nmem_strdup(mem, argv[1]);
202         }
203         else if (!strcmp(cmd, "reference"))
204         {
205             char *name;
206             
207             if (argc != 2)
208             {
209                 yaz_log(YLOG_WARN, "%s:%d: Bad # args to reference",
210                         file, lineno);
211                 continue;
212             }
213             name = argv[1];
214             if ((res->reference = oid_getvalbyname(name)) == VAL_NONE)
215             {
216                 yaz_log(YLOG_WARN, "%s:%d: Unknown tagset ref '%s'",
217                         file, lineno, name);
218                 continue;
219             }
220         }
221         else if (!strcmp(cmd, "type"))
222         {
223             if (argc != 2)
224             {
225                 yaz_log (YLOG_WARN, "%s:%d: Bad # args to type", file, lineno);
226                 continue;
227             }
228             if (!res->type)
229                 res->type = atoi(argv[1]);
230         }
231         else if (!strcmp(cmd, "include"))
232         {
233             char *name;
234             int type = 0;
235
236             if (argc < 2)
237             {
238                 yaz_log(YLOG_WARN, "%s:%d: Bad # args to include",
239                         file, lineno);
240                 continue;
241             }
242             name = argv[1];
243             if (argc == 3)
244                 type = atoi(argv[2]);
245             *childp = data1_read_tagset (dh, name, type);
246             if (!(*childp))
247             {
248                 yaz_log(YLOG_WARN, "%s:%d: Inclusion failed for tagset %s",
249                         file, lineno, name);
250                 continue;
251             }
252             childp = &(*childp)->next;
253         }
254         else
255         {
256             yaz_log(YLOG_WARN, "%s:%d: Unknown directive '%s'",
257                     file, lineno, cmd);
258         }
259     }
260     fclose(f);
261     return res;
262 }