Skip to content
This repository
Browse code

Added the knhx library

  • Loading branch information...
commit ebfff490001fba06b8f51682d4de2792cafe18ca 1 parent 375fd6e
Attractive Chaos authored January 13, 2011

Showing 2 changed files with 123 additions and 0 deletions. Show diff stats Hide diff stats

  1. 107  knhx.c
  2. 16  knhx.h
107  knhx.c
... ...
@@ -0,0 +1,107 @@
  1
+#include <ctype.h>
  2
+#include <stdio.h>
  3
+#include <stdlib.h>
  4
+#include <string.h>
  5
+#include "knhx.h"
  6
+
  7
+typedef struct {
  8
+	int error, n, max;
  9
+	knhx1_t *node;
  10
+} knaux_t;
  11
+
  12
+static inline char *add_node(const char *s, knaux_t *aux, int x)
  13
+{
  14
+	char *p, *nbeg, *nend = 0;
  15
+	knhx1_t *r;
  16
+	if (aux->n == aux->max) {
  17
+		aux->max = aux->max? aux->max<<1 : 8;
  18
+		aux->node = (knhx1_t*)realloc(aux->node, sizeof(knhx1_t) * aux->max);
  19
+	}
  20
+	r = aux->node + (aux->n++);
  21
+	r->n = x; r->parent = -1;
  22
+	for (p = (char*)s, nbeg = p, r->d = -1.0; *p && *p != ',' && *p != ')'; ++p) {
  23
+		if (*p == '[') {
  24
+			if (nend == 0) nend = p;
  25
+			do ++p; while (*p && *p != ']');
  26
+			if (*p == 0) {
  27
+				aux->error |= KNERR_BRACKET;
  28
+				break;
  29
+			}
  30
+		} else if (*p == ':') {
  31
+			if (nend == 0) nend = p;
  32
+			r->d = strtod(p + 1, &p);
  33
+			--p;
  34
+		} else if (!isgraph(*p)) if (nend == 0) nend = p;
  35
+	}
  36
+	if (nend == 0) nend = p;
  37
+	if (nend != nbeg) {
  38
+		r->name = (char*)calloc(nend - nbeg + 1, 1);
  39
+		strncpy(r->name, nbeg, nend - nbeg);
  40
+	} else r->name = strdup("");
  41
+	return p;
  42
+}
  43
+
  44
+knhx1_t *kn_parse(const char *nhx, int *_n, int *_error)
  45
+{
  46
+	char *p;
  47
+	int *stack, top, max;
  48
+	knaux_t *aux;
  49
+	knhx1_t *ret;
  50
+
  51
+#define __push_back(y) do {										\
  52
+		if (top == max) {										\
  53
+			max = max? max<<1 : 16;								\
  54
+			stack = (int*)realloc(stack, sizeof(int) * max);	\
  55
+		}														\
  56
+		stack[top++] = (y);										\
  57
+	} while (0)													\
  58
+
  59
+	stack = 0; top = max = 0;
  60
+	p = (char*)nhx;
  61
+	aux = (knaux_t*)calloc(1, sizeof(knaux_t));
  62
+	while (*p) {
  63
+		while (*p && !isgraph(*p)) ++p;
  64
+		if (*p == 0) break;
  65
+		if (*p == ',') ++p;
  66
+		else if (*p == '(') {
  67
+			__push_back(-1);
  68
+			++p;
  69
+		} else if (*p == ')') {
  70
+			int x = aux->n, m, i;
  71
+			for (i = top - 1; i >= 0; --i)
  72
+				if (stack[i] < 0) break;
  73
+			m = top - 1 - i;
  74
+			p = add_node(p + 1, aux, m);
  75
+			aux->node[x].child = (int*)calloc(m, sizeof(int));
  76
+			for (i = top - 1, m = m - 1; m >= 0; --m, --i) {
  77
+				aux->node[x].child[m] = stack[i];
  78
+				aux->node[stack[i]].parent = x;
  79
+			}
  80
+			top = i;
  81
+			__push_back(x);
  82
+		} else {
  83
+			__push_back(aux->n);
  84
+			p = add_node(p, aux, 0);
  85
+		}
  86
+	}
  87
+	*_n = aux->n;
  88
+	*_error = aux->error;
  89
+	ret = aux->node;
  90
+	free(aux); free(stack);
  91
+	return ret;
  92
+}
  93
+
  94
+#ifdef KNHX_MAIN
  95
+int main(int argc, char *argv[])
  96
+{
  97
+	char *s = "((a[abc],d1)x:0.5,((b[&&NHX:S=MOUSE],h2)[&&NHX:S=HUMAN:B=99][blabla][&&NHX:K=foo],c))";
  98
+	knhx1_t *node;
  99
+	int i, n, error;
  100
+	node = kn_parse(s, &n, &error);
  101
+	for (i = 0; i < n; ++i) {
  102
+		knhx1_t *p = node + i;
  103
+		printf("%s[%d]: %d,%d,%lg\n", p->name, i, p->parent, p->n, p->d);
  104
+	}
  105
+	return 0;
  106
+}
  107
+#endif
16  knhx.h
... ...
@@ -0,0 +1,16 @@
  1
+#ifndef KNHX_H_
  2
+#define KNHX_H_
  3
+
  4
+#define KNERR_MISSING_LEFT   0x01
  5
+#define KNERR_MISSING_RGHT   0x02
  6
+#define KNERR_BRACKET        0x04
  7
+#define KNERR_COLON          0x08
  8
+
  9
+typedef struct {
  10
+	int parent, n;
  11
+	int *child;
  12
+	char *name;
  13
+	double d;
  14
+} knhx1_t;
  15
+
  16
+#endif

0 notes on commit ebfff49

Please sign in to comment.
Something went wrong with that request. Please try again.