glue.c - bag - Dutch BAG Kadaster Extract parser (subset)
 (HTM) git clone git://git.codemadness.org/bag
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       glue.c (2865B)
       ---
            1 #if WIN32
            2 #include <io.h> /* for setmode() */
            3 #endif
            4 
            5 #include <stdio.h>
            6 #include <string.h>
            7 #include <stdlib.h>
            8 
            9 #define PUTCHAR putchar
           10 #define FPUTS fputs
           11 
           12 #define FieldLast 8
           13 
           14 struct string {
           15         char *data;
           16         size_t len;
           17         size_t cap;
           18 };
           19 
           20 static struct string mergedfields[FieldLast];
           21 static char *fields[FieldLast];
           22 
           23 /* Splits fields in the line buffer by replacing TAB separators with NUL ('\0')
           24 * terminators and assign these fields as pointers. If there are less fields
           25 * than expected then the field is an empty string constant. */
           26 void
           27 parseline(char *line, char *fields[FieldLast])
           28 {
           29         char *prev, *s;
           30         size_t i;
           31 
           32         for (prev = line, i = 0;
           33             (s = strchr(prev, '\t')) && i < FieldLast - 1;
           34             ++i) {
           35                 *s = '\0';
           36                 fields[i] = prev;
           37                 prev = s + 1;
           38         }
           39         fields[i++] = prev;
           40         /* make non-parsed fields empty. */
           41         for (; i < FieldLast; i++)
           42                 fields[i] = "";
           43 }
           44 
           45 void
           46 printfields(void)
           47 {
           48         if (!mergedfields[0].len)
           49                 return;
           50 
           51         fputs(mergedfields[0].data, stdout);
           52         fputs("\t", stdout);
           53         fputs(mergedfields[1].data, stdout);
           54         fputs("\t", stdout);
           55         fputs(mergedfields[2].data, stdout);
           56         fputs("\t", stdout);
           57         fputs(mergedfields[3].data, stdout);
           58         fputs("\t", stdout);
           59         fputs(mergedfields[4].data, stdout);
           60         fputs("\t", stdout);
           61         fputs(mergedfields[5].data, stdout);
           62         fputs("\t", stdout);
           63         fputs(mergedfields[6].data, stdout);
           64         fputs("\t", stdout);
           65         fputs(mergedfields[7].data, stdout);
           66         fputs("\n", stdout);
           67 }
           68 
           69 void
           70 string_reset(struct string *d)
           71 {
           72         d->data[0] = '\0';
           73         d->len = 0;
           74 }
           75 
           76 void
           77 string_set(struct string *d, const char *data)
           78 {
           79         size_t len;
           80 
           81         len = strlen(data);
           82         if (len + 1 >= d->cap) {
           83                 d->cap = d->cap + len + 1;
           84                 if (!(d->data = realloc(d->data, d->cap))) {
           85                         perror(NULL);
           86                         exit(1);
           87                 }
           88         }
           89         memcpy(d->data, data, len + 1); /* copy including NUL byte */
           90         d->len = len;
           91 }
           92 
           93 int
           94 main(void)
           95 {
           96         char line[4096], *p;
           97         size_t i;
           98 
           99         /* required for Windows binary mode aka more retarded bullshit. */
          100 #if WIN32
          101         /* binary mode for stdin, stdout and stderr */
          102         _setmode(0, 0x8000); /* 0x8000 is O_BINARY */
          103         _setmode(1, 0x8000);
          104         _setmode(2, 0x8000);
          105 #endif
          106 
          107         for (i = 0; i < FieldLast; ++i) {
          108                 mergedfields[i].cap = 4096;
          109                 if (!(mergedfields[i].data = calloc(1, 4096))) {
          110                         perror(NULL);
          111                         exit(1);
          112                 }
          113                 mergedfields[i].len = 0;
          114         }
          115 
          116         while (fgets(line, sizeof(line), stdin)) {
          117                 if ((p = strchr(line, '\n')))
          118                         *p = '\0';
          119 
          120                 parseline(line, fields);
          121 
          122                 /* primary key */
          123                 if (strcmp(fields[0], mergedfields[0].data)) {
          124                         printfields();
          125                         for (i = 0; i < FieldLast; ++i)
          126                                 string_reset(&mergedfields[i]);
          127                         string_set(&mergedfields[0], fields[0]);
          128                 }
          129 
          130                 for (i = 1; i < FieldLast; ++i) {
          131                         /* field is set: override with next */
          132                         if (!fields[i][0])
          133                                 continue;
          134                         string_set(&mergedfields[i], fields[i]);
          135                 }
          136         }
          137         printfields();
          138 
          139         if (ferror(stdin) || (fflush(stdout) && ferror(stdout))) {
          140                 perror(NULL);
          141                 exit(1);
          142         }
          143 
          144         return 0;
          145 }