commit 752a2f5617d6b6ccf9758a19372b27fadfe6c65d
parent e39cc9652d340623fd4fba9c2f938fd168e8d5be
Author: Renev Pavel <an2qzavok@gmail.com>
Date: Thu, 11 May 2023 23:27:18 +0000
tablist: encoder is operational!
Diffstat:
4 files changed, 192 insertions(+), 47 deletions(-)
diff --git a/src/tablist/example.tl b/src/tablist/example.tl
@@ -1,10 +1,14 @@
-wdbentry
- uuid \5cb897dd-0fcb-4102-204b-5fdede76930c
- name
- \Shinju no Nectar
- \Nectar of Dharani
- \Nectar of Divine Curse
- \神呪のネクタール
- status \ch 31
- tags \setting:fantasy isekai ecchi smut
- type \manga
+a
+aa
+ b
+ c
+ d
+ cc dd
+name
+ \Shinju no Nectar
+ \Nectar of Dharani
+ \Nectar of Divine Curse
+ \神呪のネクタール
+status \ch 31
+tags \setting:fantasy isekai ecchi smut
+type \manga
diff --git a/src/tablist/tablist.c b/src/tablist/tablist.c
@@ -129,3 +129,144 @@ _tlparse(char *data, usize count)
}
return pc.root;
}
+
+TLdecoder *
+initTLdecoder(char *file)
+{
+ TLdecoder *tlp;
+ tlp = mallocz(sizeof(TLdecoder), 1);
+ tlp->file = file;
+ // tlp->root = allocTLnode(strdup("root"), nil);
+ return tlp;
+}
+
+int
+TLdecode(TLdecoder *tlp, char *buf, usize count)
+{
+ tlp->root = _tlparse(buf, count);
+ return 0;
+}
+
+TLencoder *
+initTLencoder(TLnode *root)
+{
+ TLencoder *w = mallocz(sizeof(TLencoder), 1);
+ w->root = root;
+ w->np = root;
+ w->ns[0] = root;
+ w->n = 0;
+ return w;
+}
+
+int
+TLencode(TLencoder *w, char *buf, usize count)
+{
+ enum {
+ Start = 0,
+ Node, Next, Space, Newline, Escape,
+ Indent, Name, Value, Select, End,
+ };
+
+ usize i;
+ int j;
+ char c;
+
+ for (i = 0; i < count;) {
+ switch (w->state) {
+
+ case Start:
+ case Node:
+ w->np = w->ns[w->n];
+ if (w->nl != 0) {
+ w->state = Indent;
+ break;
+ }
+ else w->state = Select;
+
+ case Select:
+ w->i = 0;
+ if (w->np->name != nil) {
+ w->state = Name;
+ }
+ else if (w->np->value != nil) {
+ w->state = Escape;
+ }
+ else w->state = Next;
+ break;
+
+ case Next:
+ if (w->cs[w->n] < w->np->count) {
+ assert(w->np->children != nil);
+ w->ns[w->n + 1] = w->np->children[w->cs[w->n]];
+ w->cs[w->n + 1] = 0;
+ w->n++;
+ } else {
+ w->n--;
+ if (w->n < 0) {
+ w->state = End;
+ break;
+ }
+ w->np = w->ns[w->n];
+ w->cs[w->n]++;
+ w->state = Next;
+ break;
+ }
+ w->state = Node;
+ break;
+
+ case Name:
+ c = w->np->name[w->i++];
+ if (c != '\0') {
+ buf[i++] = c;
+ }
+ else {
+ if (w->np->count == 1) w->state = Space;
+ else w->state = Newline;
+ }
+ break;
+
+ case Value:
+ c = w->np->value[w->i++];
+ if (c != '\0') {
+ buf[i++] = c;
+ }
+ else w->state = Newline;
+ break;
+
+ case Space:
+ buf[i++] = ' ';
+ w->state = Next;
+ break;
+
+ case Newline:
+ buf[i++] = '\n';
+ w->i = 0;
+ w->nl = 1;
+ w->indent = 0;
+ w->state = Next;
+ break;
+
+ case Escape:
+ buf[i++] = '\\';
+ w->state = Value;
+ break;
+
+ case Indent:
+ if (w->i++ < w->n - 1) {
+ if (w->ns[w->i]->count >1) buf[i++] = '\t';
+ }
+ else {
+ w->state = Select;
+ w->nl = 0;
+ }
+ break;
+
+ case End:
+ return i;
+
+ default:
+ sysfatal("TLencode: unknown state %d", w->state);
+ }
+ }
+ return i;
+}
diff --git a/src/tablist/tablist.h b/src/tablist/tablist.h
@@ -1,4 +1,10 @@
#pragma lib "../tablist/libtablist.a$O"
+
+enum {
+ TLstackdepth = 256,
+ TLbufsize = 1024,
+};
+
typedef struct TLnode TLnode;
struct TLnode {
char *name;
@@ -7,18 +13,25 @@ struct TLnode {
int count;
};
-typedef struct TLparser TLparser;
-struct TLparserr {
- char *file;
+typedef struct TLdecoder TLdecoder;
+struct TLdecoder {
+ char *file, *buf;
+ TLnode *root, *stack[TLstackdepth];
int sp, row, col;
- TLnode *root, *stack[64];
};
-TLparesr * initTLparser(char *);
-int TLparse(TLparser *, void *, size);
+typedef struct TLencoder TLencoder;
+struct TLencoder {
+ TLnode *root, *np, *ns[TLstackdepth];
+ int state, i, nl, indent, n, cs[TLstackdepth];
+};
TLnode * allocTLnode(char *, char *);
int freeTLnode(TLnode *);
int TLnodeappend(TLnode *, TLnode *);
-TLnode * _tlparse(char *, usize);
+TLdecoder * initTLdecoder(char *);
+int TLdecode(TLdecoder *, char *, usize);
+
+TLencoder * initTLencoder(TLnode *);
+int TLencode(TLencoder *, char *, usize);
diff --git a/src/tablist/test.c b/src/tablist/test.c
@@ -2,40 +2,25 @@
#include <libc.h>
#include "tablist.h"
-void tlprint(int, TLnode *);
-
-void
-tlprint(int indent, TLnode *node)
-{
- int i;
- for (i = 0; i < indent; i++) print("\t");
-
- if (node->name) print("%s", node->name);
- else if (node->value) {
- print("\\%s", node->value);
- }
- else print("\\");
-
- print("\n");
-
- for (i = 0; i < node->count; i++) {
- tlprint(indent + 1, node->children[i]);
- }
-}
-
void
test(char *path)
{
- TLnode *root;
- int n, fd;
- char buf[4096];
- fd = open(path, OREAD);
+ fprint(2, "%s...\n", path);
+ char *buf = malloc(4096);
+ int fd = open(path, OREAD);
if (fd < 0) sysfatal("%r");
- n = readn(fd, buf, 4096);
- root = _tlparse(buf, n);
- if (root == nil) sysfatal("%r");
- tlprint(0, root);
- exits(nil);
+ usize n = read(fd, buf, 4096);
+ print("READ %d bytes\n", n);
+ write(1, buf, n);
+ TLdecoder *tld = initTLdecoder(path);
+ TLdecode(tld, buf, n);
+
+ TLencoder *tle = initTLencoder(tld->root);
+ print("WRITE\n");
+ while (n > 0) {
+ n = TLencode(tle, buf, 4096);
+ write(1, buf, n);
+ }
}
void
@@ -43,4 +28,6 @@ main(int argc, char **argv)
{
int i;
for (i = 1; i < argc; i++) test(argv[i]);
+ fprint(2, "OVER\n");
+ exits(nil);
}