Minor changes.
[egate.git] / util / iso2709a.c
1 /*
2  * Copyright (c) 1995, the EUROPAGATE consortium (see below).
3  *
4  * The EUROPAGATE consortium members are:
5  *
6  *    University College Dublin
7  *    Danmarks Teknologiske Videnscenter
8  *    An Chomhairle Leabharlanna
9  *    Consejo Superior de Investigaciones Cientificas
10  *
11  * Permission to use, copy, modify, distribute, and sell this software and
12  * its documentation, in whole or in part, for any purpose, is hereby granted,
13  * provided that:
14  *
15  * 1. This copyright and permission notice appear in all copies of the
16  * software and its documentation. Notices of copyright or attribution
17  * which appear at the beginning of any file must remain unchanged.
18  *
19  * 2. The names of EUROPAGATE or the project partners may not be used to
20  * endorse or promote products derived from this software without specific
21  * prior written permission.
22  *
23  * 3. Users of this software (implementors and gateway operators) agree to
24  * inform the EUROPAGATE consortium of their use of the software. This
25  * information will be used to evaluate the EUROPAGATE project and the
26  * software, and to plan further developments. The consortium may use
27  * the information in later publications.
28  * 
29  * 4. Users of this software agree to make their best efforts, when
30  * documenting their use of the software, to acknowledge the EUROPAGATE
31  * consortium, and the role played by the software in their work.
32  *
33  * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
34  * EXPRESS, IMPLIED, OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
35  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
36  * IN NO EVENT SHALL THE EUROPAGATE CONSORTIUM OR ITS MEMBERS BE LIABLE
37  * FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF
38  * ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
39  * OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND
40  * ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
41  * USE OR PERFORMANCE OF THIS SOFTWARE.
42  *
43  */
44 /*
45  * Iso2709 record management - anchor utilities
46  *
47  * Europagate, 1995.
48  *
49  * $Log: iso2709a.c,v $
50  * Revision 1.4  1995/05/16 09:40:54  adam
51  * LICENSE.
52  *
53  * Revision 1.3  1995/03/30  14:22:18  adam
54  * More work on new MARC anchor functions.
55  *
56  * Revision 1.2  1995/03/30  07:33:35  adam
57  * New 2709 function: iso2709_mk.
58  * First implementation of iso2709_a_insert.
59  *
60  * Revision 1.1  1995/03/29  11:44:29  adam
61  * New functions: iso2709_a_.. for record manipulation.
62  *
63  */
64
65 #include <stdlib.h>
66 #include <string.h>
67 #include <stdio.h>
68 #include <assert.h>
69
70 #include <iso2709p.h>
71
72 Iso2709Anchor iso2709_a_mk (Iso2709Rec rec)
73 {
74     Iso2709Anchor anchor;
75     
76     anchor = malloc (sizeof(*anchor));
77     if (!anchor)
78         return NULL;
79     anchor->rec = rec;
80     anchor->d0 = &rec->directory;
81     if (*anchor->d0)
82         anchor->f0 = &(*anchor->d0)->fields;
83     else
84         anchor->f0 = NULL;
85     return anchor;
86 }
87
88 void iso2709_a_rm (Iso2709Anchor anchor)
89 {
90     free (anchor);
91 }
92
93 int iso2709_a_first (Iso2709Anchor anchor)
94 {
95     anchor->d0 = &anchor->rec->directory;
96     if (*anchor->d0)
97     {
98         anchor->f0 = &(*anchor->d0)->fields;
99         return 1;
100     }
101     return 0;
102 }
103
104 int iso2709_a_next_line (Iso2709Anchor anchor)
105 {
106     if (! *anchor->d0)
107         return 0;
108     anchor->d0 = &(*anchor->d0)->next;
109     if (*anchor->d0)
110         anchor->f0 = &(*anchor->d0)->fields;
111     return 1;
112 }
113
114 int iso2709_a_next_field (Iso2709Anchor anchor)
115 {
116     if (!*anchor->d0 || !*anchor->f0)
117         return 0;
118     if (!(*anchor->f0)->next)
119         return 0;
120     anchor->f0 = &(*anchor->f0)->next;
121     return 1;
122 }
123
124 int iso2709_a_next (Iso2709Anchor anchor)
125 {
126     if (!*anchor->d0 || !*anchor->f0)
127         return iso2709_a_next_line (anchor);
128     anchor->f0 = &(*anchor->f0)->next;
129     if (! *anchor->f0)
130         return iso2709_a_next_line (anchor);
131     return 2;
132 }
133
134 int iso2709_a_info_field (Iso2709Anchor anchor,
135                     char **tag, char **indicator,
136                     char **identifier, char **data)
137 {
138     if (!*anchor->d0 || !*anchor->f0)
139         return 0;
140     if (tag)
141         *tag = (*anchor->d0)->tag;
142     if (indicator)
143     {
144         *indicator = (*anchor->d0)->indicator;
145         if (*indicator && !**indicator)
146             *indicator = NULL;
147     }
148     if (identifier)
149     {
150         *identifier = (*anchor->f0)->identifier;
151         if (*identifier && !**identifier)
152             *identifier = NULL;
153     }
154     if (data)
155         *data = (*anchor->f0)->data;
156     return 1;
157 }
158
159 int iso2709_a_info_line (Iso2709Anchor anchor,
160                     char **tag, char **indicator)
161 {
162     if (!*anchor->d0)
163         return 0;
164     assert (*anchor->f0);
165     return iso2709_a_info_field (anchor, tag, indicator, NULL, NULL);
166 }
167
168 int iso2709_a_delete_field (Iso2709Anchor anchor)
169 {
170     struct iso2709_field *field;
171
172     if (!*anchor->d0)
173         return 0;
174     field = *anchor->f0;
175     *anchor->f0 = field->next;
176     free (field->data);
177     free (field);
178     if (!*anchor->f0)
179     {
180         if (! (*anchor->d0)->fields)
181             iso2709_a_delete_line (anchor);
182         iso2709_a_next_line (anchor);
183     }
184     return 1;
185 }
186
187 int iso2709_a_delete_line (Iso2709Anchor anchor)
188 {
189     struct iso2709_dir *dir;
190
191     if (!*anchor->d0)
192         return 0;
193     dir = *anchor->d0;
194     *anchor->d0 = dir->next;
195     free (dir->indicator);
196     free (dir);
197     return 1;
198 }
199
200 static int marc_cmp (const char *field, const char *pattern)
201 {
202     if (*pattern == '*')
203         return 0;
204     if (!field)
205         return -*pattern;
206     for (; *field && *pattern; field++, pattern++)
207     {
208         if (*pattern == '?')
209             continue;
210         if (*pattern != *field)
211             break;
212     }
213     return *field - *pattern;
214 }
215
216 int iso2709_a_search (Iso2709Anchor anchor,
217                       const char *tag_p, const char *indicator_p,
218                       const char *identifier_p)
219 {
220     char *tag;
221     char *indicator;
222     char *identifier;
223     do
224     {
225         if (!iso2709_a_info_field (anchor, &tag, &indicator,
226                                    &identifier, NULL))
227             return 0;
228         if ((!tag_p || !marc_cmp (tag, tag_p)) &&
229             (!indicator_p || !marc_cmp (indicator, indicator_p)) &&
230             (!identifier_p || !marc_cmp (identifier, identifier_p)))
231             return 1;
232     } while (iso2709_a_next (anchor));
233     return 0;
234 }
235
236 int iso2709_a_insert (Iso2709Anchor a, 
237                       const char *tag, const char *indicator,
238                       const char *identifier, const char *data)
239 {
240     struct iso2709_field *field;
241
242     assert (data);
243     assert (tag);
244     assert (a->d0);
245     if (! *a->d0 || strcmp (tag, (*a->d0)->tag))
246     {
247         struct iso2709_dir *dir;
248
249         if (!(dir = malloc (sizeof(*dir))))
250             return 0;
251         strcpy (dir->tag, tag);
252         if (indicator)
253         {
254             if (!(dir->indicator = malloc (strlen(indicator)+1)))
255                 return 0;
256             strcpy (dir->indicator, indicator);
257         }
258         else
259             dir->indicator = NULL;
260         if (*a->d0)
261             a->d0 = &(*a->d0)->next;
262         dir->next = *a->d0;
263         *a->d0 = dir;
264         dir->fields = NULL;
265         a->f0 = &dir->fields;
266     }
267     if (!(field = malloc (sizeof(*field))))
268         return 0;
269     if (identifier)
270         strcpy (field->identifier, identifier);
271     else
272         *field->identifier = '\0';
273     if (!(field->data = malloc (strlen (data)+1)))
274         return 0;
275     strcpy (field->data, data);
276     field->next = *a->f0;
277     *a->f0 = field;
278     a->f0 = &field->next;
279     return 1;
280 }