Code

1792cdac9b3f53eacb9c0b8ef238426a5e465b3b
[sysdb.git] / src / tools / sysdb / json.c
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 #include <yajl/yajl_parse.h>
39 #include <yajl/yajl_gen.h>
41 #include <unistd.h>
42 #include <stdio.h>
44 #ifdef HAVE_LIBYAJL
46 /*
47  * YAJL callbacks
48  */
50 #define GEN(obj) ((yajl_gen)(obj))
51 #define OK(cb) ((cb) == yajl_gen_status_ok)
53 static int
54 gen_null(void *ctx) { return OK(yajl_gen_null(GEN(ctx))); }
56 static int
57 gen_boolean(void *ctx, int v) { return OK(yajl_gen_bool(GEN(ctx), v)); }
59 static int
60 gen_number(void *ctx, const char *v, size_t l)
61 {
62         return OK(yajl_gen_number(GEN(ctx), v, l));
63 }
65 static int
66 gen_string(void *ctx, const unsigned char *v, size_t l)
67 {
68         return OK(yajl_gen_string(GEN(ctx), v, l));
69 }
71 static int
72 gen_start_map(void *ctx) { return OK(yajl_gen_map_open(GEN(ctx))); }
74 static int
75 gen_end_map(void *ctx) { return OK(yajl_gen_map_close(GEN(ctx))); }
77 static int
78 gen_start_array(void *ctx) { return OK(yajl_gen_array_open(GEN(ctx))); }
80 static int
81 gen_end_array(void *ctx) { return OK(yajl_gen_array_close(GEN(ctx))); }
83 static yajl_callbacks reformatters = {
84         gen_null,
85         gen_boolean,
86         NULL, /* gen_integer; */
87         NULL, /* gen_doube; both default to gen_number */
88         gen_number,
89         gen_string,
90         gen_start_map,
91         gen_string,
92         gen_end_map,
93         gen_start_array,
94         gen_end_array,
95 };
97 static void
98 printer(void __attribute__((unused)) *ctx, const char *str, size_t len)
99 {
100         write(1, str, len);
101 } /* printer */
103 #endif /* HAVE_LIBYAJL */
105 /*
106  * public API
107  */
109 int
110 sdb_json_print(sdb_input_t *input, sdb_strbuf_t *buf)
112 #ifdef HAVE_LIBYAJL
113         const unsigned char *json;
114         size_t json_len;
116         yajl_handle h;
117         yajl_gen gen;
118         yajl_status status;
120         int ret = 0;
122         if (!input->interactive) {
123                 /* no formatting */
124                 printf("%s\n", sdb_strbuf_string(buf));
125                 return 0;
126         }
128         gen = yajl_gen_alloc(/* alloc_funcs */ NULL);
129         if (! gen)
130                 return -1;
132         yajl_gen_config(gen, yajl_gen_beautify, 1);
133         yajl_gen_config(gen, yajl_gen_validate_utf8, 1);
134         yajl_gen_config(gen, yajl_gen_print_callback, printer, NULL);
136         h = yajl_alloc(&reformatters, /* alloc_funcs */ NULL, (void *)gen);
137         if (! h) {
138                 yajl_gen_free(gen);
139                 return -1;
140         }
142         json = (const unsigned char *)sdb_strbuf_string(buf);
143         json_len = sdb_strbuf_len(buf);
144         status = yajl_parse(h, json, json_len);
145         if (status == yajl_status_ok)
146                 status = yajl_complete_parse(h);
148         if (status != yajl_status_ok) {
149                 unsigned char *err = yajl_get_error(h, 1, json, json_len);
150                 sdb_log(SDB_LOG_ERR, "%s", err);
151                 yajl_free_error(h, err);
152                 ret = -1;
153         }
155         yajl_gen_free(gen);
156         yajl_free(h);
157         return ret;
158 #else /* HAVE_LIBYAJL */
159         printf("%s\n", sdb_strbuf_string(buf));
160         return 0;
161 #endif /* HAVE_LIBYAJL */
162 } /* sdb_json_print */
164 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */