8588ea1a6120380a72221f67f59033c7130996a6
[egate.git] / util / iso2709o.c
1 /*
2  * Iso2709 record management
3  *
4  * Europagate, 1995.
5  *
6  * $Log: iso2709o.c,v $
7  * Revision 1.2  1995/03/30 14:22:19  adam
8  * More work on new MARC anchor functions.
9  *
10  * Revision 1.1  1995/03/28  16:07:07  adam
11  * New function: iso2709_out. This function is the reverse of iso2709_cvt.
12  *
13  */
14
15 #include <stdlib.h>
16 #include <string.h>
17 #include <stdio.h>
18 #include <assert.h>
19 #include <ctype.h>
20
21 #include <iso2709p.h>
22
23 static void memint (char *p, int val, int len)
24 {
25     static char buf[9];
26
27     if (len == 1)
28         *p = val + '0';
29     else
30     {
31         sprintf (buf, "%08d", val);
32         memcpy (p, buf+8-len, len);
33     }
34 }
35
36 int iso2709_out (Iso2709Rec p, char **buf, int bsize)
37 {
38     struct iso2709_field *field;
39     struct iso2709_dir *dir;
40     int len = 26;
41     int base_address = 25;
42     int entry_p, data_p;
43     char *op;
44
45     for (dir = p->directory; dir; dir = dir->next)
46     {
47         len += 4 + p->length_data_entry + p->length_starting
48             + p->length_implementation;
49         base_address += 3 + p->length_data_entry + p->length_starting
50             + p->length_implementation;
51         if (dir->indicator)
52             len += p->indicator_length;
53         for (field = dir->fields; field; field = field->next)
54         {
55             if (*field->identifier)
56                 len += p->identifier_length;
57             len += strlen (field->data);
58         }
59     }
60     if (!buf)
61         return len;
62     if (bsize)
63     {
64         if (bsize <= len)
65             return -2;
66     }
67     else
68     {
69         *buf = malloc (len);
70         if (!*buf)
71             return -1;
72     }
73     op = *buf;
74     memint (op, len, 5);
75     memcpy (op+5, p->record_status, 1);
76     memcpy (op+6, p->implementation_codes, 4);
77     memint (op+10, p->indicator_length, 1);
78     memint (op+11, p->identifier_length, 1);
79     memint (op+12, base_address, 5);
80     memcpy (op+17, p->user_systems, 3);
81     memint (op+20, p->length_data_entry, 1);
82     memint (op+21, p->length_starting, 1);
83     memint (op+22, p->length_implementation, 1);
84     memcpy (op+23, p->future_use, 1);
85     
86     entry_p = 24;
87     data_p = base_address;
88
89     for (dir = p->directory; dir; dir = dir->next)
90     {
91         int data_0 = data_p;
92         if (dir->indicator)
93         {
94             memcpy (op + data_p, dir->indicator, p->indicator_length);
95             data_p += p->indicator_length;
96         }
97         for (field = dir->fields; field; field = field->next)
98         {
99             if (*field->identifier)
100             {
101                 op[data_p] = ISO2709_IDFS;
102                 memcpy (op + data_p+1, field->identifier,
103                         p->identifier_length-1);
104                 data_p += p->identifier_length;
105             }
106             memcpy (op + data_p, field->data, strlen(field->data));
107             data_p += strlen(field->data);
108         }
109         op[data_p++] = ISO2709_FS;
110
111         memcpy (op + entry_p, dir->tag, 3);
112         entry_p += 3;
113         memint (op + entry_p, data_p - data_0, p->length_data_entry);
114         entry_p += p->length_data_entry;
115         memint (op + entry_p, data_0 - base_address, p->length_starting);
116         entry_p += p->length_starting;
117         entry_p += p->length_implementation;
118     }
119     op[entry_p++] = ISO2709_FS;
120     assert (entry_p == base_address);
121     op[data_p++] = ISO2709_RS;
122     assert (data_p == len);
123     return len;
124 }