/fitz/obj_print.c

https://github.com/Lafriks/mupdf · C · 340 lines · 306 code · 34 blank · 0 comment · 102 complexity · 73c3c0972b25bf82783c2234ad2f7c06 MD5 · raw file

  1. #include "fitz.h"
  2. struct fmt
  3. {
  4. char *buf;
  5. int cap;
  6. int len;
  7. int indent;
  8. int tight;
  9. int col;
  10. int sep;
  11. int last;
  12. fz_context *ctx;
  13. };
  14. static void fmt_obj(struct fmt *fmt, fz_obj *obj);
  15. static inline int iswhite(int ch)
  16. {
  17. return
  18. ch == '\000' ||
  19. ch == '\011' ||
  20. ch == '\012' ||
  21. ch == '\014' ||
  22. ch == '\015' ||
  23. ch == '\040';
  24. }
  25. static inline int isdelim(int ch)
  26. {
  27. return ch == '(' || ch == ')' ||
  28. ch == '<' || ch == '>' ||
  29. ch == '[' || ch == ']' ||
  30. ch == '{' || ch == '}' ||
  31. ch == '/' ||
  32. ch == '%';
  33. }
  34. static inline void fmt_putc(struct fmt *fmt, int c)
  35. {
  36. if (fmt->sep && !isdelim(fmt->last) && !isdelim(c)) {
  37. fmt->sep = 0;
  38. fmt_putc(fmt, ' ');
  39. }
  40. fmt->sep = 0;
  41. if (fmt->buf && fmt->len < fmt->cap)
  42. fmt->buf[fmt->len] = c;
  43. if (c == '\n')
  44. fmt->col = 0;
  45. else
  46. fmt->col ++;
  47. fmt->len ++;
  48. fmt->last = c;
  49. }
  50. static inline void fmt_indent(struct fmt *fmt)
  51. {
  52. int i = fmt->indent;
  53. while (i--) {
  54. fmt_putc(fmt, ' ');
  55. fmt_putc(fmt, ' ');
  56. }
  57. }
  58. static inline void fmt_puts(struct fmt *fmt, char *s)
  59. {
  60. while (*s)
  61. fmt_putc(fmt, *s++);
  62. }
  63. static inline void fmt_sep(struct fmt *fmt)
  64. {
  65. fmt->sep = 1;
  66. }
  67. static void fmt_str(struct fmt *fmt, fz_obj *obj)
  68. {
  69. char *s = fz_to_str_buf(fmt->ctx, obj);
  70. int n = fz_to_str_len(fmt->ctx, obj);
  71. int i, c;
  72. fmt_putc(fmt, '(');
  73. for (i = 0; i < n; i++)
  74. {
  75. c = (unsigned char)s[i];
  76. if (c == '\n')
  77. fmt_puts(fmt, "\\n");
  78. else if (c == '\r')
  79. fmt_puts(fmt, "\\r");
  80. else if (c == '\t')
  81. fmt_puts(fmt, "\\t");
  82. else if (c == '\b')
  83. fmt_puts(fmt, "\\b");
  84. else if (c == '\f')
  85. fmt_puts(fmt, "\\f");
  86. else if (c == '(')
  87. fmt_puts(fmt, "\\(");
  88. else if (c == ')')
  89. fmt_puts(fmt, "\\)");
  90. else if (c < 32 || c >= 127) {
  91. char buf[16];
  92. fmt_putc(fmt, '\\');
  93. sprintf(buf, "%03o", c);
  94. fmt_puts(fmt, buf);
  95. }
  96. else
  97. fmt_putc(fmt, c);
  98. }
  99. fmt_putc(fmt, ')');
  100. }
  101. static void fmt_hex(struct fmt *fmt, fz_obj *obj)
  102. {
  103. char *s = fz_to_str_buf(fmt->ctx, obj);
  104. int n = fz_to_str_len(fmt->ctx, obj);
  105. int i, b, c;
  106. fmt_putc(fmt, '<');
  107. for (i = 0; i < n; i++) {
  108. b = (unsigned char) s[i];
  109. c = (b >> 4) & 0x0f;
  110. fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA);
  111. c = (b) & 0x0f;
  112. fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA);
  113. }
  114. fmt_putc(fmt, '>');
  115. }
  116. static void fmt_name(struct fmt *fmt, fz_obj *obj)
  117. {
  118. unsigned char *s = (unsigned char *) fz_to_name(fmt->ctx, obj);
  119. int i, c;
  120. fmt_putc(fmt, '/');
  121. for (i = 0; s[i]; i++)
  122. {
  123. if (isdelim(s[i]) || iswhite(s[i]) ||
  124. s[i] == '#' || s[i] < 32 || s[i] >= 127)
  125. {
  126. fmt_putc(fmt, '#');
  127. c = (s[i] >> 4) & 0xf;
  128. fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA);
  129. c = s[i] & 0xf;
  130. fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA);
  131. }
  132. else
  133. {
  134. fmt_putc(fmt, s[i]);
  135. }
  136. }
  137. }
  138. static void fmt_array(struct fmt *fmt, fz_obj *obj)
  139. {
  140. int i;
  141. fz_context *ctx = fmt->ctx;
  142. if (fmt->tight) {
  143. fmt_putc(fmt, '[');
  144. for (i = 0; i < fz_array_len(ctx, obj); i++) {
  145. fmt_obj(fmt, fz_array_get(ctx, obj, i));
  146. fmt_sep(fmt);
  147. }
  148. fmt_putc(fmt, ']');
  149. }
  150. else {
  151. fmt_puts(fmt, "[ ");
  152. for (i = 0; i < fz_array_len(ctx, obj); i++) {
  153. if (fmt->col > 60) {
  154. fmt_putc(fmt, '\n');
  155. fmt_indent(fmt);
  156. }
  157. fmt_obj(fmt, fz_array_get(ctx, obj, i));
  158. fmt_putc(fmt, ' ');
  159. }
  160. fmt_putc(fmt, ']');
  161. fmt_sep(fmt);
  162. }
  163. }
  164. static void fmt_dict(struct fmt *fmt, fz_obj *obj)
  165. {
  166. int i;
  167. fz_obj *key, *val;
  168. fz_context *ctx = fmt->ctx;
  169. if (fmt->tight) {
  170. fmt_puts(fmt, "<<");
  171. for (i = 0; i < fz_dict_len(ctx, obj); i++) {
  172. fmt_obj(fmt, fz_dict_get_key(ctx, obj, i));
  173. fmt_sep(fmt);
  174. fmt_obj(fmt, fz_dict_get_val(ctx, obj, i));
  175. fmt_sep(fmt);
  176. }
  177. fmt_puts(fmt, ">>");
  178. }
  179. else {
  180. fmt_puts(fmt, "<<\n");
  181. fmt->indent ++;
  182. for (i = 0; i < fz_dict_len(ctx, obj); i++) {
  183. key = fz_dict_get_key(ctx, obj, i);
  184. val = fz_dict_get_val(ctx, obj, i);
  185. fmt_indent(fmt);
  186. fmt_obj(fmt, key);
  187. fmt_putc(fmt, ' ');
  188. if (!fz_is_indirect(val) && fz_is_array(ctx, val))
  189. fmt->indent ++;
  190. fmt_obj(fmt, val);
  191. fmt_putc(fmt, '\n');
  192. if (!fz_is_indirect(val) && fz_is_array(ctx, val))
  193. fmt->indent --;
  194. }
  195. fmt->indent --;
  196. fmt_indent(fmt);
  197. fmt_puts(fmt, ">>");
  198. }
  199. }
  200. static void fmt_obj(struct fmt *fmt, fz_obj *obj)
  201. {
  202. char buf[256];
  203. fz_context *ctx = fmt->ctx;
  204. if (!obj)
  205. fmt_puts(fmt, "<NULL>");
  206. else if (fz_is_indirect(obj))
  207. {
  208. sprintf(buf, "%d %d R", fz_to_num(obj), fz_to_gen(obj));
  209. fmt_puts(fmt, buf);
  210. }
  211. else if (fz_is_null(ctx, obj))
  212. fmt_puts(fmt, "null");
  213. else if (fz_is_bool(ctx, obj))
  214. fmt_puts(fmt, fz_to_bool(ctx, obj) ? "true" : "false");
  215. else if (fz_is_int(ctx, obj))
  216. {
  217. sprintf(buf, "%d", fz_to_int(ctx, obj));
  218. fmt_puts(fmt, buf);
  219. }
  220. else if (fz_is_real(ctx, obj))
  221. {
  222. sprintf(buf, "%g", fz_to_real(ctx, obj));
  223. if (strchr(buf, 'e')) /* bad news! */
  224. sprintf(buf, fabsf(fz_to_real(ctx, obj)) > 1 ? "%1.1f" : "%1.8f", fz_to_real(ctx, obj));
  225. fmt_puts(fmt, buf);
  226. }
  227. else if (fz_is_string(ctx, obj))
  228. {
  229. char *str = fz_to_str_buf(ctx, obj);
  230. int len = fz_to_str_len(ctx, obj);
  231. int added = 0;
  232. int i, c;
  233. for (i = 0; i < len; i++) {
  234. c = (unsigned char)str[i];
  235. if (strchr("()\\\n\r\t\b\f", c))
  236. added ++;
  237. else if (c < 32 || c >= 127)
  238. added += 3;
  239. }
  240. if (added < len)
  241. fmt_str(fmt, obj);
  242. else
  243. fmt_hex(fmt, obj);
  244. }
  245. else if (fz_is_name(ctx, obj))
  246. fmt_name(fmt, obj);
  247. else if (fz_is_array(ctx, obj))
  248. fmt_array(fmt, obj);
  249. else if (fz_is_dict(ctx, obj))
  250. fmt_dict(fmt, obj);
  251. else
  252. fmt_puts(fmt, "<unknown object>");
  253. }
  254. static int
  255. fz_sprint_obj(fz_context *ctx, char *s, int n, fz_obj *obj, int tight)
  256. {
  257. struct fmt fmt;
  258. fmt.indent = 0;
  259. fmt.col = 0;
  260. fmt.sep = 0;
  261. fmt.last = 0;
  262. fmt.tight = tight;
  263. fmt.buf = s;
  264. fmt.cap = n;
  265. fmt.len = 0;
  266. fmt.ctx = ctx;
  267. fmt_obj(&fmt, obj);
  268. if (fmt.buf && fmt.len < fmt.cap)
  269. fmt.buf[fmt.len] = '\0';
  270. return fmt.len;
  271. }
  272. int
  273. fz_fprint_obj(fz_context *ctx, FILE *fp, fz_obj *obj, int tight)
  274. {
  275. char buf[1024];
  276. char *ptr;
  277. int n;
  278. n = fz_sprint_obj(ctx, NULL, 0, obj, tight);
  279. if ((n + 1) < sizeof buf)
  280. {
  281. fz_sprint_obj(ctx, buf, sizeof buf, obj, tight);
  282. fputs(buf, fp);
  283. fputc('\n', fp);
  284. }
  285. else
  286. {
  287. ptr = fz_malloc(ctx, n + 1);
  288. fz_sprint_obj(ctx, ptr, n + 1, obj, tight);
  289. fputs(ptr, fp);
  290. fputc('\n', fp);
  291. fz_free(ctx, ptr);
  292. }
  293. return n;
  294. }
  295. void
  296. fz_debug_obj(fz_context *ctx, fz_obj *obj)
  297. {
  298. fz_fprint_obj(ctx, stdout, obj, 0);
  299. }
  300. void
  301. fz_debug_ref(fz_context *ctx, fz_obj *ref)
  302. {
  303. fz_obj *obj;
  304. obj = fz_resolve_indirect(ctx, ref);
  305. fz_debug_obj(ctx, obj);
  306. }