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