7f6c612ddf9ac143f22ae171d45331e10bac0fc4
[idzebra-moved-to-github.git] / data1 / d1_tagset.c
1 /* This file is part of the Zebra server.
2    Copyright (C) 1994-2009 Index Data
3
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
18 */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include <yaz/log.h>
25 #include <idzebra/data1.h>
26 #include <yaz/oid_db.h>
27
28 /*
29  * We'll probably want to add some sort of hashed index to these lookup-
30  * functions eventually.
31  */
32
33 data1_datatype data1_maptype (data1_handle dh, char *t)
34 {
35     static struct
36     {
37         char *tname;
38         data1_datatype type;
39     } types[] =
40     {
41         {"structured", DATA1K_structured},
42         {"string", DATA1K_string},
43         {"numeric", DATA1K_numeric},
44         {"oid", DATA1K_oid},
45         {"bool", DATA1K_bool},
46         {"generalizedtime", DATA1K_generalizedtime},
47         {"intunit", DATA1K_intunit},
48         {"int", DATA1K_int},
49         {"octetstring", DATA1K_octetstring},
50         {"null", DATA1K_null},
51         {NULL, (data1_datatype) -1}
52     };
53     int i;
54
55     for (i = 0; types[i].tname; i++)
56         if (!data1_matchstr(types[i].tname, t))
57             return types[i].type;
58     return DATA1K_unknown;
59 }
60
61 data1_tag *data1_gettagbynum (data1_handle dh, data1_tagset *s,
62                               int type, int value)
63 {
64     data1_tag *r;
65     
66     for (; s; s = s->next)
67     {
68         /* scan local set */
69         if (type == s->type)
70             for (r = s->tags; r; r = r->next)
71                 if (r->which == DATA1T_numeric && r->value.numeric == value)
72                     return r;
73         /* scan included sets */
74         if (s->children &&
75             (r = data1_gettagbynum (dh, s->children, type, value)))
76             return r;
77     }
78     return 0;
79 }
80
81 data1_tag *data1_gettagbyname (data1_handle dh, data1_tagset *s,
82                                const char *name)
83 {
84     data1_tag *r;
85
86     for (; s; s = s->next)
87     {
88         /* scan local set */
89         for (r = s->tags; r; r = r->next)
90         {
91             data1_name *np;
92
93             for (np = r->names; np; np = np->next)
94                 if (!data1_matchstr(np->name, name))
95                     return r;
96         }
97         /* scan included sets */
98         if (s->children && (r = data1_gettagbyname (dh, s->children, name)))
99             return r;
100     }
101     return 0;
102 }
103
104 data1_tagset *data1_empty_tagset (data1_handle dh)
105 {
106     data1_tagset *res =
107         (data1_tagset *) nmem_malloc(data1_nmem_get (dh), sizeof(*res));
108     res->name = 0;
109     res->oid = 0;
110     res->tags = 0;
111     res->type = 0;
112     res->children = 0;
113     res->next = 0;
114     return res;
115 }
116
117 data1_tagset *data1_read_tagset (data1_handle dh, const char *file, int type)
118 {
119     NMEM mem = data1_nmem_get (dh);
120     data1_tagset *res = 0;
121     data1_tagset **childp;
122     data1_tag **tagp;
123     FILE *f;
124     int lineno = 0;
125     int argc;
126     char *argv[50], line[512];
127
128     if (!(f = data1_path_fopen(dh, file, "r")))
129     {
130         yaz_log(YLOG_WARN|YLOG_ERRNO, "%s", file);
131         return 0;
132     }
133     res = data1_empty_tagset (dh);
134     res->type = type;
135     childp = &res->children;
136     tagp = &res->tags;
137
138     while ((argc = readconf_line(f, &lineno, line, 512, argv, 50)))
139     {
140         char *cmd = *argv;
141         if (!strcmp(cmd, "tag"))
142         {
143             int value;
144             char *names, *type, *nm;
145             data1_tag *rr;
146             data1_name **npp;
147
148             if (argc != 4)
149             {
150                 yaz_log(YLOG_WARN, "%s:%d: Bad # args to tag", file, lineno);
151                 continue;
152             }
153             value = atoi(argv[1]);
154             names = argv[2];
155             type = argv[3];
156
157             rr = *tagp = (data1_tag *)nmem_malloc(mem, sizeof(*rr));
158             rr->tagset = res;
159             rr->next = 0;
160             rr->which = DATA1T_numeric;
161             rr->value.numeric = value;
162             /*
163              * how to deal with local numeric tags?
164              */
165
166             if (!(rr->kind = data1_maptype(dh, type)))
167             {
168                 yaz_log(YLOG_WARN, "%s:%d: Unknown datatype %s",
169                      file, lineno, type);
170                 fclose(f);
171                 return 0;
172             }
173             
174             /* read namelist */
175             nm = names;
176             npp = &rr->names;
177             do
178             {
179                 char *e;
180
181                 *npp = (data1_name *)nmem_malloc(mem, sizeof(**npp));
182                 if ((e = strchr(nm, '/')))
183                     *(e++) = '\0';
184                 (*npp)->name = nmem_strdup(mem, nm);
185                 (*npp)->next = 0;
186                 npp = &(*npp)->next;
187                 nm = e;
188             }
189             while (nm);
190             tagp = &rr->next;
191         }
192         else if (!strcmp(cmd, "name"))
193         {
194             if (argc != 2)
195             {
196                 yaz_log(YLOG_WARN, "%s:%d: Bad # args to name", file, lineno);
197                 continue;
198             }
199             res->name = nmem_strdup(mem, argv[1]);
200         }
201         else if (!strcmp(cmd, "reference"))
202         {
203             char *name;
204             
205             if (argc != 2)
206             {
207                 yaz_log(YLOG_WARN, "%s:%d: Bad # args to reference",
208                         file, lineno);
209                 continue;
210             }
211             name = argv[1];
212             res->oid = yaz_string_to_oid_nmem(yaz_oid_std(),
213                                               CLASS_TAGSET, name, mem);
214             if (!res->oid)
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 }
263 /*
264  * Local variables:
265  * c-basic-offset: 4
266  * c-file-style: "Stroustrup"
267  * indent-tabs-mode: nil
268  * End:
269  * vim: shiftwidth=4 tabstop=8 expandtab
270  */
271