ref: 222bf07cdb99049713271bba455e07e5e4e55e71
dir: /stl.c/
#include <u.h> #include <libc.h> #include <bio.h> #include "stl.h" static int bunpack(Biobuf*, char*, ...); static int Bgets(Biobuf *b, u16int *s) { uchar buf[2]; if(Bread(b, buf, 2) != 2){ werrstr("could not get 2 bytes"); return -1; } *s = buf[0] | buf[1] << 8; return 0; } static int Bgetl(Biobuf *b, u32int *l) { uchar buf[4]; if(Bread(b, buf, 4) != 4){ werrstr("could not get 4 bytes"); return -1; } *l = buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24; return 0; } static int Bgetf(Biobuf *b, float *f) { u32int l; if(Bgetl(b, &l) < 0){ werrstr("Bgetl: %r"); return -1; } *f = *(float*)&l; return 0; } static int vbunpack(Biobuf *b, char *fmt, va_list a) { u16int s; u32int l; float f, *v; void *p; for(;;){ switch(*fmt++){ case '\0': return 0; case 's': if(Bgets(b, &s) < 0) goto error; *va_arg(a, ushort*) = s; break; case 'l': if(Bgetl(b, &l) < 0) goto error; *va_arg(a, ulong*) = l; break; case 'f': if(Bgetf(b, &f) < 0) goto error; *va_arg(a, float*) = f; break; case 'v': v = va_arg(a, float*); if(bunpack(b, "fff", v+0, v+1, v+2) < 0) goto error; break; case '[': p = va_arg(a, void*); s = va_arg(a, ushort); if(Bread(b, p, s) != s){ werrstr("Bread: could not read %ud bytes", s); goto error; } break; } } error: return -1; } static int bunpack(Biobuf *b, char *fmt, ...) { va_list a; int n; va_start(a, fmt); n = vbunpack(b, fmt, a); va_end(a); return n; } Stl * readstl(int fd) { Biobuf *bin; Stltri *tri; Stl *stl; u32int i, ntris; bin = Bfdopen(fd, OREAD); if(bin == nil){ werrstr("Bfdopen: %r"); return nil; } stl = mallocz(sizeof(Stl), 1); if(stl == nil){ werrstr("mallocz0: %r"); goto error; } if(bunpack(bin, "[l", stl->hdr, sizeof(stl->hdr), &ntris) < 0){ werrstr("hdr bunpack: %r"); goto error; } for(i = 0; i < ntris; i++){ tri = mallocz(sizeof(Stltri), 1); if(tri == nil){ werrstr("mallocz1: %r"); goto error; } if(bunpack(bin, "vvvvs", tri->n, tri->p0, tri->p1, tri->p2, &tri->attrlen) < 0){ free(tri); werrstr("tri bunpack0: %r"); goto error; } tri = realloc(tri, sizeof(Stltri) + tri->attrlen); if(tri == nil){ werrstr("realloc0: %r"); goto error; } if(bunpack(bin, "[", tri->attrs, tri->attrlen) < 0){ free(tri); werrstr("tri bunpack1: %r"); goto error; } stl->tris = realloc(stl->tris, (stl->ntris+1)*sizeof(*stl->tris)); if(stl->tris == nil){ free(tri); werrstr("realloc1: %r"); goto error; } stl->tris[stl->ntris++] = tri; } Bterm(bin); return stl; error: Bterm(bin); freestl(stl); return nil; } void freestl(Stl *stl) { int i; if(stl == nil) return; for(i = 0; i < stl->ntris; i++) free(stl->tris[i]); free(stl->tris); free(stl); }