1 /* Copyright (c) 2014, Vsevolod Stakhov
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution.
12 * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
13 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15 * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
16 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
19 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "ucl_internal.h"
30 #include "ucl_chartable.h"
39 extern const struct ucl_emitter_operations ucl_standartd_emitter_ops[];
41 static const struct ucl_emitter_context ucl_standard_emitters[] = {
46 .ops = &ucl_standartd_emitter_ops[UCL_EMIT_JSON]
48 [UCL_EMIT_JSON_COMPACT] = {
49 .name = "json_compact",
50 .id = UCL_EMIT_JSON_COMPACT,
52 .ops = &ucl_standartd_emitter_ops[UCL_EMIT_JSON_COMPACT]
56 .id = UCL_EMIT_CONFIG,
58 .ops = &ucl_standartd_emitter_ops[UCL_EMIT_CONFIG]
64 .ops = &ucl_standartd_emitter_ops[UCL_EMIT_YAML]
69 * Get standard emitter context for a specified emit_type
70 * @param emit_type type of emitter
71 * @return context or NULL if input is invalid
73 const struct ucl_emitter_context *
74 ucl_emit_get_standard_context (enum ucl_emitter emit_type)
76 if (emit_type >= UCL_EMIT_JSON && emit_type <= UCL_EMIT_YAML) {
77 return &ucl_standard_emitters[emit_type];
85 * @param str string to emit
86 * @param buf target buffer
89 ucl_elt_string_write_json (const char *str, size_t size,
90 struct ucl_emitter_context *ctx)
92 const char *p = str, *c = str;
94 const struct ucl_emitter_functions *func = ctx->func;
96 func->ucl_emitter_append_character ('"', 1, func->ud);
99 if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) {
101 func->ucl_emitter_append_len (c, len, func->ud);
105 func->ucl_emitter_append_len ("\\n", 2, func->ud);
108 func->ucl_emitter_append_len ("\\r", 2, func->ud);
111 func->ucl_emitter_append_len ("\\b", 2, func->ud);
114 func->ucl_emitter_append_len ("\\t", 2, func->ud);
117 func->ucl_emitter_append_len ("\\f", 2, func->ud);
120 func->ucl_emitter_append_len ("\\\\", 2, func->ud);
123 func->ucl_emitter_append_len ("\\\"", 2, func->ud);
136 func->ucl_emitter_append_len (c, len, func->ud);
138 func->ucl_emitter_append_character ('"', 1, func->ud);
142 ucl_elt_string_write_multiline (const char *str, size_t size,
143 struct ucl_emitter_context *ctx)
145 const struct ucl_emitter_functions *func = ctx->func;
147 func->ucl_emitter_append_len ("<<EOD\n", sizeof ("<<EOD\n") - 1, func->ud);
148 func->ucl_emitter_append_len (str, size, func->ud);
149 func->ucl_emitter_append_len ("\nEOD", sizeof ("\nEOD") - 1, func->ud);
153 * Generic utstring output
156 ucl_utstring_append_character (unsigned char c, size_t len, void *ud)
161 utstring_append_c (buf, c);
164 utstring_reserve (buf, len + 1);
165 memset (&buf->d[buf->i], c, len);
167 buf->d[buf->i] = '\0';
174 ucl_utstring_append_len (const unsigned char *str, size_t len, void *ud)
178 utstring_append_len (buf, str, len);
184 ucl_utstring_append_int (int64_t val, void *ud)
188 utstring_printf (buf, "%jd", (intmax_t)val);
193 ucl_utstring_append_double (double val, void *ud)
196 const double delta = 0.0000001;
198 if (val == (double)(int)val) {
199 utstring_printf (buf, "%.1lf", val);
201 else if (fabs (val - (double)(int)val) < delta) {
202 /* Write at maximum precision */
203 utstring_printf (buf, "%.*lg", DBL_DIG, val);
206 utstring_printf (buf, "%lf", val);
213 * Generic file output
216 ucl_file_append_character (unsigned char c, size_t len, void *ud)
228 ucl_file_append_len (const unsigned char *str, size_t len, void *ud)
232 fwrite (str, len, 1, fp);
238 ucl_file_append_int (int64_t val, void *ud)
242 fprintf (fp, "%jd", (intmax_t)val);
248 ucl_file_append_double (double val, void *ud)
251 const double delta = 0.0000001;
253 if (val == (double)(int)val) {
254 fprintf (fp, "%.1lf", val);
256 else if (fabs (val - (double)(int)val) < delta) {
257 /* Write at maximum precision */
258 fprintf (fp, "%.*lg", DBL_DIG, val);
261 fprintf (fp, "%lf", val);
268 * Generic file descriptor writing functions
271 ucl_fd_append_character (unsigned char c, size_t len, void *ud)
277 return write (fd, &c, 1);
284 if (write (fd, &c, 1) == -1) {
290 memset (buf, c, len);
291 if (write (fd, buf, len) == -1) {
303 ucl_fd_append_len (const unsigned char *str, size_t len, void *ud)
307 return write (fd, str, len);
311 ucl_fd_append_int (int64_t val, void *ud)
316 snprintf (intbuf, sizeof (intbuf), "%jd", (intmax_t)val);
317 return write (fd, intbuf, strlen (intbuf));
321 ucl_fd_append_double (double val, void *ud)
324 const double delta = 0.0000001;
327 if (val == (double)(int)val) {
328 snprintf (nbuf, sizeof (nbuf), "%.1lf", val);
330 else if (fabs (val - (double)(int)val) < delta) {
331 /* Write at maximum precision */
332 snprintf (nbuf, sizeof (nbuf), "%.*lg", DBL_DIG, val);
335 snprintf (nbuf, sizeof (nbuf), "%lf", val);
338 return write (fd, nbuf, strlen (nbuf));
341 struct ucl_emitter_functions*
342 ucl_object_emit_memory_funcs (void **pmem)
344 struct ucl_emitter_functions *f;
347 f = calloc (1, sizeof (*f));
350 f->ucl_emitter_append_character = ucl_utstring_append_character;
351 f->ucl_emitter_append_double = ucl_utstring_append_double;
352 f->ucl_emitter_append_int = ucl_utstring_append_int;
353 f->ucl_emitter_append_len = ucl_utstring_append_len;
354 f->ucl_emitter_free_func = free;
364 struct ucl_emitter_functions*
365 ucl_object_emit_file_funcs (FILE *fp)
367 struct ucl_emitter_functions *f;
369 f = calloc (1, sizeof (*f));
372 f->ucl_emitter_append_character = ucl_file_append_character;
373 f->ucl_emitter_append_double = ucl_file_append_double;
374 f->ucl_emitter_append_int = ucl_file_append_int;
375 f->ucl_emitter_append_len = ucl_file_append_len;
376 f->ucl_emitter_free_func = NULL;
383 struct ucl_emitter_functions*
384 ucl_object_emit_fd_funcs (int fd)
386 struct ucl_emitter_functions *f;
389 f = calloc (1, sizeof (*f));
392 ip = malloc (sizeof (fd));
398 memcpy (ip, &fd, sizeof (fd));
399 f->ucl_emitter_append_character = ucl_fd_append_character;
400 f->ucl_emitter_append_double = ucl_fd_append_double;
401 f->ucl_emitter_append_int = ucl_fd_append_int;
402 f->ucl_emitter_append_len = ucl_fd_append_len;
403 f->ucl_emitter_free_func = free;
411 ucl_object_emit_funcs_free (struct ucl_emitter_functions *f)
414 if (f->ucl_emitter_free_func != NULL) {
415 f->ucl_emitter_free_func (f->ud);
423 ucl_object_emit_single_json (const ucl_object_t *obj)
425 UT_string *buf = NULL;
426 unsigned char *res = NULL;
437 ucl_utstring_append_len ("object", 6, buf);
440 ucl_utstring_append_len ("array", 5, buf);
443 ucl_utstring_append_int (obj->value.iv, buf);
447 ucl_utstring_append_double (obj->value.dv, buf);
450 ucl_utstring_append_len ("null", 4, buf);
454 ucl_utstring_append_len ("true", 4, buf);
457 ucl_utstring_append_len ("false", 5, buf);
461 ucl_utstring_append_len (obj->value.sv, obj->len, buf);
464 ucl_utstring_append_len ("userdata", 8, buf);
467 res = utstring_body (buf);
474 #define LONG_STRING_LIMIT 80
477 ucl_maybe_long_string (const ucl_object_t *obj)
479 if (obj->len > LONG_STRING_LIMIT || (obj->flags & UCL_OBJECT_MULTILINE)) {
480 /* String is long enough, so search for newline characters in it */
481 if (memchr (obj->value.sv, '\n', obj->len) != NULL) {