bag

Dutch BAG Kadaster Extract parser (subset)
git clone git://git.codemadness.org/bag
Log | Files | Refs | README | 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 }