diff --git a/knhx.c b/knhx.c index fd35a3f9..8dbd3b6e 100644 --- a/knhx.c +++ b/knhx.c @@ -91,17 +91,76 @@ knhx1_t *kn_parse(const char *nhx, int *_n, int *_error) return ret; } +#ifndef kroundup32 +#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) +#endif + +static inline int kputsn(const char *p, int l, kstring_t *s) +{ + if (s->l + l + 1 >= s->m) { + s->m = s->l + l + 2; + kroundup32(s->m); + s->s = (char*)realloc(s->s, s->m); + } + memcpy(s->s + s->l, p, l); + s->l += l; s->s[s->l] = 0; + return l; +} + +static inline int kputc(int c, kstring_t *s) +{ + if (s->l + 1 >= s->m) { + s->m = s->l + 2; + kroundup32(s->m); + s->s = (char*)realloc(s->s, s->m); + } + s->s[s->l++] = c; s->s[s->l] = 0; + return c; +} + +static void format_node_recur(const knhx1_t *node, const knhx1_t *p, kstring_t *s, char *numbuf) +{ + if (p->n) { + int i; + kputc('(', s); + for (i = 0; i < p->n; ++i) { + if (i) kputc(',', s); + format_node_recur(node, &node[p->child[i]], s, numbuf); + } + kputc(')', s); + if (p->name) kputsn(p->name, strlen(p->name), s); + if (p->d >= 0) { + sprintf(numbuf, ":%g", p->d); + kputsn(numbuf, strlen(numbuf), s); + } + } else kputsn(p->name, strlen(p->name), s); +} + +void kn_format(const knhx1_t *node, int root, kstring_t *s) // TODO: get rid of recursion +{ + char numbuf[128]; + format_node_recur(node, &node[root], s, numbuf); +} + #ifdef KNHX_MAIN int main(int argc, char *argv[]) { char *s = "((a[abc],d1)x:0.5,((b[&&NHX:S=MOUSE],h2)[&&NHX:S=HUMAN:B=99][blabla][&&NHX:K=foo],c))"; knhx1_t *node; - int i, n, error; + int i, j, n, error; + kstring_t str; node = kn_parse(s, &n, &error); for (i = 0; i < n; ++i) { knhx1_t *p = node + i; - printf("%s[%d]: %d,%d,%lg\n", p->name, i, p->parent, p->n, p->d); + printf("[%d] %s\t%d\t%d\t%g", i, p->name, p->parent, p->n, p->d); + for (j = 0; j < p->n; ++j) + printf("\t%d", p->child[j]); + putchar('\n'); } + str.l = str.m = 0; str.s = 0; + kn_format(node, n-1, &str); + puts(str.s); + free(str.s); return 0; } #endif diff --git a/knhx.h b/knhx.h index 3bb0f375..dbad7dd9 100644 --- a/knhx.h +++ b/knhx.h @@ -13,4 +13,23 @@ typedef struct { double d; } knhx1_t; +#ifndef KSTRING_T +#define KSTRING_T kstring_t +typedef struct __kstring_t { + size_t l, m; + char *s; +} kstring_t; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + knhx1_t *kn_parse(const char *nhx, int *_n, int *_error); + void kn_format(const knhx1_t *node, int root, kstring_t *s); + +#ifdef __cplusplus +} +#endif + #endif