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] 6539ee7a7aSBaptiste Daroussin }, 6639ee7a7aSBaptiste Daroussin [UCL_EMIT_MSGPACK] = { 6739ee7a7aSBaptiste Daroussin .name = "msgpack", 6839ee7a7aSBaptiste Daroussin .id = UCL_EMIT_MSGPACK, 6939ee7a7aSBaptiste Daroussin .func = NULL, 7039ee7a7aSBaptiste 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 { 8239ee7a7aSBaptiste 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) { 105*11dd9ed6SBaptiste Daroussin if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE|UCL_CHARACTER_DENIED)) { 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; 131*11dd9ed6SBaptiste Daroussin default: 132*11dd9ed6SBaptiste Daroussin /* Emit unicode unknown character */ 133*11dd9ed6SBaptiste Daroussin func->ucl_emitter_append_len ("\\uFFFD", 5, func->ud); 134*11dd9ed6SBaptiste Daroussin break; 1353dcf5eb7SBaptiste Daroussin } 1363dcf5eb7SBaptiste Daroussin len = 0; 1373dcf5eb7SBaptiste Daroussin c = ++p; 1383dcf5eb7SBaptiste Daroussin } 1393dcf5eb7SBaptiste Daroussin else { 1403dcf5eb7SBaptiste Daroussin p ++; 1413dcf5eb7SBaptiste Daroussin len ++; 1423dcf5eb7SBaptiste Daroussin } 1433dcf5eb7SBaptiste Daroussin size --; 1443dcf5eb7SBaptiste Daroussin } 145*11dd9ed6SBaptiste Daroussin 1463dcf5eb7SBaptiste Daroussin if (len > 0) { 1473dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_len (c, len, func->ud); 1483dcf5eb7SBaptiste Daroussin } 149*11dd9ed6SBaptiste Daroussin 1503dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_character ('"', 1, func->ud); 1513dcf5eb7SBaptiste Daroussin } 1524bf54857SBaptiste Daroussin 1534bf54857SBaptiste Daroussin void 1544bf54857SBaptiste Daroussin ucl_elt_string_write_multiline (const char *str, size_t size, 1554bf54857SBaptiste Daroussin struct ucl_emitter_context *ctx) 1564bf54857SBaptiste Daroussin { 1574bf54857SBaptiste Daroussin const struct ucl_emitter_functions *func = ctx->func; 1584bf54857SBaptiste Daroussin 1594bf54857SBaptiste Daroussin func->ucl_emitter_append_len ("<<EOD\n", sizeof ("<<EOD\n") - 1, func->ud); 1604bf54857SBaptiste Daroussin func->ucl_emitter_append_len (str, size, func->ud); 1614bf54857SBaptiste Daroussin func->ucl_emitter_append_len ("\nEOD", sizeof ("\nEOD") - 1, func->ud); 1623dcf5eb7SBaptiste Daroussin } 1633dcf5eb7SBaptiste Daroussin 1643dcf5eb7SBaptiste Daroussin /* 1653dcf5eb7SBaptiste Daroussin * Generic utstring output 1663dcf5eb7SBaptiste Daroussin */ 1673dcf5eb7SBaptiste Daroussin static int 1683dcf5eb7SBaptiste Daroussin ucl_utstring_append_character (unsigned char c, size_t len, void *ud) 1693dcf5eb7SBaptiste Daroussin { 1703dcf5eb7SBaptiste Daroussin UT_string *buf = ud; 1713dcf5eb7SBaptiste Daroussin 1723dcf5eb7SBaptiste Daroussin if (len == 1) { 1733dcf5eb7SBaptiste Daroussin utstring_append_c (buf, c); 1743dcf5eb7SBaptiste Daroussin } 1753dcf5eb7SBaptiste Daroussin else { 1764bf54857SBaptiste Daroussin utstring_reserve (buf, len + 1); 1773dcf5eb7SBaptiste Daroussin memset (&buf->d[buf->i], c, len); 1783dcf5eb7SBaptiste Daroussin buf->i += len; 1793dcf5eb7SBaptiste Daroussin buf->d[buf->i] = '\0'; 1803dcf5eb7SBaptiste Daroussin } 1813dcf5eb7SBaptiste Daroussin 1823dcf5eb7SBaptiste Daroussin return 0; 1833dcf5eb7SBaptiste Daroussin } 1843dcf5eb7SBaptiste Daroussin 1853dcf5eb7SBaptiste Daroussin static int 1863dcf5eb7SBaptiste Daroussin ucl_utstring_append_len (const unsigned char *str, size_t len, void *ud) 1873dcf5eb7SBaptiste Daroussin { 1883dcf5eb7SBaptiste Daroussin UT_string *buf = ud; 1893dcf5eb7SBaptiste Daroussin 1903dcf5eb7SBaptiste Daroussin utstring_append_len (buf, str, len); 1913dcf5eb7SBaptiste Daroussin 1923dcf5eb7SBaptiste Daroussin return 0; 1933dcf5eb7SBaptiste Daroussin } 1943dcf5eb7SBaptiste Daroussin 1953dcf5eb7SBaptiste Daroussin static int 1963dcf5eb7SBaptiste Daroussin ucl_utstring_append_int (int64_t val, void *ud) 1973dcf5eb7SBaptiste Daroussin { 1983dcf5eb7SBaptiste Daroussin UT_string *buf = ud; 1993dcf5eb7SBaptiste Daroussin 2003dcf5eb7SBaptiste Daroussin utstring_printf (buf, "%jd", (intmax_t)val); 2013dcf5eb7SBaptiste Daroussin return 0; 2023dcf5eb7SBaptiste Daroussin } 2033dcf5eb7SBaptiste Daroussin 2043dcf5eb7SBaptiste Daroussin static int 2053dcf5eb7SBaptiste Daroussin ucl_utstring_append_double (double val, void *ud) 2063dcf5eb7SBaptiste Daroussin { 2073dcf5eb7SBaptiste Daroussin UT_string *buf = ud; 2083dcf5eb7SBaptiste Daroussin const double delta = 0.0000001; 2093dcf5eb7SBaptiste Daroussin 2103dcf5eb7SBaptiste Daroussin if (val == (double)(int)val) { 2113dcf5eb7SBaptiste Daroussin utstring_printf (buf, "%.1lf", val); 2123dcf5eb7SBaptiste Daroussin } 2133dcf5eb7SBaptiste Daroussin else if (fabs (val - (double)(int)val) < delta) { 2143dcf5eb7SBaptiste Daroussin /* Write at maximum precision */ 2153dcf5eb7SBaptiste Daroussin utstring_printf (buf, "%.*lg", DBL_DIG, val); 2163dcf5eb7SBaptiste Daroussin } 2173dcf5eb7SBaptiste Daroussin else { 2183dcf5eb7SBaptiste Daroussin utstring_printf (buf, "%lf", val); 2193dcf5eb7SBaptiste Daroussin } 2203dcf5eb7SBaptiste Daroussin 2213dcf5eb7SBaptiste Daroussin return 0; 2223dcf5eb7SBaptiste Daroussin } 2233dcf5eb7SBaptiste Daroussin 2243dcf5eb7SBaptiste Daroussin /* 2253dcf5eb7SBaptiste Daroussin * Generic file output 2263dcf5eb7SBaptiste Daroussin */ 2273dcf5eb7SBaptiste Daroussin static int 2283dcf5eb7SBaptiste Daroussin ucl_file_append_character (unsigned char c, size_t len, void *ud) 2293dcf5eb7SBaptiste Daroussin { 2303dcf5eb7SBaptiste Daroussin FILE *fp = ud; 2313dcf5eb7SBaptiste Daroussin 2323dcf5eb7SBaptiste Daroussin while (len --) { 2333dcf5eb7SBaptiste Daroussin fputc (c, fp); 2343dcf5eb7SBaptiste Daroussin } 2353dcf5eb7SBaptiste Daroussin 2363dcf5eb7SBaptiste Daroussin return 0; 2373dcf5eb7SBaptiste Daroussin } 2383dcf5eb7SBaptiste Daroussin 2393dcf5eb7SBaptiste Daroussin static int 2403dcf5eb7SBaptiste Daroussin ucl_file_append_len (const unsigned char *str, size_t len, void *ud) 2413dcf5eb7SBaptiste Daroussin { 2423dcf5eb7SBaptiste Daroussin FILE *fp = ud; 2433dcf5eb7SBaptiste Daroussin 2443dcf5eb7SBaptiste Daroussin fwrite (str, len, 1, fp); 2453dcf5eb7SBaptiste Daroussin 2463dcf5eb7SBaptiste Daroussin return 0; 2473dcf5eb7SBaptiste Daroussin } 2483dcf5eb7SBaptiste Daroussin 2493dcf5eb7SBaptiste Daroussin static int 2503dcf5eb7SBaptiste Daroussin ucl_file_append_int (int64_t val, void *ud) 2513dcf5eb7SBaptiste Daroussin { 2523dcf5eb7SBaptiste Daroussin FILE *fp = ud; 2533dcf5eb7SBaptiste Daroussin 2543dcf5eb7SBaptiste Daroussin fprintf (fp, "%jd", (intmax_t)val); 2553dcf5eb7SBaptiste Daroussin 2563dcf5eb7SBaptiste Daroussin return 0; 2573dcf5eb7SBaptiste Daroussin } 2583dcf5eb7SBaptiste Daroussin 2593dcf5eb7SBaptiste Daroussin static int 2603dcf5eb7SBaptiste Daroussin ucl_file_append_double (double val, void *ud) 2613dcf5eb7SBaptiste Daroussin { 2623dcf5eb7SBaptiste Daroussin FILE *fp = ud; 2633dcf5eb7SBaptiste Daroussin const double delta = 0.0000001; 2643dcf5eb7SBaptiste Daroussin 2653dcf5eb7SBaptiste Daroussin if (val == (double)(int)val) { 2663dcf5eb7SBaptiste Daroussin fprintf (fp, "%.1lf", val); 2673dcf5eb7SBaptiste Daroussin } 2683dcf5eb7SBaptiste Daroussin else if (fabs (val - (double)(int)val) < delta) { 2693dcf5eb7SBaptiste Daroussin /* Write at maximum precision */ 2703dcf5eb7SBaptiste Daroussin fprintf (fp, "%.*lg", DBL_DIG, val); 2713dcf5eb7SBaptiste Daroussin } 2723dcf5eb7SBaptiste Daroussin else { 2733dcf5eb7SBaptiste Daroussin fprintf (fp, "%lf", val); 2743dcf5eb7SBaptiste Daroussin } 2753dcf5eb7SBaptiste Daroussin 2763dcf5eb7SBaptiste Daroussin return 0; 2773dcf5eb7SBaptiste Daroussin } 2783dcf5eb7SBaptiste Daroussin 2793dcf5eb7SBaptiste Daroussin /* 2803dcf5eb7SBaptiste Daroussin * Generic file descriptor writing functions 2813dcf5eb7SBaptiste Daroussin */ 2823dcf5eb7SBaptiste Daroussin static int 2833dcf5eb7SBaptiste Daroussin ucl_fd_append_character (unsigned char c, size_t len, void *ud) 2843dcf5eb7SBaptiste Daroussin { 2853dcf5eb7SBaptiste Daroussin int fd = *(int *)ud; 2863dcf5eb7SBaptiste Daroussin unsigned char *buf; 2873dcf5eb7SBaptiste Daroussin 2883dcf5eb7SBaptiste Daroussin if (len == 1) { 2894bf54857SBaptiste Daroussin return write (fd, &c, 1); 2903dcf5eb7SBaptiste Daroussin } 2913dcf5eb7SBaptiste Daroussin else { 2923dcf5eb7SBaptiste Daroussin buf = malloc (len); 2933dcf5eb7SBaptiste Daroussin if (buf == NULL) { 2943dcf5eb7SBaptiste Daroussin /* Fallback */ 2953dcf5eb7SBaptiste Daroussin while (len --) { 2964bf54857SBaptiste Daroussin if (write (fd, &c, 1) == -1) { 2974bf54857SBaptiste Daroussin return -1; 2984bf54857SBaptiste Daroussin } 2993dcf5eb7SBaptiste Daroussin } 3003dcf5eb7SBaptiste Daroussin } 3013dcf5eb7SBaptiste Daroussin else { 3023dcf5eb7SBaptiste Daroussin memset (buf, c, len); 3034bf54857SBaptiste Daroussin if (write (fd, buf, len) == -1) { 3048e3b1ab2SBaptiste Daroussin free(buf); 3054bf54857SBaptiste Daroussin return -1; 3064bf54857SBaptiste Daroussin } 3073dcf5eb7SBaptiste Daroussin free (buf); 3083dcf5eb7SBaptiste Daroussin } 3093dcf5eb7SBaptiste Daroussin } 3103dcf5eb7SBaptiste Daroussin 3113dcf5eb7SBaptiste Daroussin return 0; 3123dcf5eb7SBaptiste Daroussin } 3133dcf5eb7SBaptiste Daroussin 3143dcf5eb7SBaptiste Daroussin static int 3153dcf5eb7SBaptiste Daroussin ucl_fd_append_len (const unsigned char *str, size_t len, void *ud) 3163dcf5eb7SBaptiste Daroussin { 3173dcf5eb7SBaptiste Daroussin int fd = *(int *)ud; 3183dcf5eb7SBaptiste Daroussin 3194bf54857SBaptiste Daroussin return write (fd, str, len); 3203dcf5eb7SBaptiste Daroussin } 3213dcf5eb7SBaptiste Daroussin 3223dcf5eb7SBaptiste Daroussin static int 3233dcf5eb7SBaptiste Daroussin ucl_fd_append_int (int64_t val, void *ud) 3243dcf5eb7SBaptiste Daroussin { 3253dcf5eb7SBaptiste Daroussin int fd = *(int *)ud; 3263dcf5eb7SBaptiste Daroussin char intbuf[64]; 3273dcf5eb7SBaptiste Daroussin 3283dcf5eb7SBaptiste Daroussin snprintf (intbuf, sizeof (intbuf), "%jd", (intmax_t)val); 3294bf54857SBaptiste Daroussin return write (fd, intbuf, strlen (intbuf)); 3303dcf5eb7SBaptiste Daroussin } 3313dcf5eb7SBaptiste Daroussin 3323dcf5eb7SBaptiste Daroussin static int 3333dcf5eb7SBaptiste Daroussin ucl_fd_append_double (double val, void *ud) 3343dcf5eb7SBaptiste Daroussin { 3353dcf5eb7SBaptiste Daroussin int fd = *(int *)ud; 3363dcf5eb7SBaptiste Daroussin const double delta = 0.0000001; 3373dcf5eb7SBaptiste Daroussin char nbuf[64]; 3383dcf5eb7SBaptiste Daroussin 3393dcf5eb7SBaptiste Daroussin if (val == (double)(int)val) { 3403dcf5eb7SBaptiste Daroussin snprintf (nbuf, sizeof (nbuf), "%.1lf", val); 3413dcf5eb7SBaptiste Daroussin } 3423dcf5eb7SBaptiste Daroussin else if (fabs (val - (double)(int)val) < delta) { 3433dcf5eb7SBaptiste Daroussin /* Write at maximum precision */ 3443dcf5eb7SBaptiste Daroussin snprintf (nbuf, sizeof (nbuf), "%.*lg", DBL_DIG, val); 3453dcf5eb7SBaptiste Daroussin } 3463dcf5eb7SBaptiste Daroussin else { 3473dcf5eb7SBaptiste Daroussin snprintf (nbuf, sizeof (nbuf), "%lf", val); 3483dcf5eb7SBaptiste Daroussin } 3493dcf5eb7SBaptiste Daroussin 3504bf54857SBaptiste Daroussin return write (fd, nbuf, strlen (nbuf)); 3513dcf5eb7SBaptiste Daroussin } 3523dcf5eb7SBaptiste Daroussin 3533dcf5eb7SBaptiste Daroussin struct ucl_emitter_functions* 3543dcf5eb7SBaptiste Daroussin ucl_object_emit_memory_funcs (void **pmem) 3553dcf5eb7SBaptiste Daroussin { 3563dcf5eb7SBaptiste Daroussin struct ucl_emitter_functions *f; 3573dcf5eb7SBaptiste Daroussin UT_string *s; 3583dcf5eb7SBaptiste Daroussin 3593dcf5eb7SBaptiste Daroussin f = calloc (1, sizeof (*f)); 3603dcf5eb7SBaptiste Daroussin 3613dcf5eb7SBaptiste Daroussin if (f != NULL) { 3623dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_character = ucl_utstring_append_character; 3633dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_double = ucl_utstring_append_double; 3643dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_int = ucl_utstring_append_int; 3653dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_len = ucl_utstring_append_len; 3663dcf5eb7SBaptiste Daroussin f->ucl_emitter_free_func = free; 3673dcf5eb7SBaptiste Daroussin utstring_new (s); 3683dcf5eb7SBaptiste Daroussin f->ud = s; 3693dcf5eb7SBaptiste Daroussin *pmem = s->d; 3703dcf5eb7SBaptiste Daroussin s->pd = pmem; 3713dcf5eb7SBaptiste Daroussin } 3723dcf5eb7SBaptiste Daroussin 3733dcf5eb7SBaptiste Daroussin return f; 3743dcf5eb7SBaptiste Daroussin } 3753dcf5eb7SBaptiste Daroussin 3763dcf5eb7SBaptiste Daroussin struct ucl_emitter_functions* 3773dcf5eb7SBaptiste Daroussin ucl_object_emit_file_funcs (FILE *fp) 3783dcf5eb7SBaptiste Daroussin { 3793dcf5eb7SBaptiste Daroussin struct ucl_emitter_functions *f; 3803dcf5eb7SBaptiste Daroussin 3813dcf5eb7SBaptiste Daroussin f = calloc (1, sizeof (*f)); 3823dcf5eb7SBaptiste Daroussin 3833dcf5eb7SBaptiste Daroussin if (f != NULL) { 3843dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_character = ucl_file_append_character; 3853dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_double = ucl_file_append_double; 3863dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_int = ucl_file_append_int; 3873dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_len = ucl_file_append_len; 3883dcf5eb7SBaptiste Daroussin f->ucl_emitter_free_func = NULL; 3893dcf5eb7SBaptiste Daroussin f->ud = fp; 3903dcf5eb7SBaptiste Daroussin } 3913dcf5eb7SBaptiste Daroussin 3923dcf5eb7SBaptiste Daroussin return f; 3933dcf5eb7SBaptiste Daroussin } 3943dcf5eb7SBaptiste Daroussin 3953dcf5eb7SBaptiste Daroussin struct ucl_emitter_functions* 3963dcf5eb7SBaptiste Daroussin ucl_object_emit_fd_funcs (int fd) 3973dcf5eb7SBaptiste Daroussin { 3983dcf5eb7SBaptiste Daroussin struct ucl_emitter_functions *f; 3993dcf5eb7SBaptiste Daroussin int *ip; 4003dcf5eb7SBaptiste Daroussin 4013dcf5eb7SBaptiste Daroussin f = calloc (1, sizeof (*f)); 4023dcf5eb7SBaptiste Daroussin 4033dcf5eb7SBaptiste Daroussin if (f != NULL) { 4043dcf5eb7SBaptiste Daroussin ip = malloc (sizeof (fd)); 4053dcf5eb7SBaptiste Daroussin if (ip == NULL) { 4063dcf5eb7SBaptiste Daroussin free (f); 4073dcf5eb7SBaptiste Daroussin return NULL; 4083dcf5eb7SBaptiste Daroussin } 4093dcf5eb7SBaptiste Daroussin 4103dcf5eb7SBaptiste Daroussin memcpy (ip, &fd, sizeof (fd)); 4113dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_character = ucl_fd_append_character; 4123dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_double = ucl_fd_append_double; 4133dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_int = ucl_fd_append_int; 4143dcf5eb7SBaptiste Daroussin f->ucl_emitter_append_len = ucl_fd_append_len; 4153dcf5eb7SBaptiste Daroussin f->ucl_emitter_free_func = free; 4163dcf5eb7SBaptiste Daroussin f->ud = ip; 4173dcf5eb7SBaptiste Daroussin } 4183dcf5eb7SBaptiste Daroussin 4193dcf5eb7SBaptiste Daroussin return f; 4203dcf5eb7SBaptiste Daroussin } 4213dcf5eb7SBaptiste Daroussin 4223dcf5eb7SBaptiste Daroussin void 4233dcf5eb7SBaptiste Daroussin ucl_object_emit_funcs_free (struct ucl_emitter_functions *f) 4243dcf5eb7SBaptiste Daroussin { 4253dcf5eb7SBaptiste Daroussin if (f != NULL) { 4263dcf5eb7SBaptiste Daroussin if (f->ucl_emitter_free_func != NULL) { 4273dcf5eb7SBaptiste Daroussin f->ucl_emitter_free_func (f->ud); 4283dcf5eb7SBaptiste Daroussin } 4293dcf5eb7SBaptiste Daroussin free (f); 4303dcf5eb7SBaptiste Daroussin } 4313dcf5eb7SBaptiste Daroussin } 4323dcf5eb7SBaptiste Daroussin 4333dcf5eb7SBaptiste Daroussin 4343dcf5eb7SBaptiste Daroussin unsigned char * 4353dcf5eb7SBaptiste Daroussin ucl_object_emit_single_json (const ucl_object_t *obj) 4363dcf5eb7SBaptiste Daroussin { 4373dcf5eb7SBaptiste Daroussin UT_string *buf = NULL; 4383dcf5eb7SBaptiste Daroussin unsigned char *res = NULL; 4393dcf5eb7SBaptiste Daroussin 4403dcf5eb7SBaptiste Daroussin if (obj == NULL) { 4413dcf5eb7SBaptiste Daroussin return NULL; 4423dcf5eb7SBaptiste Daroussin } 4433dcf5eb7SBaptiste Daroussin 4443dcf5eb7SBaptiste Daroussin utstring_new (buf); 4453dcf5eb7SBaptiste Daroussin 4463dcf5eb7SBaptiste Daroussin if (buf != NULL) { 4473dcf5eb7SBaptiste Daroussin switch (obj->type) { 4483dcf5eb7SBaptiste Daroussin case UCL_OBJECT: 4493dcf5eb7SBaptiste Daroussin ucl_utstring_append_len ("object", 6, buf); 4503dcf5eb7SBaptiste Daroussin break; 4513dcf5eb7SBaptiste Daroussin case UCL_ARRAY: 4523dcf5eb7SBaptiste Daroussin ucl_utstring_append_len ("array", 5, buf); 4533dcf5eb7SBaptiste Daroussin break; 4543dcf5eb7SBaptiste Daroussin case UCL_INT: 4553dcf5eb7SBaptiste Daroussin ucl_utstring_append_int (obj->value.iv, buf); 4563dcf5eb7SBaptiste Daroussin break; 4573dcf5eb7SBaptiste Daroussin case UCL_FLOAT: 4583dcf5eb7SBaptiste Daroussin case UCL_TIME: 4593dcf5eb7SBaptiste Daroussin ucl_utstring_append_double (obj->value.dv, buf); 4603dcf5eb7SBaptiste Daroussin break; 4613dcf5eb7SBaptiste Daroussin case UCL_NULL: 4623dcf5eb7SBaptiste Daroussin ucl_utstring_append_len ("null", 4, buf); 4633dcf5eb7SBaptiste Daroussin break; 4643dcf5eb7SBaptiste Daroussin case UCL_BOOLEAN: 4653dcf5eb7SBaptiste Daroussin if (obj->value.iv) { 4663dcf5eb7SBaptiste Daroussin ucl_utstring_append_len ("true", 4, buf); 4673dcf5eb7SBaptiste Daroussin } 4683dcf5eb7SBaptiste Daroussin else { 4693dcf5eb7SBaptiste Daroussin ucl_utstring_append_len ("false", 5, buf); 4703dcf5eb7SBaptiste Daroussin } 4713dcf5eb7SBaptiste Daroussin break; 4723dcf5eb7SBaptiste Daroussin case UCL_STRING: 4733dcf5eb7SBaptiste Daroussin ucl_utstring_append_len (obj->value.sv, obj->len, buf); 4743dcf5eb7SBaptiste Daroussin break; 4753dcf5eb7SBaptiste Daroussin case UCL_USERDATA: 4763dcf5eb7SBaptiste Daroussin ucl_utstring_append_len ("userdata", 8, buf); 4773dcf5eb7SBaptiste Daroussin break; 4783dcf5eb7SBaptiste Daroussin } 4793dcf5eb7SBaptiste Daroussin res = utstring_body (buf); 4803dcf5eb7SBaptiste Daroussin free (buf); 4813dcf5eb7SBaptiste Daroussin } 4823dcf5eb7SBaptiste Daroussin 4833dcf5eb7SBaptiste Daroussin return res; 4843dcf5eb7SBaptiste Daroussin } 4854bf54857SBaptiste Daroussin 4864bf54857SBaptiste Daroussin #define LONG_STRING_LIMIT 80 4874bf54857SBaptiste Daroussin 4884bf54857SBaptiste Daroussin bool 4894bf54857SBaptiste Daroussin ucl_maybe_long_string (const ucl_object_t *obj) 4904bf54857SBaptiste Daroussin { 4914bf54857SBaptiste Daroussin if (obj->len > LONG_STRING_LIMIT || (obj->flags & UCL_OBJECT_MULTILINE)) { 4924bf54857SBaptiste Daroussin /* String is long enough, so search for newline characters in it */ 4934bf54857SBaptiste Daroussin if (memchr (obj->value.sv, '\n', obj->len) != NULL) { 4944bf54857SBaptiste Daroussin return true; 4954bf54857SBaptiste Daroussin } 4964bf54857SBaptiste Daroussin } 4974bf54857SBaptiste Daroussin 4984bf54857SBaptiste Daroussin return false; 4994bf54857SBaptiste Daroussin } 500