diff options
Diffstat (limited to 'object')
-rw-r--r-- | object/array.c | 182 | ||||
-rw-r--r-- | object/dict.c | 260 | ||||
-rw-r--r-- | object/parse.c | 400 | ||||
-rw-r--r-- | object/print.c | 332 | ||||
-rw-r--r-- | object/simple.c | 230 |
5 files changed, 1404 insertions, 0 deletions
diff --git a/object/array.c b/object/array.c new file mode 100644 index 00000000..d7beeb38 --- /dev/null +++ b/object/array.c @@ -0,0 +1,182 @@ +#include <fitz.h> + +fz_error * +fz_newarray(fz_obj **op, int initialcap) +{ + fz_obj *obj; + int i; + + obj = *op = fz_malloc(sizeof (fz_obj)); + if (!obj) return fz_outofmem; + + obj->kind = FZ_ARRAY; + obj->refcount = 1; + + obj->u.a.len = 0; + obj->u.a.cap = initialcap > 0 ? initialcap : 6; + + obj->u.a.items = fz_malloc(sizeof (fz_obj*) * obj->u.a.cap); + if (!obj->u.a.items) { fz_free(obj); return fz_outofmem; } + + for (i = 0; i < obj->u.a.cap; i++) + obj->u.a.items[i] = nil; + + return nil; +} + +fz_error * +fz_copyarray(fz_obj **op, fz_obj *obj) +{ + fz_error *err; + fz_obj *new; + int i; + + if (!fz_isarray(obj)) + return fz_throw("typecheck in copyarray"); + + err = fz_newarray(&new, fz_arraylen(obj)); + if (err) return err; + *op = new; + + for (i = 0; i < fz_arraylen(obj); i++) { + err = fz_arraypush(new, fz_arrayget(obj, i)); + if (err) { fz_freearray(new); return err; } + } + + return nil; +} + +fz_error * +fz_deepcopyarray(fz_obj **op, fz_obj *obj) +{ + fz_error *err; + fz_obj *new; + fz_obj *val; + int i; + + if (!fz_isarray(obj)) + return fz_throw("typecheck in deepcopyarray"); + + err = fz_newarray(&new, fz_arraylen(obj)); + if (err) return err; + *op = new; + + for (i = 0; i < fz_arraylen(obj); i++) + { + val = fz_arrayget(obj, i); + + if (fz_isarray(val)) { + err = fz_deepcopyarray(&val, val); + if (err) { fz_freearray(new); return err; } + err = fz_arraypush(new, val); + if (err) { fz_dropobj(val); fz_freearray(new); return err; } + fz_dropobj(val); + } + + else if (fz_isdict(val)) { + err = fz_deepcopydict(&val, val); + if (err) { fz_freearray(new); return err; } + err = fz_arraypush(new, val); + if (err) { fz_dropobj(val); fz_freearray(new); return err; } + fz_dropobj(val); + } + + else { + err = fz_arraypush(new, val); + if (err) { fz_freearray(new); return err; } + } + } + + return nil; +} + +int +fz_arraylen(fz_obj *obj) +{ + if (!fz_isarray(obj)) + return 0; + return obj->u.a.len; +} + +fz_obj * +fz_arrayget(fz_obj *obj, int i) +{ + if (!fz_isarray(obj)) + return nil; + + if (i < 0 || i >= obj->u.a.len) + return nil; + + return obj->u.a.items[i]; +} + +fz_error * +fz_arrayput(fz_obj *obj, int i, fz_obj *item) +{ + if (!fz_isarray(obj)) + return fz_throw("typecheck in arrayput"); + if (i < 0) + return fz_throw("rangecheck in arrayput: %d < 0", i); + if (i >= obj->u.a.len) + return fz_throw("rangecheck in arrayput: %d > %d", i, obj->u.a.len); + + if (obj->u.a.items[i]) + fz_dropobj(obj->u.a.items[i]); + obj->u.a.items[i] = fz_keepobj(item); + + return nil; +} + +static fz_error * +growarray(fz_obj *obj) +{ + fz_obj **newitems; + int newcap; + int i; + + newcap = obj->u.a.cap * 2; + newitems = fz_realloc(obj->u.a.items, sizeof (fz_obj*) * newcap); + if (!newitems) return fz_outofmem; + + obj->u.a.items = newitems; + for (i = obj->u.a.cap ; i < newcap; i++) + obj->u.a.items[i] = nil; + obj->u.a.cap = newcap; + + return nil; +} + +fz_error * +fz_arraypush(fz_obj *obj, fz_obj *item) +{ + fz_error *err; + + if (!fz_isarray(obj)) + return fz_throw("typecheck in arraypush"); + + if (obj->u.a.len + 1 > obj->u.a.cap) { + err = growarray(obj); + if (err) return err; + } + + obj->u.a.items[obj->u.a.len] = fz_keepobj(item); + obj->u.a.len++; + + return nil; +} + +void +fz_freearray(fz_obj *obj) +{ + int i; + + assert(obj->kind == FZ_ARRAY); + + for (i = 0; i < obj->u.a.len; i++) + if (obj->u.a.items[i]) + fz_dropobj(obj->u.a.items[i]); + + fz_free(obj->u.a.items); + fz_free(obj); +} + diff --git a/object/dict.c b/object/dict.c new file mode 100644 index 00000000..fd2f3382 --- /dev/null +++ b/object/dict.c @@ -0,0 +1,260 @@ +#include <fitz.h> + +fz_error * +fz_newdict(fz_obj **op, int initialcap) +{ + fz_obj *obj; + int i; + + obj = *op = fz_malloc(sizeof (fz_obj)); + if (!obj) return fz_outofmem; + + obj->kind = FZ_DICT; + obj->refcount = 1; + + obj->u.d.len = 0; + obj->u.d.cap = initialcap > 0 ? initialcap : 10; + + obj->u.d.items = fz_malloc(sizeof(struct fz_keyval_s) * obj->u.d.cap); + if (!obj->u.d.items) { fz_free(obj); return fz_outofmem; } + + for (i = 0; i < obj->u.d.cap; i++) { + obj->u.d.items[i].k = nil; + obj->u.d.items[i].v = nil; + } + + return nil; +} + +fz_error * +fz_copydict(fz_obj **op, fz_obj *obj) +{ + fz_error *err; + fz_obj *new; + int i; + + if (!fz_isdict(obj)) + return fz_throw("typecheck in copydict"); + + err = fz_newdict(&new, obj->u.d.cap); + if (err) return err; + *op = new; + + for (i = 0; i < fz_dictlen(obj); i++) { + err = fz_dictput(new, fz_dictgetkey(obj, i), fz_dictgetval(obj, i)); + if (err) { fz_freedict(new); return err; } + } + + return nil; +} + +fz_error * +fz_deepcopydict(fz_obj **op, fz_obj *obj) +{ + fz_error *err; + fz_obj *new; + fz_obj *val; + int i; + + if (!fz_isdict(obj)) + return fz_throw("typecheck in deepcopydict"); + + err = fz_newdict(&new, obj->u.d.cap); + if (err) return err; + *op = new; + + for (i = 0; i < fz_dictlen(obj); i++) + { + val = fz_dictgetval(obj, i); + + if (fz_isarray(val)) { + err = fz_deepcopyarray(&val, val); + if (err) { fz_freedict(new); return err; } + err = fz_dictput(new, fz_dictgetkey(obj, i), val); + if (err) { fz_dropobj(val); fz_freedict(new); return err; } + fz_dropobj(val); + } + + else if (fz_isdict(val)) { + err = fz_deepcopydict(&val, val); + if (err) { fz_freedict(new); return err; } + err = fz_dictput(new, fz_dictgetkey(obj, i), val); + if (err) { fz_dropobj(val); fz_freedict(new); return err; } + fz_dropobj(val); + } + + else { + err = fz_dictput(new, fz_dictgetkey(obj, i), val); + if (err) { fz_freedict(new); return err; } + } + } + + return nil; +} + +static fz_error * +growdict(fz_obj *obj) +{ + struct fz_keyval_s *newitems; + int newcap; + int i; + + newcap = obj->u.d.cap * 2; + + newitems = fz_realloc(obj->u.d.items, sizeof(struct fz_keyval_s) * newcap); + if (!newitems) return fz_outofmem; + + obj->u.d.items = newitems; + for (i = obj->u.d.cap; i < newcap; i++) { + obj->u.d.items[i].k = nil; + obj->u.d.items[i].v = nil; + } + obj->u.d.cap = newcap; + + return nil; +} + +int +fz_dictlen(fz_obj *obj) +{ + if (!fz_isdict(obj)) + return 0; + return obj->u.d.len; +} + +fz_obj * +fz_dictgetkey(fz_obj *obj, int i) +{ + if (!fz_isdict(obj)) + return nil; + + if (i < 0 || i >= obj->u.d.len) + return nil; + + return obj->u.d.items[i].k; +} + +fz_obj * +fz_dictgetval(fz_obj *obj, int i) +{ + if (!fz_isdict(obj)) + return nil; + + if (i < 0 || i >= obj->u.d.len) + return nil; + + return obj->u.d.items[i].v; +} + +fz_obj * +fz_dictgets(fz_obj *obj, char *key) +{ + int i; + + if (!fz_isdict(obj)) + return nil; + + for (i = 0; i < obj->u.d.len; i++) + if (strcmp(fz_toname(obj->u.d.items[i].k), key) == 0) + return obj->u.d.items[i].v; + + return nil; +} + +fz_obj * +fz_dictget(fz_obj *obj, fz_obj *key) +{ + return fz_dictgets(obj, fz_toname(key)); +} + +fz_error * +fz_dictput(fz_obj *obj, fz_obj *key, fz_obj *val) +{ + fz_error *err; + int i; + char *s; + + if (!fz_isdict(obj)) + return fz_throw("typecheck in dictput"); + if (!fz_isname(key)) + return fz_throw("typecheck in dictput"); + + s = fz_toname(key); + + for (i = 0; i < obj->u.d.len; i++) { + if (strcmp(fz_toname(obj->u.d.items[i].k), s) == 0) { + fz_dropobj(obj->u.d.items[i].v); + obj->u.d.items[i].v = fz_keepobj(val); + return nil; + } + } + + if (obj->u.d.len + 1 > obj->u.d.cap) { + err = growdict(obj); + if (err) return err; + } + + obj->u.d.items[obj->u.d.len].k = fz_keepobj(key); + obj->u.d.items[obj->u.d.len].v = fz_keepobj(val); + obj->u.d.len ++; + + return nil; +} + +fz_error * +fz_dictputs(fz_obj *obj, char *key, fz_obj *val) +{ + fz_error *err; + fz_obj *keyobj; + err = fz_newname(&keyobj, key); + if (err) return err; + err = fz_dictput(obj, keyobj, val); + fz_dropobj(keyobj); + return err; +} + +fz_error * +fz_dictdels(fz_obj *obj, char *key) +{ + int i; + + if (!fz_isdict(obj)) + return fz_throw("typecheck in dictdel"); + + for (i = 0; i < obj->u.d.len; i++) { + if (strcmp(fz_toname(obj->u.d.items[i].k), key) == 0) { + fz_dropobj(obj->u.d.items[i].k); + fz_dropobj(obj->u.d.items[i].v); + obj->u.d.items[i] = obj->u.d.items[obj->u.d.len-1]; + obj->u.d.len --; + } + } + + return nil; +} + +fz_error * +fz_dictdel(fz_obj *obj, fz_obj *key) +{ + return fz_dictdels(obj, fz_toname(key)); +} + +void +fz_freedict(fz_obj *obj) +{ + int i; + + if (!fz_isdict(obj)) + return; + + for (i = 0; i < obj->u.d.len; i++) { + if (obj->u.d.items[i].k) + fz_dropobj(obj->u.d.items[i].k); + if (obj->u.d.items[i].v) + fz_dropobj(obj->u.d.items[i].v); + } + + fz_free(obj->u.d.items); + fz_free(obj); +} + diff --git a/object/parse.c b/object/parse.c new file mode 100644 index 00000000..c065a132 --- /dev/null +++ b/object/parse.c @@ -0,0 +1,400 @@ +#include <fitz.h> + +struct vap { va_list ap; }; + +static inline int iswhite(int ch) +{ + return + ch == '\000' || + ch == '\011' || + ch == '\012' || + ch == '\014' || + ch == '\015' || + ch == '\040'; +} + +static inline int isdelim(int ch) +{ + return + ch == '(' || ch == ')' || + ch == '<' || ch == '>' || + ch == '[' || ch == ']' || + ch == '{' || ch == '}' || + ch == '/' || + ch == '%'; +} + +static inline int isregular(int ch) +{ + return !isdelim(ch) && !iswhite(ch) && ch != EOF; +} + +static fz_error *parseobj(fz_obj **obj, char **sp, struct vap *v); + +static inline int fromhex(char ch) +{ + if (ch >= '0' && ch <= '9') + return ch - '0'; + else if (ch >= 'A' && ch <= 'F') + return ch - 'A' + 0xA; + else if (ch >= 'a' && ch <= 'f') + return ch - 'a' + 0xA; + return 0; +} + +static inline void skipwhite(char **sp) +{ + char *s = *sp; + while (iswhite(*s)) + s ++; + *sp = s; +} + +static void parsekeyword(char **sp, char *b, char *eb) +{ + char *s = *sp; + while (b < eb && isregular(*s)) + *b++ = *s++; + *b++ = 0; + *sp = s; +} + +static fz_error *parsename(fz_obj **obj, char **sp) +{ + char buf[64]; + char *s = *sp; + char *p = buf; + + s ++; /* skip '/' */ + while (p < buf + sizeof buf - 1 && isregular(*s)) + *p++ = *s++; + *p++ = 0; + *sp = s; + + return fz_newname(obj, buf); +} + +static fz_error *parsenumber(fz_obj **obj, char **sp) +{ + char buf[32]; + char *s = *sp; + char *p = buf; + + while (p < buf + sizeof buf - 1) + { + if (s[0] == '-' || s[0] == '.' || (s[0] >= '0' && s[0] <= '9')) + *p++ = *s++; + else + break; + } + *p++ = 0; + *sp = s; + + if (strchr(buf, '.')) + return fz_newreal(obj, atof(buf)); + return fz_newint(obj, atoi(buf)); +} + +static fz_error *parsedict(fz_obj **obj, char **sp, struct vap *v) +{ + fz_error *err = nil; + fz_obj *dict = nil; + fz_obj *key = nil; + fz_obj *val = nil; + char *s = *sp; + + err = fz_newdict(&dict, 8); + if (err) return err; + *obj = dict; + + s += 2; /* skip "<<" */ + + while (*s) + { + skipwhite(&s); + + /* end-of-dict marker >> */ + if (*s == '>') { + s ++; + if (*s == '>') { + s ++; + break; + } + err = fz_throw("syntaxerror in parsedict"); + goto error; + } + + /* non-name as key, bail */ + if (*s != '/') { + err = fz_throw("syntaxerror in parsedict"); + goto error; + } + + err = parsename(&key, &s); + if (err) goto error; + + skipwhite(&s); + + err = parseobj(&val, &s, v); + if (err) goto error; + + err = fz_dictput(dict, key, val); + if (err) goto error; + + fz_dropobj(val); val = nil; + fz_dropobj(key); key = nil; + } + + *sp = s; + return nil; + +error: + if (val) fz_dropobj(val); + if (key) fz_dropobj(key); + if (dict) fz_freedict(dict); + *obj = nil; + *sp = s; + return err; +} + +static fz_error *parsearray(fz_obj **obj, char **sp, struct vap *v) +{ + fz_error *err; + fz_obj *a; + fz_obj *o; + char *s = *sp; + + err = fz_newarray(&a, 8); + if (err) return err; + *obj = a; + + s ++; /* skip '[' */ + + while (*s) + { + skipwhite(&s); + + if (*s == ']') { + s ++; + break; + } + + err = parseobj(&o, &s, v); + if (err) { *obj = nil; fz_freearray(a); return err; } + + err = fz_arraypush(a, o); + if (err) { fz_dropobj(o); *obj = nil; fz_freearray(a); return err; } + + fz_dropobj(o); + } + + *sp = s; + return nil; +} + +static fz_error *parsestring(fz_obj **obj, char **sp) +{ + char buf[512]; + char *s = *sp; + char *p = buf; + int balance = 1; + int oct; + + s ++; /* skip '(' */ + + while (*s && p < buf + sizeof buf) + { + if (*s == '(') + { + balance ++; + *p++ = *s++; + } + else if (*s == ')') + { + balance --; + *p++ = *s++; + } + else if (*s == '\\') + { + s ++; + if (*s >= '0' && *s <= '9') + { + oct = *s - '0'; + s ++; + if (*s >= '0' && *s <= '9') + { + oct = oct * 8 + (*s - '0'); + s ++; + if (*s >= '0' && *s <= '9') + { + oct = oct * 8 + (*s - '0'); + s ++; + } + } + *p++ = oct; + } + else switch (*s) + { + case 'n': *p++ = '\n'; s++; break; + case 'r': *p++ = '\r'; s++; break; + case 't': *p++ = '\t'; s++; break; + case 'b': *p++ = '\b'; s++; break; + case 'f': *p++ = '\f'; s++; break; + default: *p++ = *s++; break; + } + } + else + *p++ = *s++; + + if (balance == 0) + break; + } + + *sp = s; + return fz_newstring(obj, buf, p - buf - 1); +} + +static fz_error *parsehexstring(fz_obj **obj, char **sp) +{ + char buf[512]; + char *s = *sp; + char *p = buf; + int a, b; + + s ++; /* skip '<' */ + + while (*s && p < buf + sizeof buf) + { + skipwhite(&s); + if (*s == '>') { + s ++; + break; + } + a = *s++; + + if (*s == '\0') + break; + + skipwhite(&s); + if (*s == '>') { + s ++; + break; + } + b = *s++; + + *p++ = fromhex(a) * 16 + fromhex(b); + } + + *sp = s; + return fz_newstring(obj, buf, p - buf); +} + +static fz_error *parseobj(fz_obj **obj, char **sp, struct vap *v) +{ + fz_error *err; + char buf[32]; + int oid, gid, len; + char *tmp; + char *s = *sp; + + if (*s == '\0') + return fz_throw("syntaxerror in parseobj: end-of-string"); + + skipwhite(&s); + + err = nil; + + if (v != nil && *s == '%') + { + s ++; + switch (*s) + { + case 'o': *obj = fz_keepobj(va_arg(v->ap, fz_obj*)); break; + case 'b': err = fz_newbool(obj, va_arg(v->ap, int)); break; + case 'i': err = fz_newint(obj, va_arg(v->ap, int)); break; + case 'f': err = fz_newreal(obj, (float)va_arg(v->ap, double)); break; + case 'n': err = fz_newname(obj, va_arg(v->ap, char*)); break; + case 'r': + oid = va_arg(v->ap, int); + gid = va_arg(v->ap, int); + err = fz_newindirect(obj, oid, gid); + break; + case 's': + tmp = va_arg(v->ap, char*); + err = fz_newstring(obj, tmp, strlen(tmp)); + break; + case '#': + tmp = va_arg(v->ap, char*); + len = va_arg(v->ap, int); + err = fz_newstring(obj, tmp, len); + break; + default: + err = fz_throw("unknown format specifier in packobj: '%c'", *s); + break; + } + s ++; + } + + else if (*s == '/') + err = parsename(obj, &s); + + else if (*s == '(') + err = parsestring(obj, &s); + + else if (*s == '<') { + if (s[1] == '<') + err = parsedict(obj, &s, v); + else + err = parsehexstring(obj, &s); + } + + else if (*s == '[') + err = parsearray(obj, &s, v); + + else if (*s == '-' || *s == '.' || (*s >= '0' && *s <= '9')) + err = parsenumber(obj, &s); + + else if (isregular(*s)) + { + parsekeyword(&s, buf, buf + sizeof buf); + + if (strcmp("true", buf) == 0) + err = fz_newbool(obj, 1); + else if (strcmp("false", buf) == 0) + err = fz_newbool(obj, 0); + else if (strcmp("null", buf) == 0) + err = fz_newnull(obj); + else + err = fz_throw("syntaxerror in parseobj: undefined keyword %s", buf); + } + + else + err = fz_throw("syntaxerror in parseobj"); + + *sp = s; + return err; +} + +fz_error * +fz_packobj(fz_obj **op, char *fmt, ...) +{ + fz_error *err; + struct vap v; + va_list ap; + + va_start(ap, fmt); + va_copy(v.ap, ap); + + err = parseobj(op, &fmt, &v); + + va_end(ap); + + return err; +} + +fz_error * +fz_parseobj(fz_obj **op, char *str) +{ + return parseobj(op, &str, nil); +} + diff --git a/object/print.c b/object/print.c new file mode 100644 index 00000000..af6941f9 --- /dev/null +++ b/object/print.c @@ -0,0 +1,332 @@ +#include <fitz.h> + +struct fmt +{ + FILE *file; + char *buf; + int len; + + int indent; + int tight; + int col; + int sep; + int last; +}; + +static void fmtobj(struct fmt *fmt, fz_obj *obj); + +static inline int isdelim(int ch) +{ + return ch == '(' || ch == ')' || + ch == '<' || ch == '>' || + ch == '[' || ch == ']' || + ch == '{' || ch == '}' || + ch == '/' || + ch == '%'; +} + +static inline void fmtputc(struct fmt *fmt, int c) +{ + if (fmt->sep && !isdelim(fmt->last) && !isdelim(c)) { + fmt->sep = 0; + fmtputc(fmt, ' '); + } + fmt->sep = 0; + + if (fmt->file) + putc(c, fmt->file); + if (fmt->buf) + fmt->buf[fmt->len] = c; + + if (c == '\n') + fmt->col = 0; + else + fmt->col ++; + + fmt->len ++; + + fmt->last = c; +} + +static void fmtindent(struct fmt *fmt) +{ + int i = fmt->indent; + while (i--) { + fmtputc(fmt, ' '); + fmtputc(fmt, ' '); + } +} + +static inline void fmtputs(struct fmt *fmt, char *s) +{ + while (*s) + fmtputc(fmt, *s++); +} + +static inline void fmtsep(struct fmt *fmt) +{ + fmt->sep = 1; +} + +static void fmtstr(struct fmt *fmt, fz_obj *obj) +{ + int i; + int c; + + fmtputc(fmt, '('); + for (i = 0; i < obj->u.s.len; i++) + { + c = obj->u.s.buf[i]; + if (c == '\n') + fmtputs(fmt, "\\n"); + else if (c == '\r') + fmtputs(fmt, "\\r"); + else if (c == '\t') + fmtputs(fmt, "\\t"); + else if (c == '\b') + fmtputs(fmt, "\\b"); + else if (c == '\f') + fmtputs(fmt, "\\f"); + else if (c == '(') + fmtputs(fmt, "\\("); + else if (c == ')') + fmtputs(fmt, "\\)"); + else if (c < 32 || c > 126) { + char buf[16]; + fmtputc(fmt, '\\'); + sprintf(buf, "%o", c); + fmtputs(fmt, buf); + //fmtputc(fmt, ((c >> 6) & 7) + '0'); + //fmtputc(fmt, ((c >> 3) & 7) + '0'); + //fmtputc(fmt, ((c) & 7) + '0'); + } + else + fmtputc(fmt, c); + } + fmtputc(fmt, ')'); +} + +static void fmthex(struct fmt *fmt, fz_obj *obj) +{ + int i; + int c; + + fmtputc(fmt, '<'); + for (i = 0; i < obj->u.s.len; i++) { + c = (obj->u.s.buf[i] >> 4) & 0x0f; + fmtputc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); + c = (obj->u.s.buf[i]) & 0x0f; + fmtputc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); + } + fmtputc(fmt, '>'); +} + +static void fmtarray(struct fmt *fmt, fz_obj *obj) +{ + int i; + + if (fmt->tight) { + fmtputc(fmt, '['); + for (i = 0; i < fz_arraylen(obj); i++) { + fmtobj(fmt, fz_arrayget(obj, i)); + fmtsep(fmt); + } + fmtputc(fmt, ']'); + } + else { + fmtputs(fmt, "[ "); + for (i = 0; i < fz_arraylen(obj); i++) { + if (fmt->col > 60) { + fmtputc(fmt, '\n'); + fmtindent(fmt); + } + fmtobj(fmt, fz_arrayget(obj, i)); + fmtputc(fmt, ' '); + } + fmtputc(fmt, ']'); + fmtsep(fmt); + } +} + +static void fmtdict(struct fmt *fmt, fz_obj *obj) +{ + int i; + fz_obj *key, *val; + + if (fmt->tight) { + fmtputs(fmt, "<<"); + for (i = 0; i < fz_dictlen(obj); i++) { + fmtobj(fmt, fz_dictgetkey(obj, i)); + fmtsep(fmt); + fmtobj(fmt, fz_dictgetval(obj, i)); + fmtsep(fmt); + } + fmtputs(fmt, ">>"); + } + else { + fmtputs(fmt, "<<\n"); + fmt->indent ++; + for (i = 0; i < fz_dictlen(obj); i++) { + key = fz_dictgetkey(obj, i); + val = fz_dictgetval(obj, i); + fmtindent(fmt); + fmtobj(fmt, key); + fmtputc(fmt, ' '); + if (fz_isarray(val)) + fmt->indent ++; + fmtobj(fmt, val); + fmtputc(fmt, '\n'); + if (fz_isarray(val)) + fmt->indent --; + } + fmt->indent --; + fmtindent(fmt); + fmtputs(fmt, ">>"); + } +} + +static void fmtobj(struct fmt *fmt, fz_obj *obj) +{ + char buf[256]; + + if (!obj) { + fmtputs(fmt, "<nil>"); + return; + } + + switch (obj->kind) + { + case FZ_NULL: + fmtputs(fmt, "null"); + break; + case FZ_BOOL: + fmtputs(fmt, fz_tobool(obj) ? "true" : "false"); + break; + case FZ_INT: + sprintf(buf, "%d", fz_toint(obj)); + fmtputs(fmt, buf); + break; + case FZ_REAL: + sprintf(buf, "%g", fz_toreal(obj)); + if (strchr(buf, 'e')) /* bad news! */ + sprintf(buf, fabs(fz_toreal(obj)) > 1 ? "%1.1f" : "%1.8f", fz_toreal(obj)); + fmtputs(fmt, buf); + break; + case FZ_STRING: + { + int added = 0; + int i, c; + for (i = 0; i < obj->u.s.len; i++) { + c = (unsigned char)obj->u.s.buf[i]; + if (strchr("()\\\n\r\t\b\f", c) != 0) + added ++; + else if (c < 8) + added ++; + else if (c < 32) + added += 2; + else if (c >= 127) + added += 3; + } + if (added < obj->u.s.len) + fmtstr(fmt, obj); + else + fmthex(fmt, obj); + } + break; + case FZ_NAME: + sprintf(buf, "/%s", fz_toname(obj)); + fmtputs(fmt, buf); + break; + case FZ_ARRAY: + fmtarray(fmt, obj); + break; + case FZ_DICT: + fmtdict(fmt, obj); + break; + case FZ_INDIRECT: + sprintf(buf, "%d %d R", obj->u.r.oid, obj->u.r.gid); + fmtputs(fmt, buf); + break; + case FZ_POINTER: + sprintf(buf, "$%p", obj->u.p); + fmtputs(fmt, buf); + break; + default: + sprintf(buf, "<unknown object type %d>", obj->kind); + fmtputs(fmt, buf); + break; + } +} + +int +fz_sprintobj(char *s, fz_obj *obj) +{ + struct fmt fmt; + + fmt.indent = 0; + fmt.tight = 0; + fmt.col = 0; + fmt.sep = 0; + fmt.last = 0; + + fmt.file = nil; + fmt.buf = s; + fmt.len = 0; + fmtobj(&fmt, obj); + return fmt.len; +} + +int +fz_sprintcobj(char *s, fz_obj *obj) +{ + struct fmt fmt; + + fmt.indent = 0; + fmt.tight = 1; + fmt.col = 0; + fmt.sep = 0; + fmt.last = 0; + + fmt.file = nil; + fmt.buf = s; + fmt.len = 0; + fmtobj(&fmt, obj); + return fmt.len; +} + +int +fz_fprintobj(FILE *file, fz_obj *obj) +{ + struct fmt fmt; + + fmt.indent = 0; + fmt.tight = 0; + fmt.col = 0; + fmt.sep = 0; + fmt.last = 0; + + fmt.file = file; + fmt.buf = nil; + fmt.len = 0; + fmtobj(&fmt, obj); + return fmt.len; +} + +int +fz_fprintcobj(FILE *file, fz_obj *obj) +{ + struct fmt fmt; + + fmt.indent = 0; + fmt.tight = 1; + fmt.col = 0; + fmt.sep = 0; + fmt.last = 0; + + fmt.file = file; + fmt.buf = nil; + fmt.len = 0; + fmtobj(&fmt, obj); + return fmt.len; +} + diff --git a/object/simple.c b/object/simple.c new file mode 100644 index 00000000..02da3cec --- /dev/null +++ b/object/simple.c @@ -0,0 +1,230 @@ +#include <fitz.h> + +#define NEWOBJ(KIND,SIZE) \ + fz_obj *o; \ + o = *op = fz_malloc(SIZE); \ + if (!o) return fz_outofmem; \ + o->kind = KIND; \ + o->refcount = 1 + +fz_error * +fz_newnull(fz_obj **op) +{ + NEWOBJ(FZ_NULL, sizeof (fz_obj)); + return nil; +} + +fz_error * +fz_newbool(fz_obj **op, int b) +{ + NEWOBJ(FZ_BOOL, sizeof (fz_obj)); + o->u.b = b; + return nil; +} + +fz_error * +fz_newint(fz_obj **op, int i) +{ + NEWOBJ(FZ_INT, sizeof (fz_obj)); + o->u.i = i; + return nil; +} + +fz_error * +fz_newreal(fz_obj **op, float f) +{ + NEWOBJ(FZ_REAL, sizeof (fz_obj)); + o->u.f = f; + return nil; +} + +fz_error * +fz_newstring(fz_obj **op, char *str, int len) +{ + NEWOBJ(FZ_STRING, offsetof(fz_obj, u.s.buf) + len); + o->u.s.len = len; + memcpy(o->u.s.buf, str, len); + return nil; +} + +fz_error * +fz_newname(fz_obj **op, char *str) +{ + NEWOBJ(FZ_NAME, offsetof(fz_obj, u.n) + strlen(str) + 1); + strcpy(o->u.n, str); + return nil; +} + +fz_error * +fz_newindirect(fz_obj **op, int objid, int genid) +{ + NEWOBJ(FZ_INDIRECT, sizeof (fz_obj)); + o->u.r.oid = objid; + o->u.r.gid = genid; + return nil; +} + +fz_error * +fz_newpointer(fz_obj **op, void *p) +{ + NEWOBJ(FZ_POINTER, sizeof (fz_obj)); + o->u.p = p; + return nil; +} + +fz_obj * +fz_keepobj(fz_obj *o) +{ + o->refcount ++; + return o; +} + +fz_obj * +fz_dropobj(fz_obj *o) +{ + o->refcount --; + if (o->refcount == 0) { + if (o->kind == FZ_ARRAY) + fz_freearray(o); + else if (o->kind == FZ_DICT) + fz_freedict(o); + else + fz_free(o); + } + return nil; +} + +int +fz_isnull(fz_obj *obj) +{ + return obj ? obj->kind == FZ_NULL : 0; +} + +int +fz_isbool(fz_obj *obj) +{ + return obj ? obj->kind == FZ_BOOL : 0; +} + +int +fz_isint(fz_obj *obj) +{ + return obj ? obj->kind == FZ_INT : 0; +} + +int +fz_isreal(fz_obj *obj) +{ + return obj ? obj->kind == FZ_REAL : 0; +} + +int +fz_isstring(fz_obj *obj) +{ + return obj ? obj->kind == FZ_STRING : 0; +} + +int +fz_isname(fz_obj *obj) +{ + return obj ? obj->kind == FZ_NAME : 0; +} + +int +fz_isarray(fz_obj *obj) +{ + return obj ? obj->kind == FZ_ARRAY : 0; +} + +int +fz_isdict(fz_obj *obj) +{ + return obj ? obj->kind == FZ_DICT : 0; +} + +int +fz_isindirect(fz_obj *obj) +{ + return obj ? obj->kind == FZ_INDIRECT : 0; +} + +int +fz_ispointer(fz_obj *obj) +{ + return obj ? obj->kind == FZ_POINTER : 0; +} + +int +fz_tobool(fz_obj *obj) +{ + if (fz_isbool(obj)) + return obj->u.b; + return 0; +} + +int +fz_toint(fz_obj *obj) +{ + if (fz_isint(obj)) + return obj->u.i; + return 0; +} + +float +fz_toreal(fz_obj *obj) +{ + if (fz_isreal(obj)) + return obj->u.f; + if (fz_isint(obj)) + return obj->u.i; + return 0; +} + +char * +fz_toname(fz_obj *obj) +{ + if (fz_isname(obj)) + return obj->u.n; + return ""; +} + +char * +fz_tostringbuf(fz_obj *obj) +{ + if (fz_isstring(obj)) + return obj->u.s.buf; + return ""; +} + +int +fz_tostringlen(fz_obj *obj) +{ + if (fz_isstring(obj)) + return obj->u.s.len; + return 0; +} + +int +fz_toobjid(fz_obj *obj) +{ + if (fz_isindirect(obj)) + return obj->u.r.oid; + return 0; +} + +int +fz_togenid(fz_obj *obj) +{ + if (fz_isindirect(obj)) + return obj->u.r.gid; + return 0; +} + +void * +fz_topointer(fz_obj *obj) +{ + if (fz_ispointer(obj)) + return obj->u.p; + return nil; +} + |