enowars5-service-stldoctor

STL-Analyzing A/D Service for ENOWARS5 in 2021
git clone https://git.sinitax.com/sinitax/enowars5-service-stldoctor
Log | Files | Refs | README | LICENSE | sfeed.txt

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:
Mservice/src/printdoc.c | 95+++++++++----------------------------------------------------------------------
Mservice/src/stlfile.c | 109++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Mservice/src/stlfile.h | 30++++++++++++++++++++++++++----
Aservice/src/util.c | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aservice/src/util.h | 20++++++++++++++++++++
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 */