New function: iso2709_out. This function is the reverse of iso2709_cvt.
[egate.git] / util / iso2709o.c
diff --git a/util/iso2709o.c b/util/iso2709o.c
new file mode 100644 (file)
index 0000000..1af8693
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Iso2709 record management
+ *
+ * Europagate, 1995.
+ *
+ * $Log: iso2709o.c,v $
+ * Revision 1.1  1995/03/28 16:07:07  adam
+ * New function: iso2709_out. This function is the reverse of iso2709_cvt.
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <iso2709p.h>
+
+static void memint (char *p, int val, int len)
+{
+    static char buf[9];
+
+    if (len == 1)
+        *p = val + '0';
+    else
+    {
+        sprintf (buf, "%08d", val);
+        memcpy (p, buf+8-len, len);
+    }
+}
+
+int iso2709_out (Iso2709Rec p, char **buf, int bsize)
+{
+    struct iso2709_field *field;
+    struct iso2709_dir *dir;
+    int len = 26;
+    int base_address = 25;
+    int entry_p, data_p;
+    char *op;
+
+    for (dir = p->directory; dir; dir = dir->next)
+    {
+        len += 4 + p->length_data_entry + p->length_starting
+            + p->length_implementation;
+        base_address += 3 + p->length_data_entry + p->length_starting
+            + p->length_implementation;
+        if (dir->indicator)
+            len += p->indicator_length;
+        for (field = dir->fields; field; field = field->next)
+        {
+            if (field->identifier)
+                len += p->identifier_length;
+            len += strlen (field->data);
+        }
+    }
+    if (!buf)
+        return len;
+    if (bsize)
+    {
+        if (bsize <= len)
+            return -2;
+    }
+    else
+    {
+        *buf = malloc (len);
+        if (!*buf)
+            return -1;
+    }
+    op = *buf;
+    memint (op, len, 5);
+    memcpy (op+5, p->record_status, 1);
+    memcpy (op+6, p->implementation_codes, 4);
+    memint (op+10, p->indicator_length, 1);
+    memint (op+11, p->identifier_length, 1);
+    memint (op+12, base_address, 5);
+    memcpy (op+17, p->user_systems, 3);
+    memint (op+20, p->length_data_entry, 1);
+    memint (op+21, p->length_starting, 1);
+    memint (op+22, p->length_implementation, 1);
+    memcpy (op+23, p->future_use, 1);
+    
+    entry_p = 24;
+    data_p = base_address;
+
+    for (dir = p->directory; dir; dir = dir->next)
+    {
+        int data_0 = data_p;
+        if (dir->indicator)
+        {
+            memcpy (op + data_p, dir->indicator, p->indicator_length);
+            data_p += p->indicator_length;
+        }
+        for (field = dir->fields; field; field = field->next)
+        {
+            if (field->identifier)
+            {
+                op[data_p] = ISO2709_IDFS;
+                memcpy (op + data_p+1, field->identifier,
+                        p->identifier_length-1);
+                data_p += p->identifier_length;
+            }
+            memcpy (op + data_p, field->data, strlen(field->data));
+            data_p += strlen(field->data);
+        }
+        op[data_p++] = ISO2709_FS;
+
+        memcpy (op + entry_p, dir->tag, 3);
+        entry_p += 3;
+        memint (op + entry_p, data_p - data_0, p->length_data_entry);
+        entry_p += p->length_data_entry;
+        memint (op + entry_p, data_0 - base_address, p->length_starting);
+        entry_p += p->length_starting;
+        entry_p += p->length_implementation;
+    }
+    op[entry_p++] = ISO2709_FS;
+    assert (entry_p == base_address);
+    op[data_p++] = ISO2709_RS;
+    assert (data_p == len);
+    return len;
+}