#include #include #include #include #include "article.h" Post* newpost(void) { Post* p; p = malloc(sizeof(Post)); memset(p, 0, sizeof(p)); return p; } void closepost(Post* p) { if (p == nil) return; free(p->title); free(p->author); free(p->body); free(p); } int prefixcmp(int top[], int p[], int n) { int i; for (i = 0; i < Nids && i < n; i++) if (top[i] != p[i]) return 1; return 0; } char* id2str(int ids[], int n) { char buf[100]; char* s; int i; s = buf; for (i = 0; i < n; i++) if (i == 0) s = seprint(s, buf+sizeof(buf), "%d", ids[i]); else s = seprint(s, buf+sizeof(buf), ".%d", ids[i]); return strdup(buf); } int parseid(char* buf, int ids[], int max) { char* toks[Nids+1]; int i; int n; n = getfields(buf, toks, nelem(toks), 0, "."); if (n > Nids || n > max) n = 0; for (i = 0; i < n; i++) ids[i] = atoi(toks[i]); return n; } int isson(Post* t, Post* p) { if (t != nil && p != nil && t->nids == p->nids - 1) if (!prefixcmp(t->ids, p->ids, t->nids)) return 1; return 0; } char* seprintpost(char* s, char* e, Post* p) { char* is; is = id2str(p->ids, p->nids); s = seprint(s, e, "%s", is); free(is); s = seprint(s, e, "\n%s\n", p->title); s = seprint(s, e, "%s\n", p->author); return seprint(s, e, "%s%c", p->body, Eop); } Post* readpost(Biobuf* b) { Post* p; char* ln; ln = Brdstr(b, '\n', 1); if (ln == nil) return nil; p = malloc(sizeof(Post)); memset(p, 0, sizeof(Post)); p->nids = parseid(ln, p->ids, Nids); free(ln); p->title = Brdstr(b, '\n', 1); p->author= Brdstr(b, '\n', 1); p->body = Brdstr(b, Eop, 1); if (p->nids == 0 || !p->title || !p->author || !p->body){ fprint(2, "null post member\n"); closepost(p); return nil; } else return p; } /* * Top ids[] is a prefix of p ids[] * we descend evaluating more into the prefix * until we have a single element to evaluate */ void insert(Post* top, Post* p) { int i; Post* s; Post* nxt; while(!isson(top, p)){ nxt = nil; for (i = 0; i < top->nsons; i++){ s = top->sons[i]; if (s != nil) if (!prefixcmp(s->ids, p->ids, s->nids)){ nxt = s; break; } } if (nxt == nil){ fprint(2, "warning: parent %s\n", top->title); fprint(2, "warning: son w/o parent %s\n", p->title); return; } top = nxt; } if (top->nsons == Nsons){ fprint(2, "warning: Nsons reached\n"); return; } top->sons[top->nsons++] = p; } Post* lookup(Post* p, int ids[], int nids) { int i; Post* s; Post* nxt; while(p != nil && !(p->nids == nids && !prefixcmp(p->ids, ids, nids))){ nxt = nil; for (i = 0; i < p->nsons; i++){ s = p->sons[i]; if (s != nil) if (!prefixcmp(s->ids, ids, s->nids)){ nxt = s; break; } } p = nxt; } return p; } Post* readarticle(Biobuf* bin, int* n) { Post* top; Post* p; if (n != nil) *n = 0; top = readpost(bin); while(top != nil){ if (n != nil) *n = *n + 1; p = readpost(bin); if (p == nil) break; insert(top, p); } return top; }