#include "fitz.h" struct fmt { char *buf; int cap; int len; int indent; int tight; int col; int sep; int last; }; static void fmtobj(struct fmt *fmt, fz_obj *obj); 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 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->buf && fmt->len < fmt->cap) fmt->buf[fmt->len] = c; if (c == '\n') fmt->col = 0; else fmt->col ++; fmt->len ++; fmt->last = c; } static inline 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, c; fmtputc(fmt, '('); for (i = 0; i < obj->u.s.len; i++) { c = (unsigned char) 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); } else fmtputc(fmt, c); } fmtputc(fmt, ')'); } static void fmthex(struct fmt *fmt, fz_obj *obj) { int i, b, c; fmtputc(fmt, '<'); for (i = 0; i < obj->u.s.len; i++) { b = (unsigned char) obj->u.s.buf[i]; c = (b >> 4) & 0x0f; fmtputc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); c = (b) & 0x0f; fmtputc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); } fmtputc(fmt, '>'); } static void fmtname(struct fmt *fmt, fz_obj *obj) { unsigned char *s = (unsigned char *) fz_toname(obj); int i, c; fmtputc(fmt, '/'); for (i = 0; s[i]; i++) { if (isdelim(s[i]) || iswhite(s[i]) || s[i] == '#' || s[i] < 32 || s[i] > 127) { fmtputc(fmt, '#'); c = (s[i] >> 4) & 0xf; fmtputc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); c = s[i] & 0xf; fmtputc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); } else { fmtputc(fmt, s[i]); } } } 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_isindirect(val) && fz_isarray(val)) fmt->indent ++; fmtobj(fmt, val); fmtputc(fmt, '\n'); if (!fz_isindirect(val) && 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, ""); else if (fz_isindirect(obj)) { sprintf(buf, "%d %d R", fz_tonum(obj), fz_togen(obj)); fmtputs(fmt, buf); } else if (fz_isnull(obj)) fmtputs(fmt, "null"); else if (fz_isbool(obj)) fmtputs(fmt, fz_tobool(obj) ? "true" : "false"); else if (fz_isint(obj)) { sprintf(buf, "%d", fz_toint(obj)); fmtputs(fmt, buf); } else if (fz_isreal(obj)) { sprintf(buf, "%g", fz_toreal(obj)); if (strchr(buf, 'e')) /* bad news! */ sprintf(buf, fabsf(fz_toreal(obj)) > 1 ? "%1.1f" : "%1.8f", fz_toreal(obj)); fmtputs(fmt, buf); } else if (fz_isstring(obj)) { char *str = fz_tostrbuf(obj); int len = fz_tostrlen(obj); int added = 0; int i, c; for (i = 0; i < len; i++) { c = (unsigned char)str[i]; if (strchr("()\\\n\r\t\b\f", c)) 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); } else if (fz_isname(obj)) fmtname(fmt, obj); else if (fz_isarray(obj)) fmtarray(fmt, obj); else if (fz_isdict(obj)) fmtdict(fmt, obj); else fmtputs(fmt, ""); } int fz_sprintobj(char *s, int n, fz_obj *obj, int tight) { struct fmt fmt; fmt.indent = 0; fmt.col = 0; fmt.sep = 0; fmt.last = 0; fmt.tight = tight; fmt.buf = s; fmt.cap = n; fmt.len = 0; fmtobj(&fmt, obj); if (fmt.buf && fmt.len < fmt.cap) fmt.buf[fmt.len] = '\0'; return fmt.len; } int fz_fprintobj(FILE *fp, fz_obj *obj, int tight) { char buf[1024]; char *ptr; int n; n = fz_sprintobj(nil, 0, obj, tight); if ((n + 1) < sizeof buf) { fz_sprintobj(buf, sizeof buf, obj, tight); fputs(buf, fp); fputc('\n', fp); } else { ptr = fz_malloc(n + 1); fz_sprintobj(ptr, n + 1, obj, tight); fputs(ptr, fp); fputc('\n', fp); fz_free(ptr); } return n; } void fz_debugobj(fz_obj *obj) { fz_fprintobj(stdout, obj, 0); }