commit a50aacd30adb87698eb775ef5c7615c65e57a11d
parent 008b5f74235a7fd04852e6f640429269f1ec4845
Author: Louis Burda <quent.burda@gmail.com>
Date: Thu, 29 Apr 2021 17:54:54 +0200
very basic binary file parsing and skeleton for state-machine based parsing of ascii format
Diffstat:
5 files changed, 235 insertions(+), 93 deletions(-)
diff --git a/service/src/printdoc.c b/service/src/printdoc.c
@@ -5,19 +5,14 @@
#include <dirent.h>
#include "stlfile.h"
-
-#define ARRSIZE(x) (sizeof(x)/sizeof((x)[0]))
-#define MIN(x,y) ((x) > (y) ? (y) : (x))
+#include "util.h"
struct command {
const char *name;
void (*func)(char *);
};
-void* checkp(void *p);
const char* ask(const char *fmtstr, ...);
-void* die(const char *fmtstr, ...);
-char* aprintf(const char *fmtstr, ...);
void dump(const char *filepath);
void search_cmd(char *arg);
@@ -32,16 +27,9 @@ struct command commands[] = {
{ "search", search_cmd }
};
-struct parseinfo *lastrun = NULL;
+struct parseinfo lastrun;
const char *resultdir;
-void*
-checkp(void *p)
-{
- if (!p) die("pointer assertion failed, OOM?\n");
- return p;
-}
-
const char*
ask(const char *fmtstr, ...)
{
@@ -60,69 +48,6 @@ ask(const char *fmtstr, ...)
return fail ? "" : linebuf;
}
-void*
-die(const char *fmtstr, ...)
-{
- va_list ap;
-
- va_start(ap, fmtstr);
- vfprintf(stderr, fmtstr, ap);
- va_end(ap);
-
- exit(EXIT_FAILURE);
-}
-
-char*
-aprintf(const char *fmtstr, ...)
-{
- va_list ap, cpy;
- size_t nb;
- char *str;
-
- va_copy(cpy, ap);
-
- va_start(cpy, fmtstr);
- nb = vsnprintf(NULL, 0, fmtstr, ap);
- va_end(cpy);
-
- if (nb <= 0) die("encountered invalid fmtstr!\n");
-
- str = checkp(malloc(nb));
- va_start(ap, fmtstr);
- nb = vsnprintf(str, nb, fmtstr, ap);
- va_end(ap);
-
- return str;
-}
-
-char*
-strhash(const char *filename)
-{
- static const char *hexalph = "0123456789ABCDEF";
- char *buf;
- int i, k;
-
- buf = checkp(malloc(33));
- for (i = 0; i < MIN(32, strlen(filename)); i++) {
- unsigned char v = 0;
- for (k = i; k < strlen(filename); k += 32)
- v ^= filename[k];
- buf[i*2+0] = hexalph[(v >> 0) & 0x0f];
- buf[i*2+1] = hexalph[(v >> 4) & 0x0f];
- }
-
- if (i == 0) {
- memset(buf, '0', 32);
- } else if (i < 32) {
- for (k = 0; k < 32; k++)
- buf[k] = buf[k % i];
- }
-
- buf[32] = '\0';
-
- return buf;
-}
-
void
dump(const char *filename)
{
@@ -142,15 +67,15 @@ void
search_cmd(char *arg)
{
char *end, *resultfile = NULL;
- char *hash;
+ const char *hash;
struct dirent *de;
int i, which;
DIR *d = NULL;
- if (!lastrun)
- hash = strhash(ask("What is the model name?\n"));
+ if (lastrun.valid)
+ hash = lastrun.namehash;
else
- hash = checkp(strdup(lastrun->namehash));
+ hash = mhash(ask("What is the model name?\n"), -1);
d = opendir("scans");
if (!d) return;
@@ -207,13 +132,13 @@ submit_cmd(char *arg)
}
printf("Ok! Im listening..\n");
- contents = checkp(malloc(len));
+ contents = checkp(malloc(len + 1));
fread(contents, 1, len, stdin);
+ contents[len] = '\0';
- if (lastrun) free_parseinfo(lastrun);
- lastrun = parse_file(contents, len);
+ lastrun.valid = parse_file(&lastrun, contents, len);
- dump(lastrun->infopath);
+ if (lastrun.valid) dump(lastrun.infopath);
free(contents);
}
diff --git a/service/src/stlfile.c b/service/src/stlfile.c
@@ -1,16 +1,117 @@
#include "stlfile.h"
+#include "util.h"
+void
+stack_init(struct stack *stack)
+{
+ stack->cap = 10;
+ stack->data = checkp(malloc(sizeof(int) * stack->cap));
+ stack->count = 0;
+}
-struct parseinfo*
-parse_file(char *buf, size_t len)
+void
+stack_push(struct stack *stack, int v)
{
+ if (stack->count == stack->cap) {
+ stack->cap *= 2;
+ stack->data = checkp(realloc(stack->data, sizeof(int) * stack->cap));
+ }
- return NULL;
+ stack->data[stack->count] = v;
+ stack->count++;
}
+int
+stack_pop(struct stack *stack)
+{
+ if (stack->count == 0)
+ die("popping empty stack!\n");
+
+ stack->count--;
+ return stack->data[stack->count];
+}
void
-free_parseinfo(struct parseinfo *info)
+stack_free(struct stack *stack)
+{
+ free(stack->data);
+}
+
+int
+consume_keyword(char **bp, char *end)
+{
+ /* TODO */
+ return KW_SOLID_BEGIN;
+}
+
+int
+parse_file_ascii(struct parseinfo *info, char *buf, size_t len)
{
+ char *bp, *pbp, *end = buf + len;
+ struct stack states;
+ int type, kw;
+
+ stack_init(&states);
+
+ info = checkp(malloc(sizeof(struct parseinfo)));
+ info->type = TYPE_ASCII;
+
+ while ((kw = consume_keyword(&bp, end))) {
+ /* TODO */
+ }
+
+ stack_free(&states);
+ return OK;
+
+fail:
+ stack_free(&states);
free(info);
+ return FAIL;
+}
+
+int
+parse_file_bin(struct parseinfo *info, char *buf, size_t len)
+{
+ char *bp, *end = buf + len;
+ unsigned int i;
+
+ if (len < 84) {
+ fprintf(stderr, "Truncated data! (header missing)\n");
+ return FAIL;
+ }
+
+ /* treat header as model name */
+ info->namehash = strdup(mhash(buf, 80));
+
+ bp = buf + 80;
+ info->loopcount = le32toh(*(uint32_t*)bp);
+
+ for (i = 0; i < info->loopcount; i++) {
+ if (bp + 50 > end) {
+ fprintf(stderr, "Truncated data! (loops missing)\n");
+ return FAIL;
+ }
+ bp += 50;
+ }
+
+ return OK;
+}
+
+int
+parse_file(struct parseinfo *info, char *buf, size_t len)
+{
+ char *bp;
+
+ if (info->valid) {
+ NULLFREE(info->infopath);
+ NULLFREE(info->namehash);
+ NULLFREE(info->stlpath);
+ }
+
+ /* check bin vs ascii */
+ for (bp = buf; strchr(" \n\r\t", *bp); bp++);
+
+ return !strncmp("solid ", bp, 6)
+ ? parse_file_ascii(info, buf, len)
+ : parse_file_bin(info, buf, len);
}
diff --git a/service/src/stlfile.h b/service/src/stlfile.h
@@ -3,14 +3,36 @@
#include <stdlib.h>
#include <string.h>
+#include <stdint.h>
+#include <endian.h>
+
+enum {
+ KW_SOLID_BEGIN,
+ KW_SOLID_END,
+ KW_FACET,
+ KW_OUTER,
+ KW_VERTEX
+};
+
+enum {
+ TYPE_ASCII,
+ TYPE_BIN
+};
+
+struct stack {
+ int *data;
+ size_t count, cap;
+};
struct parseinfo {
char fmtbuf[256];
- int attrs;
+ char header[80];
+ int type, valid;
+ unsigned int loopcount;
+ float bbw, bbh;
char *namehash, *infopath, *stlpath;
};
-struct parseinfo* parse_file(char *buf, size_t len);
-void free_parseinfo(struct parseinfo *info);
+int parse_file(struct parseinfo *info, char *buf, size_t len);
-#endif // STLFILE_H
+#endif /* STLFILE_H */
diff --git a/service/src/util.c b/service/src/util.c
@@ -0,0 +1,74 @@
+#include "util.h"
+
+void*
+checkp(void *p)
+{
+ if (!p) die("pointer assertion failed, OOM?\n");
+ return p;
+}
+
+void*
+die(const char *fmtstr, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmtstr);
+ vfprintf(stderr, fmtstr, ap);
+ va_end(ap);
+
+ exit(EXIT_FAILURE);
+}
+
+char*
+aprintf(const char *fmtstr, ...)
+{
+ va_list ap, cpy;
+ size_t nb;
+ char *str;
+
+ va_copy(cpy, ap);
+
+ va_start(cpy, fmtstr);
+ nb = vsnprintf(NULL, 0, fmtstr, ap);
+ va_end(cpy);
+
+ if (nb <= 0) die("encountered invalid fmtstr!\n");
+
+ str = checkp(malloc(nb));
+ va_start(ap, fmtstr);
+ nb = vsnprintf(str, nb, fmtstr, ap);
+ va_end(ap);
+
+ return str;
+}
+
+const char*
+mhash(const char *filename, int len)
+{
+ static const char *hexalph = "0123456789ABCDEF";
+ static char buf[33];
+ int i, k;
+
+ if (len == -1) len = strlen(filename);
+
+ for (i = 0; i < MIN(32, len); i++) {
+ unsigned char v = 0;
+ for (k = i; k < len; k += 32)
+ v ^= filename[k];
+ buf[i*2+0] = hexalph[(v >> 0) & 0x0f];
+ buf[i*2+1] = hexalph[(v >> 4) & 0x0f];
+ }
+
+ if (i == 0) {
+ memset(buf, '0', 32);
+ } else if (i < 32) {
+ for (k = 0; k < 32; k++)
+ buf[k] = buf[k % i];
+ }
+
+ buf[32] = '\0';
+
+ return buf;
+}
+
+
diff --git a/service/src/util.h b/service/src/util.h
@@ -0,0 +1,20 @@
+#ifndef UTIL_H
+#define UTIL_H
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+
+#define ARRSIZE(x) (sizeof(x)/sizeof((x)[0]))
+#define MIN(x,y) ((x) > (y) ? (y) : (x))
+#define NULLFREE(p) do { free(p); p = NULL; } while (0)
+
+enum { FAIL = 0, OK = 1 };
+
+void* checkp(void *p);
+void* die(const char *fmtstr, ...);
+char* aprintf(const char *fmtstr, ...);
+const char* mhash(const char *filename, int len);
+
+#endif /* UTIL_H */