e635fabadb2d4257464b6464b905c58d8566ed68
[egate.git] / util / iso2709a.c
1 /*
2  * Iso2709 record management - anchor utilities
3  *
4  * Europagate, 1995.
5  *
6  * $Log: iso2709a.c,v $
7  * Revision 1.3  1995/03/30 14:22:18  adam
8  * More work on new MARC anchor functions.
9  *
10  * Revision 1.2  1995/03/30  07:33:35  adam
11  * New 2709 function: iso2709_mk.
12  * First implementation of iso2709_a_insert.
13  *
14  * Revision 1.1  1995/03/29  11:44:29  adam
15  * New functions: iso2709_a_.. for record manipulation.
16  *
17  */
18
19 #include <stdlib.h>
20 #include <string.h>
21 #include <stdio.h>
22 #include <assert.h>
23
24 #include <iso2709p.h>
25
26 Iso2709Anchor iso2709_a_mk (Iso2709Rec rec)
27 {
28     Iso2709Anchor anchor;
29     
30     anchor = malloc (sizeof(*anchor));
31     if (!anchor)
32         return NULL;
33     anchor->rec = rec;
34     anchor->d0 = &rec->directory;
35     if (*anchor->d0)
36         anchor->f0 = &(*anchor->d0)->fields;
37     else
38         anchor->f0 = NULL;
39     return anchor;
40 }
41
42 void iso2709_a_rm (Iso2709Anchor anchor)
43 {
44     free (anchor);
45 }
46
47 int iso2709_a_first (Iso2709Anchor anchor)
48 {
49     anchor->d0 = &anchor->rec->directory;
50     if (*anchor->d0)
51     {
52         anchor->f0 = &(*anchor->d0)->fields;
53         return 1;
54     }
55     return 0;
56 }
57
58 int iso2709_a_next_line (Iso2709Anchor anchor)
59 {
60     if (! *anchor->d0)
61         return 0;
62     anchor->d0 = &(*anchor->d0)->next;
63     if (*anchor->d0)
64         anchor->f0 = &(*anchor->d0)->fields;
65     return 1;
66 }
67
68 int iso2709_a_next_field (Iso2709Anchor anchor)
69 {
70     if (!*anchor->d0 || !*anchor->f0)
71         return 0;
72     if (!(*anchor->f0)->next)
73         return 0;
74     anchor->f0 = &(*anchor->f0)->next;
75     return 1;
76 }
77
78 int iso2709_a_next (Iso2709Anchor anchor)
79 {
80     if (!*anchor->d0 || !*anchor->f0)
81         return iso2709_a_next_line (anchor);
82     anchor->f0 = &(*anchor->f0)->next;
83     if (! *anchor->f0)
84         return iso2709_a_next_line (anchor);
85     return 2;
86 }
87
88 int iso2709_a_info_field (Iso2709Anchor anchor,
89                     char **tag, char **indicator,
90                     char **identifier, char **data)
91 {
92     if (!*anchor->d0 || !*anchor->f0)
93         return 0;
94     if (tag)
95         *tag = (*anchor->d0)->tag;
96     if (indicator)
97     {
98         *indicator = (*anchor->d0)->indicator;
99         if (*indicator && !**indicator)
100             *indicator = NULL;
101     }
102     if (identifier)
103     {
104         *identifier = (*anchor->f0)->identifier;
105         if (*identifier && !**identifier)
106             *identifier = NULL;
107     }
108     if (data)
109         *data = (*anchor->f0)->data;
110     return 1;
111 }
112
113 int iso2709_a_info_line (Iso2709Anchor anchor,
114                     char **tag, char **indicator)
115 {
116     if (!*anchor->d0)
117         return 0;
118     assert (*anchor->f0);
119     return iso2709_a_info_field (anchor, tag, indicator, NULL, NULL);
120 }
121
122 int iso2709_a_delete_field (Iso2709Anchor anchor)
123 {
124     struct iso2709_field *field;
125
126     if (!*anchor->d0)
127         return 0;
128     field = *anchor->f0;
129     *anchor->f0 = field->next;
130     free (field->data);
131     free (field);
132     if (!*anchor->f0)
133     {
134         if (! (*anchor->d0)->fields)
135             iso2709_a_delete_line (anchor);
136         iso2709_a_next_line (anchor);
137     }
138     return 1;
139 }
140
141 int iso2709_a_delete_line (Iso2709Anchor anchor)
142 {
143     struct iso2709_dir *dir;
144
145     if (!*anchor->d0)
146         return 0;
147     dir = *anchor->d0;
148     *anchor->d0 = dir->next;
149     free (dir->indicator);
150     free (dir);
151     return 1;
152 }
153
154 static int marc_cmp (const char *field, const char *pattern)
155 {
156     if (*pattern == '*')
157         return 0;
158     if (!field)
159         return -*pattern;
160     for (; *field && *pattern; field++, pattern++)
161     {
162         if (*pattern == '?')
163             continue;
164         if (*pattern != *field)
165             break;
166     }
167     return *field - *pattern;
168 }
169
170 int iso2709_a_search (Iso2709Anchor anchor,
171                       const char *tag_p, const char *indicator_p,
172                       const char *identifier_p)
173 {
174     char *tag;
175     char *indicator;
176     char *identifier;
177     do
178     {
179         if (!iso2709_a_info_field (anchor, &tag, &indicator,
180                                    &identifier, NULL))
181             return 0;
182         if ((!tag_p || !marc_cmp (tag, tag_p)) &&
183             (!indicator_p || !marc_cmp (indicator, indicator_p)) &&
184             (!identifier_p || !marc_cmp (identifier, identifier_p)))
185             return 1;
186     } while (iso2709_a_next (anchor));
187     return 0;
188 }
189
190 int iso2709_a_insert (Iso2709Anchor a, 
191                       const char *tag, const char *indicator,
192                       const char *identifier, const char *data)
193 {
194     struct iso2709_field *field;
195
196     assert (data);
197     assert (tag);
198     assert (a->d0);
199     if (! *a->d0 || strcmp (tag, (*a->d0)->tag))
200     {
201         struct iso2709_dir *dir;
202
203         if (!(dir = malloc (sizeof(*dir))))
204             return 0;
205         strcpy (dir->tag, tag);
206         if (indicator)
207         {
208             if (!(dir->indicator = malloc (strlen(indicator)+1)))
209                 return 0;
210             strcpy (dir->indicator, indicator);
211         }
212         else
213             dir->indicator = NULL;
214         if (*a->d0)
215             a->d0 = &(*a->d0)->next;
216         dir->next = *a->d0;
217         *a->d0 = dir;
218         dir->fields = NULL;
219         a->f0 = &dir->fields;
220     }
221     if (!(field = malloc (sizeof(*field))))
222         return 0;
223     if (identifier)
224         strcpy (field->identifier, identifier);
225     else
226         *field->identifier = '\0';
227     if (!(field->data = malloc (strlen (data)+1)))
228         return 0;
229     strcpy (field->data, data);
230     field->next = *a->f0;
231     *a->f0 = field;
232     a->f0 = &field->next;
233     return 1;
234 }