4f36179b02c823161487c6c0351c9c841351824c
1 /*
2 * SysDB - src/tools/sysdb/json.c
3 * Copyright (C) 2016 Sebastian 'tokkee' Harl <sh@tokkee.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
28 #if HAVE_CONFIG_H
29 # include "config.h"
30 #endif /* HAVE_CONFIG_H */
32 #include "sysdb.h"
34 #include "utils/error.h"
35 #include "utils/strbuf.h"
36 #include "tools/sysdb/json.h"
38 #ifdef HAVE_LIBYAJL
39 # include <yajl/yajl_parse.h>
40 # include <yajl/yajl_gen.h>
41 #endif
43 #include <unistd.h>
44 #include <stdio.h>
46 #ifdef HAVE_LIBYAJL
48 /*
49 * YAJL callbacks
50 */
52 #define GEN(obj) ((yajl_gen)(obj))
53 #define OK(cb) ((cb) == yajl_gen_status_ok)
55 static int
56 gen_null(void *ctx) { return OK(yajl_gen_null(GEN(ctx))); }
58 static int
59 gen_boolean(void *ctx, int v) { return OK(yajl_gen_bool(GEN(ctx), v)); }
61 static int
62 gen_number(void *ctx, const char *v, size_t l)
63 {
64 return OK(yajl_gen_number(GEN(ctx), v, l));
65 }
67 static int
68 gen_string(void *ctx, const unsigned char *v, size_t l)
69 {
70 return OK(yajl_gen_string(GEN(ctx), v, l));
71 }
73 static int
74 gen_start_map(void *ctx) { return OK(yajl_gen_map_open(GEN(ctx))); }
76 static int
77 gen_end_map(void *ctx) { return OK(yajl_gen_map_close(GEN(ctx))); }
79 static int
80 gen_start_array(void *ctx) { return OK(yajl_gen_array_open(GEN(ctx))); }
82 static int
83 gen_end_array(void *ctx) { return OK(yajl_gen_array_close(GEN(ctx))); }
85 static yajl_callbacks reformatters = {
86 gen_null,
87 gen_boolean,
88 NULL, /* gen_integer; */
89 NULL, /* gen_doube; both default to gen_number */
90 gen_number,
91 gen_string,
92 gen_start_map,
93 gen_string,
94 gen_end_map,
95 gen_start_array,
96 gen_end_array,
97 };
99 static void
100 printer(void __attribute__((unused)) *ctx, const char *str, size_t len)
101 {
102 write(1, str, len);
103 } /* printer */
105 #endif /* HAVE_LIBYAJL */
107 /*
108 * public API
109 */
111 int
112 sdb_json_print(sdb_input_t *input, sdb_strbuf_t *buf)
113 {
114 #ifdef HAVE_LIBYAJL
115 const unsigned char *json;
116 size_t json_len;
118 yajl_handle h;
119 yajl_gen gen;
120 yajl_status status;
122 int ret = 0;
124 if (!input->interactive) {
125 /* no formatting */
126 printf("%s\n", sdb_strbuf_string(buf));
127 return 0;
128 }
130 gen = yajl_gen_alloc(/* alloc_funcs */ NULL);
131 if (! gen)
132 return -1;
134 yajl_gen_config(gen, yajl_gen_beautify, 1);
135 yajl_gen_config(gen, yajl_gen_validate_utf8, 1);
136 yajl_gen_config(gen, yajl_gen_print_callback, printer, NULL);
138 h = yajl_alloc(&reformatters, /* alloc_funcs */ NULL, (void *)gen);
139 if (! h) {
140 yajl_gen_free(gen);
141 return -1;
142 }
144 json = (const unsigned char *)sdb_strbuf_string(buf);
145 json_len = sdb_strbuf_len(buf);
146 status = yajl_parse(h, json, json_len);
147 if (status == yajl_status_ok)
148 status = yajl_complete_parse(h);
150 if (status != yajl_status_ok) {
151 unsigned char *err = yajl_get_error(h, 1, json, json_len);
152 sdb_log(SDB_LOG_ERR, "%s", err);
153 yajl_free_error(h, err);
154 ret = -1;
155 }
157 yajl_gen_free(gen);
158 yajl_free(h);
159 return ret;
160 #else /* HAVE_LIBYAJL */
161 (void)input;
162 printf("%s\n", sdb_strbuf_string(buf));
163 return 0;
164 #endif /* HAVE_LIBYAJL */
165 } /* sdb_json_print */
167 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */