13dcf5eb7SBaptiste Daroussin /* Copyright (c) 2014, Vsevolod Stakhov 23dcf5eb7SBaptiste Daroussin * All rights reserved. 33dcf5eb7SBaptiste Daroussin * 43dcf5eb7SBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 53dcf5eb7SBaptiste Daroussin * modification, are permitted provided that the following conditions are met: 63dcf5eb7SBaptiste Daroussin * * Redistributions of source code must retain the above copyright 73dcf5eb7SBaptiste Daroussin * notice, this list of conditions and the following disclaimer. 83dcf5eb7SBaptiste Daroussin * * Redistributions in binary form must reproduce the above copyright 93dcf5eb7SBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 103dcf5eb7SBaptiste Daroussin * documentation and/or other materials provided with the distribution. 113dcf5eb7SBaptiste Daroussin * 123dcf5eb7SBaptiste Daroussin * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY 133dcf5eb7SBaptiste Daroussin * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 143dcf5eb7SBaptiste Daroussin * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 153dcf5eb7SBaptiste Daroussin * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY 163dcf5eb7SBaptiste Daroussin * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 173dcf5eb7SBaptiste Daroussin * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 183dcf5eb7SBaptiste Daroussin * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 193dcf5eb7SBaptiste Daroussin * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 203dcf5eb7SBaptiste Daroussin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 213dcf5eb7SBaptiste Daroussin * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 223dcf5eb7SBaptiste Daroussin */ 233dcf5eb7SBaptiste Daroussin 243dcf5eb7SBaptiste Daroussin #ifdef HAVE_CONFIG_H 253dcf5eb7SBaptiste Daroussin #include "config.h" 263dcf5eb7SBaptiste Daroussin #endif 273dcf5eb7SBaptiste Daroussin 283dcf5eb7SBaptiste Daroussin #include "ucl.h" 293dcf5eb7SBaptiste Daroussin #include "ucl_internal.h" 303dcf5eb7SBaptiste Daroussin #include "ucl_chartable.h" 313dcf5eb7SBaptiste Daroussin 323dcf5eb7SBaptiste Daroussin #ifdef HAVE_FLOAT_H 333dcf5eb7SBaptiste Daroussin #include <float.h> 343dcf5eb7SBaptiste Daroussin #endif 353dcf5eb7SBaptiste Daroussin #ifdef HAVE_MATH_H 363dcf5eb7SBaptiste Daroussin #include <math.h> 373dcf5eb7SBaptiste Daroussin #endif 383dcf5eb7SBaptiste Daroussin 393dcf5eb7SBaptiste Daroussin extern const struct ucl_emitter_operations ucl_standartd_emitter_ops[]; 403dcf5eb7SBaptiste Daroussin 413dcf5eb7SBaptiste Daroussin static const struct ucl_emitter_context ucl_standard_emitters[] = { 423dcf5eb7SBaptiste Daroussin [UCL_EMIT_JSON] = { 433dcf5eb7SBaptiste Daroussin .name = "json", 443dcf5eb7SBaptiste Daroussin .id = UCL_EMIT_JSON, 453dcf5eb7SBaptiste Daroussin .func = NULL, 463dcf5eb7SBaptiste Daroussin .ops = &ucl_standartd_emitter_ops[UCL_EMIT_JSON] 473dcf5eb7SBaptiste Daroussin }, 483dcf5eb7SBaptiste Daroussin [UCL_EMIT_JSON_COMPACT] = { 493dcf5eb7SBaptiste Daroussin .name = "json_compact", 503dcf5eb7SBaptiste Daroussin .id = UCL_EMIT_JSON_COMPACT, 513dcf5eb7SBaptiste Daroussin .func = NULL, 523dcf5eb7SBaptiste Daroussin .ops = &ucl_standartd_emitter_ops[UCL_EMIT_JSON_COMPACT] 533dcf5eb7SBaptiste Daroussin }, 543dcf5eb7SBaptiste Daroussin [UCL_EMIT_CONFIG] = { 553dcf5eb7SBaptiste Daroussin .name = "config", 563dcf5eb7SBaptiste Daroussin .id = UCL_EMIT_CONFIG, 573dcf5eb7SBaptiste Daroussin .func = NULL, 583dcf5eb7SBaptiste Daroussin .ops = &ucl_standartd_emitter_ops[UCL_EMIT_CONFIG] 593dcf5eb7SBaptiste Daroussin }, 603dcf5eb7SBaptiste Daroussin [UCL_EMIT_YAML] = { 613dcf5eb7SBaptiste Daroussin .name = "yaml", 623dcf5eb7SBaptiste Daroussin .id = UCL_EMIT_YAML, 633dcf5eb7SBaptiste Daroussin .func = NULL, 643dcf5eb7SBaptiste Daroussin .ops = &ucl_standartd_emitter_ops[UCL_EMIT_YAML] 65*39ee7a7aSBaptiste Daroussin }, 66*39ee7a7aSBaptiste Daroussin [UCL_EMIT_MSGPACK] = { 67*39ee7a7aSBaptiste Daroussin .name = "msgpack", 68*39ee7a7aSBaptiste Daroussin .id = UCL_EMIT_MSGPACK, 69*39ee7a7aSBaptiste Daroussin .func = NULL, 70*39ee7a7aSBaptiste Daroussin .ops = &ucl_standartd_emitter_ops[UCL_EMIT_MSGPACK] 713dcf5eb7SBaptiste Daroussin } 723dcf5eb7SBaptiste Daroussin }; 733dcf5eb7SBaptiste Daroussin 743dcf5eb7SBaptiste Daroussin /** 753dcf5eb7SBaptiste Daroussin * Get standard emitter context for a specified emit_type 763dcf5eb7SBaptiste Daroussin * @param emit_type type of emitter 773dcf5eb7SBaptiste Daroussin * @return context or NULL if input is invalid 783dcf5eb7SBaptiste Daroussin */ 793dcf5eb7SBaptiste Daroussin const struct ucl_emitter_context * 803dcf5eb7SBaptiste Daroussin ucl_emit_get_standard_context (enum ucl_emitter emit_type) 813dcf5eb7SBaptiste Daroussin { 82*39ee7a7aSBaptiste Daroussin if (emit_type >= UCL_EMIT_JSON && emit_type < UCL_EMIT_MAX) { 833dcf5eb7SBaptiste Daroussin return &ucl_standard_emitters[emit_type]; 843dcf5eb7SBaptiste Daroussin } 853dcf5eb7SBaptiste Daroussin 863dcf5eb7SBaptiste Daroussin return NULL; 873dcf5eb7SBaptiste Daroussin } 883dcf5eb7SBaptiste Daroussin 893dcf5eb7SBaptiste Daroussin /** 903dcf5eb7SBaptiste Daroussin * Serialise string 913dcf5eb7SBaptiste Daroussin * @param str string to emit 923dcf5eb7SBaptiste Daroussin * @param buf target buffer 933dcf5eb7SBaptiste Daroussin */ 943dcf5eb7SBaptiste Daroussin void 953dcf5eb7SBaptiste Daroussin ucl_elt_string_write_json (const char *str, size_t size, 963dcf5eb7SBaptiste Daroussin struct ucl_emitter_context *ctx) 973dcf5eb7SBaptiste Daroussin { 983dcf5eb7SBaptiste Daroussin const char *p = str, *c = str; 993dcf5eb7SBaptiste Daroussin size_t len = 0; 1003dcf5eb7SBaptiste Daroussin const struct ucl_emitter_functions *func = ctx->func; 1013dcf5eb7SBaptiste Daroussin 1023dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_character ('"', 1, func->ud); 1033dcf5eb7SBaptiste Daroussin 1043dcf5eb7SBaptiste Daroussin while (size) { 1053dcf5eb7SBaptiste Daroussin if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) { 1063dcf5eb7SBaptiste Daroussin if (len > 0) { 1073dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_len (c, len, func->ud); 1083dcf5eb7SBaptiste Daroussin } 1093dcf5eb7SBaptiste Daroussin switch (*p) { 1103dcf5eb7SBaptiste Daroussin case '\n': 1113dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_len ("\\n", 2, func->ud); 1123dcf5eb7SBaptiste Daroussin break; 1133dcf5eb7SBaptiste Daroussin case '\r': 1143dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_len ("\\r", 2, func->ud); 1153dcf5eb7SBaptiste Daroussin break; 1163dcf5eb7SBaptiste Daroussin case '\b': 1173dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_len ("\\b", 2, func->ud); 1183dcf5eb7SBaptiste Daroussin break; 1193dcf5eb7SBaptiste Daroussin case '\t': 1203dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_len ("\\t", 2, func->ud); 1213dcf5eb7SBaptiste Daroussin break; 1223dcf5eb7SBaptiste Daroussin case '\f': 1233dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_len ("\\f", 2, func->ud); 1243dcf5eb7SBaptiste Daroussin break; 1253dcf5eb7SBaptiste Daroussin case '\\': 1263dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_len ("\\\\", 2, func->ud); 1273dcf5eb7SBaptiste Daroussin break; 1283dcf5eb7SBaptiste Daroussin case '"': 1293dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_len ("\\\"", 2, func->ud); 1303dcf5eb7SBaptiste Daroussin break; 1313dcf5eb7SBaptiste Daroussin } 1323dcf5eb7SBaptiste Daroussin len = 0; 1333dcf5eb7SBaptiste Daroussin c = ++p; 1343dcf5eb7SBaptiste Daroussin } 1353dcf5eb7SBaptiste Daroussin else { 1363dcf5eb7SBaptiste Daroussin p ++; 1373dcf5eb7SBaptiste Daroussin len ++; 1383dcf5eb7SBaptiste Daroussin } 1393dcf5eb7SBaptiste Daroussin size --; 1403dcf5eb7SBaptiste Daroussin } 1413dcf5eb7SBaptiste Daroussin if (len > 0) { 1423dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_len (c, len, func->ud); 1433dcf5eb7SBaptiste Daroussin } 1443dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_character ('"', 1, func->ud); 1453dcf5eb7SBaptiste Daroussin } 1464bf54857SBaptiste Daroussin 1474bf54857SBaptiste Daroussin void 1484bf54857SBaptiste Daroussin ucl_elt_string_write_multiline (const char *str, size_t size, 1494bf54857SBaptiste Daroussin struct ucl_emitter_context *ctx) 1504bf54857SBaptiste Daroussin { 1514bf54857SBaptiste Daroussin const struct ucl_emitter_functions *func = ctx->func; 1524bf54857SBaptiste Daroussin 1534bf54857SBaptiste Daroussin func->ucl_emitter_append_len ("<<EOD\n", sizeof ("<<EOD\n") - 1, func->ud); 1544bf54857SBaptiste Daroussin func->ucl_emitter_append_len (str, size, func->ud); 1554bf54857SBaptiste Daroussin func->ucl_emitter_append_len ("\nEOD", sizeof ("\nEOD") - 1, func->ud); 1563dcf5eb7SBaptiste Daroussin } 1573dcf5eb7SBaptiste Daroussin 1583dcf5eb7SBaptiste Daroussin /* 1593dcf5eb7SBaptiste Daroussin * Generic utstring output 1603dcf5eb7SBaptiste Daroussin */ 1613dcf5eb7SBaptiste Daroussin static int 1623dcf5eb7SBaptiste Daroussin ucl_utstring_append_character (unsigned char c, size_t len, void *ud) 1633dcf5eb7SBaptiste Daroussin { 1643dcf5eb7SBaptiste Daroussin UT_string *buf = ud; 1653dcf5eb7SBaptiste Daroussin 1663dcf5eb7SBaptiste Daroussin if (len == 1) { 1673dcf5eb7SBaptiste Daroussin utstring_append_c (buf, c); 1683dcf5eb7SBaptiste Daroussin } 1693dcf5eb7SBaptiste Daroussin else { 1704bf54857SBaptiste Daroussin utstring_reserve (buf, len + 1); 1713dcf5eb7SBaptiste Daroussin memset (&buf->d[buf->i], c, len); 1723dcf5eb7SBaptiste Daroussin buf->i += len; 1733dcf5eb7SBaptiste Daroussin buf->d[buf->i] = '\0'; 1743dcf5eb7SBaptiste Daroussin } 1753dcf5eb7SBaptiste Daroussin 1763dcf5eb7SBaptiste Daroussin return 0; 1773dcf5eb7SBaptiste Daroussin } 1783dcf5eb7SBaptiste Daroussin 1793dcf5eb7SBaptiste Daroussin static int 1803dcf5eb7SBaptiste Daroussin ucl_utstring_append_len (const unsigned char *str, size_t len, void *ud) 1813dcf5eb7SBaptiste Daroussin { 1823dcf5eb7SBaptiste Daroussin UT_string *buf = ud; 1833dcf5eb7SBaptiste Daroussin 1843dcf5eb7SBaptiste Daroussin utstring_append_len (buf, str, len); 1853dcf5eb7SBaptiste Daroussin 1863dcf5eb7SBaptiste Daroussin return 0; 1873dcf5eb7SBaptiste Daroussin } 1883dcf5eb7SBaptiste Daroussin 1893dcf5eb7SBaptiste Daroussin static int 1903dcf5eb7SBaptiste Daroussin ucl_utstring_append_int (int64_t val, void *ud) 1913dcf5eb7SBaptiste Daroussin { 1923dcf5eb7SBaptiste Daroussin UT_string *buf = ud; 1933dcf5eb7SBaptiste Daroussin 1943dcf5eb7SBaptiste Daroussin utstring_printf (buf, "%jd", (intmax_t)val); 1953dcf5eb7SBaptiste Daroussin return 0; 1963dcf5eb7SBaptiste Daroussin } 1973dcf5eb7SBaptiste Daroussin 1983dcf5eb7SBaptiste Daroussin static int 1993dcf5eb7SBaptiste Daroussin ucl_utstring_append_double (double val, void *ud) 2003dcf5eb7SBaptiste Daroussin { 2013dcf5eb7SBaptiste Daroussin UT_string *buf = ud; 2023dcf5eb7SBaptiste Daroussin const double delta = 0.0000001; 2033dcf5eb7SBaptiste Daroussin 2043dcf5eb7SBaptiste Daroussin if (val == (double)(int)val) { 2053dcf5eb7SBaptiste Daroussin utstring_printf (buf, "%.1lf", val); 2063dcf5eb7SBaptiste Daroussin } 2073dcf5eb7SBaptiste Daroussin else if (fabs (val - (double)(int)val) < delta) { 2083dcf5eb7SBaptiste Daroussin /* Write at maximum precision */ 2093dcf5eb7SBaptiste Daroussin utstring_printf (buf, "%.*lg", DBL_DIG, val); 2103dcf5eb7SBaptiste Daroussin } 2113dcf5eb7SBaptiste Daroussin else { 2123dcf5eb7SBaptiste Daroussin utstring_printf (buf, "%lf", val); 2133dcf5eb7SBaptiste Daroussin } 2143dcf5eb7SBaptiste Daroussin 2153dcf5eb7SBaptiste Daroussin return 0; 2163dcf5eb7SBaptiste Daroussin } 2173dcf5eb7SBaptiste Daroussin 2183dcf5eb7SBaptiste Daroussin /* 2193dcf5eb7SBaptiste Daroussin * Generic file output 2203dcf5eb7SBaptiste Daroussin */ 2213dcf5eb7SBaptiste Daroussin static int 2223dcf5eb7SBaptiste Daroussin ucl_file_append_character (unsigned char c, size_t len, void *ud) 2233dcf5eb7SBaptiste Daroussin { 2243dcf5eb7SBaptiste Daroussin FILE *fp = ud; 2253dcf5eb7SBaptiste Daroussin 2263dcf5eb7SBaptiste Daroussin while (len --) { 2273dcf5eb7SBaptiste Daroussin fputc (c, fp); 2283dcf5eb7SBaptiste Daroussin } 2293dcf5eb7SBaptiste Daroussin 2303dcf5eb7SBaptiste Daroussin return 0; 2313dcf5eb7SBaptiste Daroussin } 2323dcf5eb7SBaptiste Daroussin 2333dcf5eb7SBaptiste Daroussin static int 2343dcf5eb7SBaptiste Daroussin ucl_file_append_len (const unsigned char *str, size_t len, void *ud) 2353dcf5eb7SBaptiste Daroussin { 2363dcf5eb7SBaptiste Daroussin FILE *fp = ud; 2373dcf5eb7SBaptiste Daroussin 2383dcf5eb7SBaptiste Daroussin fwrite (str, len, 1, fp); 2393dcf5eb7SBaptiste Daroussin 2403dcf5eb7SBaptiste Daroussin return 0; 2413dcf5eb7SBaptiste Daroussin } 2423dcf5eb7SBaptiste Daroussin 2433dcf5eb7SBaptiste Daroussin static int 2443dcf5eb7SBaptiste Daroussin ucl_file_append_int (int64_t val, void *ud) 2453dcf5eb7SBaptiste Daroussin { 2463dcf5eb7SBaptiste Daroussin FILE *fp = ud; 2473dcf5eb7SBaptiste Daroussin 2483dcf5eb7SBaptiste Daroussin fprintf (fp, "%jd", (intmax_t)val); 2493dcf5eb7SBaptiste Daroussin 2503dcf5eb7SBaptiste Daroussin return 0; 2513dcf5eb7SBaptiste Daroussin } 2523dcf5eb7SBaptiste Daroussin 2533dcf5eb7SBaptiste Daroussin static int 2543dcf5eb7SBaptiste Daroussin ucl_file_append_double (double val, void *ud) 2553dcf5eb7SBaptiste Daroussin { 2563dcf5eb7SBaptiste Daroussin FILE *fp = ud; 2573dcf5eb7SBaptiste Daroussin const double delta = 0.0000001; 2583dcf5eb7SBaptiste Daroussin 2593dcf5eb7SBaptiste Daroussin if (val == (double)(int)val) { 2603dcf5eb7SBaptiste Daroussin fprintf (fp, "%.1lf", val); 2613dcf5eb7SBaptiste Daroussin } 2623dcf5eb7SBaptiste Daroussin else if (fabs (val - (double)(int)val) < delta) { 2633dcf5eb7SBaptiste Daroussin /* Write at maximum precision */ 2643dcf5eb7SBaptiste Daroussin fprintf (fp, "%.*lg", DBL_DIG, val); 2653dcf5eb7SBaptiste Daroussin } 2663dcf5eb7SBaptiste Daroussin else { 2673dcf5eb7SBaptiste Daroussin fprintf (fp, "%lf", val); 2683dcf5eb7SBaptiste Daroussin } 2693dcf5eb7SBaptiste Daroussin 2703dcf5eb7SBaptiste Daroussin return 0; 2713dcf5eb7SBaptiste Daroussin } 2723dcf5eb7SBaptiste Daroussin 2733dcf5eb7SBaptiste Daroussin /* 2743dcf5eb7SBaptiste Daroussin * Generic file descriptor writing functions 2753dcf5eb7SBaptiste Daroussin */ 2763dcf5eb7SBaptiste Daroussin static int 2773dcf5eb7SBaptiste Daroussin ucl_fd_append_character (unsigned char c, size_t len, void *ud) 2783dcf5eb7SBaptiste Daroussin { 2793dcf5eb7SBaptiste Daroussin int fd = *(int *)ud; 2803dcf5eb7SBaptiste Daroussin unsigned char *buf; 2813dcf5eb7SBaptiste Daroussin 2823dcf5eb7SBaptiste Daroussin if (len == 1) { 2834bf54857SBaptiste Daroussin return write (fd, &c, 1); 2843dcf5eb7SBaptiste Daroussin } 2853dcf5eb7SBaptiste Daroussin else { 2863dcf5eb7SBaptiste Daroussin buf = malloc (len); 2873dcf5eb7SBaptiste Daroussin if (buf == NULL) { 2883dcf5eb7SBaptiste Daroussin /* Fallback */ 2893dcf5eb7SBaptiste Daroussin while (len --) { 2904bf54857SBaptiste Daroussin if (write (fd, &c, 1) == -1) { 2914bf54857SBaptiste Daroussin return -1; 2924bf54857SBaptiste Daroussin } 2933dcf5eb7SBaptiste Daroussin } 2943dcf5eb7SBaptiste Daroussin } 2953dcf5eb7SBaptiste Daroussin else { 2963dcf5eb7SBaptiste Daroussin memset (buf, c, len); 2974bf54857SBaptiste Daroussin if (write (fd, buf, len) == -1) { 2988e3b1ab2SBaptiste Daroussin free(buf); 2994bf54857SBaptiste Daroussin return -1; 3004bf54857SBaptiste Daroussin } 3013dcf5eb7SBaptiste Daroussin free (buf); 3023dcf5eb7SBaptiste Daroussin } 3033dcf5eb7SBaptiste Daroussin } 3043dcf5eb7SBaptiste Daroussin 3053dcf5eb7SBaptiste Daroussin return 0; 3063dcf5eb7SBaptiste Daroussin } 3073dcf5eb7SBaptiste Daroussin 3083dcf5eb7SBaptiste Daroussin static int 3093dcf5eb7SBaptiste Daroussin ucl_fd_append_len (const unsigned char *str, size_t len, void *ud) 3103dcf5eb7SBaptiste Daroussin { 3113dcf5eb7SBaptiste Daroussin int fd = *(int *)ud; 3123dcf5eb7SBaptiste Daroussin 3134bf54857SBaptiste Daroussin return write (fd, str, len); 3143dcf5eb7SBaptiste Daroussin } 3153dcf5eb7SBaptiste Daroussin 3163dcf5eb7SBaptiste Daroussin static int 3173dcf5eb7SBaptiste Daroussin ucl_fd_append_int (int64_t val, void *ud) 3183dcf5eb7SBaptiste Daroussin { 3193dcf5eb7SBaptiste Daroussin int fd = *(int *)ud; 3203dcf5eb7SBaptiste Daroussin char intbuf[64]; 3213dcf5eb7SBaptiste Daroussin 3223dcf5eb7SBaptiste Daroussin snprintf (intbuf, sizeof (intbuf), "%jd", (intmax_t)val); 3234bf54857SBaptiste Daroussin return write (fd, intbuf, strlen (intbuf)); 3243dcf5eb7SBaptiste Daroussin } 3253dcf5eb7SBaptiste Daroussin 3263dcf5eb7SBaptiste Daroussin static int 3273dcf5eb7SBaptiste Daroussin ucl_fd_append_double (double val, void *ud) 3283dcf5eb7SBaptiste Daroussin { 3293dcf5eb7SBaptiste Daroussin int fd = *(int *)ud; 3303dcf5eb7SBaptiste Daroussin const double delta = 0.0000001; 3313dcf5eb7SBaptiste Daroussin char nbuf[64]; 3323dcf5eb7SBaptiste Daroussin 3333dcf5eb7SBaptiste Daroussin if (val == (double)(int)val) { 3343dcf5eb7SBaptiste Daroussin snprintf (nbuf, sizeof (nbuf), "%.1lf", val); 3353dcf5eb7SBaptiste Daroussin } 3363dcf5eb7SBaptiste Daroussin else if (fabs (val - (double)(int)val) < delta) { 3373dcf5eb7SBaptiste Daroussin /* Write at maximum precision */ 3383dcf5eb7SBaptiste Daroussin snprintf (nbuf, sizeof (nbuf), "%.*lg", DBL_DIG, val); 3393dcf5eb7SBaptiste Daroussin } 3403dcf5eb7SBaptiste Daroussin else { 3413dcf5eb7SBaptiste Daroussin snprintf (nbuf, sizeof (nbuf), "%lf", val); 3423dcf5eb7SBaptiste Daroussin } 3433dcf5eb7SBaptiste Daroussin 3444bf54857SBaptiste Daroussin return write (fd, nbuf, strlen (nbuf)); 3453dcf5eb7SBaptiste Daroussin } 3463dcf5eb7SBaptiste Daroussin 3473dcf5eb7SBaptiste Daroussin struct ucl_emitter_functions* 3483dcf5eb7SBaptiste Daroussin ucl_object_emit_memory_funcs (void **pmem) 3493dcf5eb7SBaptiste Daroussin { 3503dcf5eb7SBaptiste Daroussin struct ucl_emitter_functions *f; 3513dcf5eb7SBaptiste Daroussin UT_string *s; 3523dcf5eb7SBaptiste Daroussin 3533dcf5eb7SBaptiste Daroussin f = calloc (1, sizeof (*f)); 3543dcf5eb7SBaptiste Daroussin 3553dcf5eb7SBaptiste Daroussin if (f != NULL) { 3563dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_character = ucl_utstring_append_character; 3573dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_double = ucl_utstring_append_double; 3583dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_int = ucl_utstring_append_int; 3593dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_len = ucl_utstring_append_len; 3603dcf5eb7SBaptiste Daroussin f->ucl_emitter_free_func = free; 3613dcf5eb7SBaptiste Daroussin utstring_new (s); 3623dcf5eb7SBaptiste Daroussin f->ud = s; 3633dcf5eb7SBaptiste Daroussin *pmem = s->d; 3643dcf5eb7SBaptiste Daroussin s->pd = pmem; 3653dcf5eb7SBaptiste Daroussin } 3663dcf5eb7SBaptiste Daroussin 3673dcf5eb7SBaptiste Daroussin return f; 3683dcf5eb7SBaptiste Daroussin } 3693dcf5eb7SBaptiste Daroussin 3703dcf5eb7SBaptiste Daroussin struct ucl_emitter_functions* 3713dcf5eb7SBaptiste Daroussin ucl_object_emit_file_funcs (FILE *fp) 3723dcf5eb7SBaptiste Daroussin { 3733dcf5eb7SBaptiste Daroussin struct ucl_emitter_functions *f; 3743dcf5eb7SBaptiste Daroussin 3753dcf5eb7SBaptiste Daroussin f = calloc (1, sizeof (*f)); 3763dcf5eb7SBaptiste Daroussin 3773dcf5eb7SBaptiste Daroussin if (f != NULL) { 3783dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_character = ucl_file_append_character; 3793dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_double = ucl_file_append_double; 3803dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_int = ucl_file_append_int; 3813dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_len = ucl_file_append_len; 3823dcf5eb7SBaptiste Daroussin f->ucl_emitter_free_func = NULL; 3833dcf5eb7SBaptiste Daroussin f->ud = fp; 3843dcf5eb7SBaptiste Daroussin } 3853dcf5eb7SBaptiste Daroussin 3863dcf5eb7SBaptiste Daroussin return f; 3873dcf5eb7SBaptiste Daroussin } 3883dcf5eb7SBaptiste Daroussin 3893dcf5eb7SBaptiste Daroussin struct ucl_emitter_functions* 3903dcf5eb7SBaptiste Daroussin ucl_object_emit_fd_funcs (int fd) 3913dcf5eb7SBaptiste Daroussin { 3923dcf5eb7SBaptiste Daroussin struct ucl_emitter_functions *f; 3933dcf5eb7SBaptiste Daroussin int *ip; 3943dcf5eb7SBaptiste Daroussin 3953dcf5eb7SBaptiste Daroussin f = calloc (1, sizeof (*f)); 3963dcf5eb7SBaptiste Daroussin 3973dcf5eb7SBaptiste Daroussin if (f != NULL) { 3983dcf5eb7SBaptiste Daroussin ip = malloc (sizeof (fd)); 3993dcf5eb7SBaptiste Daroussin if (ip == NULL) { 4003dcf5eb7SBaptiste Daroussin free (f); 4013dcf5eb7SBaptiste Daroussin return NULL; 4023dcf5eb7SBaptiste Daroussin } 4033dcf5eb7SBaptiste Daroussin 4043dcf5eb7SBaptiste Daroussin memcpy (ip, &fd, sizeof (fd)); 4053dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_character = ucl_fd_append_character; 4063dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_double = ucl_fd_append_double; 4073dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_int = ucl_fd_append_int; 4083dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_len = ucl_fd_append_len; 4093dcf5eb7SBaptiste Daroussin f->ucl_emitter_free_func = free; 4103dcf5eb7SBaptiste Daroussin f->ud = ip; 4113dcf5eb7SBaptiste Daroussin } 4123dcf5eb7SBaptiste Daroussin 4133dcf5eb7SBaptiste Daroussin return f; 4143dcf5eb7SBaptiste Daroussin } 4153dcf5eb7SBaptiste Daroussin 4163dcf5eb7SBaptiste Daroussin void 4173dcf5eb7SBaptiste Daroussin ucl_object_emit_funcs_free (struct ucl_emitter_functions *f) 4183dcf5eb7SBaptiste Daroussin { 4193dcf5eb7SBaptiste Daroussin if (f != NULL) { 4203dcf5eb7SBaptiste Daroussin if (f->ucl_emitter_free_func != NULL) { 4213dcf5eb7SBaptiste Daroussin f->ucl_emitter_free_func (f->ud); 4223dcf5eb7SBaptiste Daroussin } 4233dcf5eb7SBaptiste Daroussin free (f); 4243dcf5eb7SBaptiste Daroussin } 4253dcf5eb7SBaptiste Daroussin } 4263dcf5eb7SBaptiste Daroussin 4273dcf5eb7SBaptiste Daroussin 4283dcf5eb7SBaptiste Daroussin unsigned char * 4293dcf5eb7SBaptiste Daroussin ucl_object_emit_single_json (const ucl_object_t *obj) 4303dcf5eb7SBaptiste Daroussin { 4313dcf5eb7SBaptiste Daroussin UT_string *buf = NULL; 4323dcf5eb7SBaptiste Daroussin unsigned char *res = NULL; 4333dcf5eb7SBaptiste Daroussin 4343dcf5eb7SBaptiste Daroussin if (obj == NULL) { 4353dcf5eb7SBaptiste Daroussin return NULL; 4363dcf5eb7SBaptiste Daroussin } 4373dcf5eb7SBaptiste Daroussin 4383dcf5eb7SBaptiste Daroussin utstring_new (buf); 4393dcf5eb7SBaptiste Daroussin 4403dcf5eb7SBaptiste Daroussin if (buf != NULL) { 4413dcf5eb7SBaptiste Daroussin switch (obj->type) { 4423dcf5eb7SBaptiste Daroussin case UCL_OBJECT: 4433dcf5eb7SBaptiste Daroussin ucl_utstring_append_len ("object", 6, buf); 4443dcf5eb7SBaptiste Daroussin break; 4453dcf5eb7SBaptiste Daroussin case UCL_ARRAY: 4463dcf5eb7SBaptiste Daroussin ucl_utstring_append_len ("array", 5, buf); 4473dcf5eb7SBaptiste Daroussin break; 4483dcf5eb7SBaptiste Daroussin case UCL_INT: 4493dcf5eb7SBaptiste Daroussin ucl_utstring_append_int (obj->value.iv, buf); 4503dcf5eb7SBaptiste Daroussin break; 4513dcf5eb7SBaptiste Daroussin case UCL_FLOAT: 4523dcf5eb7SBaptiste Daroussin case UCL_TIME: 4533dcf5eb7SBaptiste Daroussin ucl_utstring_append_double (obj->value.dv, buf); 4543dcf5eb7SBaptiste Daroussin break; 4553dcf5eb7SBaptiste Daroussin case UCL_NULL: 4563dcf5eb7SBaptiste Daroussin ucl_utstring_append_len ("null", 4, buf); 4573dcf5eb7SBaptiste Daroussin break; 4583dcf5eb7SBaptiste Daroussin case UCL_BOOLEAN: 4593dcf5eb7SBaptiste Daroussin if (obj->value.iv) { 4603dcf5eb7SBaptiste Daroussin ucl_utstring_append_len ("true", 4, buf); 4613dcf5eb7SBaptiste Daroussin } 4623dcf5eb7SBaptiste Daroussin else { 4633dcf5eb7SBaptiste Daroussin ucl_utstring_append_len ("false", 5, buf); 4643dcf5eb7SBaptiste Daroussin } 4653dcf5eb7SBaptiste Daroussin break; 4663dcf5eb7SBaptiste Daroussin case UCL_STRING: 4673dcf5eb7SBaptiste Daroussin ucl_utstring_append_len (obj->value.sv, obj->len, buf); 4683dcf5eb7SBaptiste Daroussin break; 4693dcf5eb7SBaptiste Daroussin case UCL_USERDATA: 4703dcf5eb7SBaptiste Daroussin ucl_utstring_append_len ("userdata", 8, buf); 4713dcf5eb7SBaptiste Daroussin break; 4723dcf5eb7SBaptiste Daroussin } 4733dcf5eb7SBaptiste Daroussin res = utstring_body (buf); 4743dcf5eb7SBaptiste Daroussin free (buf); 4753dcf5eb7SBaptiste Daroussin } 4763dcf5eb7SBaptiste Daroussin 4773dcf5eb7SBaptiste Daroussin return res; 4783dcf5eb7SBaptiste Daroussin } 4794bf54857SBaptiste Daroussin 4804bf54857SBaptiste Daroussin #define LONG_STRING_LIMIT 80 4814bf54857SBaptiste Daroussin 4824bf54857SBaptiste Daroussin bool 4834bf54857SBaptiste Daroussin ucl_maybe_long_string (const ucl_object_t *obj) 4844bf54857SBaptiste Daroussin { 4854bf54857SBaptiste Daroussin if (obj->len > LONG_STRING_LIMIT || (obj->flags & UCL_OBJECT_MULTILINE)) { 4864bf54857SBaptiste Daroussin /* String is long enough, so search for newline characters in it */ 4874bf54857SBaptiste Daroussin if (memchr (obj->value.sv, '\n', obj->len) != NULL) { 4884bf54857SBaptiste Daroussin return true; 4894bf54857SBaptiste Daroussin } 4904bf54857SBaptiste Daroussin } 4914bf54857SBaptiste Daroussin 4924bf54857SBaptiste Daroussin return false; 4934bf54857SBaptiste Daroussin } 494