]> git.kaiwu.me - klib.git/commitdiff
print tree in the Newick format
authorHeng Li <lh3@me.com>
Wed, 19 Dec 2012 01:18:20 +0000 (20:18 -0500)
committerHeng Li <lh3@me.com>
Wed, 19 Dec 2012 01:18:20 +0000 (20:18 -0500)
knhx.c
knhx.h

diff --git a/knhx.c b/knhx.c
index fd35a3f9e14e9895a644bbea9b851d1e3e1b506c..8dbd3b6e35b4f47703dfc248a3fbf3ae45252818 100644 (file)
--- 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 3bb0f3752de0b32d62025123f16707459ab476b9..dbad7dd9443c91a1093b0311adef752792287d2f 100644 (file)
--- 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