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