1 /* Copyright (c) 2014, Vsevolod Stakhov 2 * All rights reserved. 3 * 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. 11 * 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. 22 */ 23 24 #ifdef HAVE_CONFIG_H 25 #include "config.h" 26 #endif 27 28 #include "ucl.h" 29 #include "ucl_internal.h" 30 #include "ucl_chartable.h" 31 32 #ifdef HAVE_FLOAT_H 33 #include <float.h> 34 #endif 35 #ifdef HAVE_MATH_H 36 #include <math.h> 37 #endif 38 39 extern const struct ucl_emitter_operations ucl_standartd_emitter_ops[]; 40 41 static const struct ucl_emitter_context ucl_standard_emitters[] = { 42 [UCL_EMIT_JSON] = { 43 .name = "json", 44 .id = UCL_EMIT_JSON, 45 .func = NULL, 46 .ops = &ucl_standartd_emitter_ops[UCL_EMIT_JSON] 47 }, 48 [UCL_EMIT_JSON_COMPACT] = { 49 .name = "json_compact", 50 .id = UCL_EMIT_JSON_COMPACT, 51 .func = NULL, 52 .ops = &ucl_standartd_emitter_ops[UCL_EMIT_JSON_COMPACT] 53 }, 54 [UCL_EMIT_CONFIG] = { 55 .name = "config", 56 .id = UCL_EMIT_CONFIG, 57 .func = NULL, 58 .ops = &ucl_standartd_emitter_ops[UCL_EMIT_CONFIG] 59 }, 60 [UCL_EMIT_YAML] = { 61 .name = "yaml", 62 .id = UCL_EMIT_YAML, 63 .func = NULL, 64 .ops = &ucl_standartd_emitter_ops[UCL_EMIT_YAML] 65 } 66 }; 67 68 /** 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 72 */ 73 const struct ucl_emitter_context * 74 ucl_emit_get_standard_context (enum ucl_emitter emit_type) 75 { 76 if (emit_type >= UCL_EMIT_JSON && emit_type <= UCL_EMIT_YAML) { 77 return &ucl_standard_emitters[emit_type]; 78 } 79 80 return NULL; 81 } 82 83 /** 84 * Serialise string 85 * @param str string to emit 86 * @param buf target buffer 87 */ 88 void 89 ucl_elt_string_write_json (const char *str, size_t size, 90 struct ucl_emitter_context *ctx) 91 { 92 const char *p = str, *c = str; 93 size_t len = 0; 94 const struct ucl_emitter_functions *func = ctx->func; 95 96 func->ucl_emitter_append_character ('"', 1, func->ud); 97 98 while (size) { 99 if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) { 100 if (len > 0) { 101 func->ucl_emitter_append_len (c, len, func->ud); 102 } 103 switch (*p) { 104 case '\n': 105 func->ucl_emitter_append_len ("\\n", 2, func->ud); 106 break; 107 case '\r': 108 func->ucl_emitter_append_len ("\\r", 2, func->ud); 109 break; 110 case '\b': 111 func->ucl_emitter_append_len ("\\b", 2, func->ud); 112 break; 113 case '\t': 114 func->ucl_emitter_append_len ("\\t", 2, func->ud); 115 break; 116 case '\f': 117 func->ucl_emitter_append_len ("\\f", 2, func->ud); 118 break; 119 case '\\': 120 func->ucl_emitter_append_len ("\\\\", 2, func->ud); 121 break; 122 case '"': 123 func->ucl_emitter_append_len ("\\\"", 2, func->ud); 124 break; 125 } 126 len = 0; 127 c = ++p; 128 } 129 else { 130 p ++; 131 len ++; 132 } 133 size --; 134 } 135 if (len > 0) { 136 func->ucl_emitter_append_len (c, len, func->ud); 137 } 138 func->ucl_emitter_append_character ('"', 1, func->ud); 139 } 140 141 void 142 ucl_elt_string_write_multiline (const char *str, size_t size, 143 struct ucl_emitter_context *ctx) 144 { 145 const struct ucl_emitter_functions *func = ctx->func; 146 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); 150 } 151 152 /* 153 * Generic utstring output 154 */ 155 static int 156 ucl_utstring_append_character (unsigned char c, size_t len, void *ud) 157 { 158 UT_string *buf = ud; 159 160 if (len == 1) { 161 utstring_append_c (buf, c); 162 } 163 else { 164 utstring_reserve (buf, len + 1); 165 memset (&buf->d[buf->i], c, len); 166 buf->i += len; 167 buf->d[buf->i] = '\0'; 168 } 169 170 return 0; 171 } 172 173 static int 174 ucl_utstring_append_len (const unsigned char *str, size_t len, void *ud) 175 { 176 UT_string *buf = ud; 177 178 utstring_append_len (buf, str, len); 179 180 return 0; 181 } 182 183 static int 184 ucl_utstring_append_int (int64_t val, void *ud) 185 { 186 UT_string *buf = ud; 187 188 utstring_printf (buf, "%jd", (intmax_t)val); 189 return 0; 190 } 191 192 static int 193 ucl_utstring_append_double (double val, void *ud) 194 { 195 UT_string *buf = ud; 196 const double delta = 0.0000001; 197 198 if (val == (double)(int)val) { 199 utstring_printf (buf, "%.1lf", val); 200 } 201 else if (fabs (val - (double)(int)val) < delta) { 202 /* Write at maximum precision */ 203 utstring_printf (buf, "%.*lg", DBL_DIG, val); 204 } 205 else { 206 utstring_printf (buf, "%lf", val); 207 } 208 209 return 0; 210 } 211 212 /* 213 * Generic file output 214 */ 215 static int 216 ucl_file_append_character (unsigned char c, size_t len, void *ud) 217 { 218 FILE *fp = ud; 219 220 while (len --) { 221 fputc (c, fp); 222 } 223 224 return 0; 225 } 226 227 static int 228 ucl_file_append_len (const unsigned char *str, size_t len, void *ud) 229 { 230 FILE *fp = ud; 231 232 fwrite (str, len, 1, fp); 233 234 return 0; 235 } 236 237 static int 238 ucl_file_append_int (int64_t val, void *ud) 239 { 240 FILE *fp = ud; 241 242 fprintf (fp, "%jd", (intmax_t)val); 243 244 return 0; 245 } 246 247 static int 248 ucl_file_append_double (double val, void *ud) 249 { 250 FILE *fp = ud; 251 const double delta = 0.0000001; 252 253 if (val == (double)(int)val) { 254 fprintf (fp, "%.1lf", val); 255 } 256 else if (fabs (val - (double)(int)val) < delta) { 257 /* Write at maximum precision */ 258 fprintf (fp, "%.*lg", DBL_DIG, val); 259 } 260 else { 261 fprintf (fp, "%lf", val); 262 } 263 264 return 0; 265 } 266 267 /* 268 * Generic file descriptor writing functions 269 */ 270 static int 271 ucl_fd_append_character (unsigned char c, size_t len, void *ud) 272 { 273 int fd = *(int *)ud; 274 unsigned char *buf; 275 276 if (len == 1) { 277 return write (fd, &c, 1); 278 } 279 else { 280 buf = malloc (len); 281 if (buf == NULL) { 282 /* Fallback */ 283 while (len --) { 284 if (write (fd, &c, 1) == -1) { 285 return -1; 286 } 287 } 288 } 289 else { 290 memset (buf, c, len); 291 if (write (fd, buf, len) == -1) { 292 return -1; 293 } 294 free (buf); 295 } 296 } 297 298 return 0; 299 } 300 301 static int 302 ucl_fd_append_len (const unsigned char *str, size_t len, void *ud) 303 { 304 int fd = *(int *)ud; 305 306 return write (fd, str, len); 307 } 308 309 static int 310 ucl_fd_append_int (int64_t val, void *ud) 311 { 312 int fd = *(int *)ud; 313 char intbuf[64]; 314 315 snprintf (intbuf, sizeof (intbuf), "%jd", (intmax_t)val); 316 return write (fd, intbuf, strlen (intbuf)); 317 } 318 319 static int 320 ucl_fd_append_double (double val, void *ud) 321 { 322 int fd = *(int *)ud; 323 const double delta = 0.0000001; 324 char nbuf[64]; 325 326 if (val == (double)(int)val) { 327 snprintf (nbuf, sizeof (nbuf), "%.1lf", val); 328 } 329 else if (fabs (val - (double)(int)val) < delta) { 330 /* Write at maximum precision */ 331 snprintf (nbuf, sizeof (nbuf), "%.*lg", DBL_DIG, val); 332 } 333 else { 334 snprintf (nbuf, sizeof (nbuf), "%lf", val); 335 } 336 337 return write (fd, nbuf, strlen (nbuf)); 338 } 339 340 struct ucl_emitter_functions* 341 ucl_object_emit_memory_funcs (void **pmem) 342 { 343 struct ucl_emitter_functions *f; 344 UT_string *s; 345 346 f = calloc (1, sizeof (*f)); 347 348 if (f != NULL) { 349 f->ucl_emitter_append_character = ucl_utstring_append_character; 350 f->ucl_emitter_append_double = ucl_utstring_append_double; 351 f->ucl_emitter_append_int = ucl_utstring_append_int; 352 f->ucl_emitter_append_len = ucl_utstring_append_len; 353 f->ucl_emitter_free_func = free; 354 utstring_new (s); 355 f->ud = s; 356 *pmem = s->d; 357 s->pd = pmem; 358 } 359 360 return f; 361 } 362 363 struct ucl_emitter_functions* 364 ucl_object_emit_file_funcs (FILE *fp) 365 { 366 struct ucl_emitter_functions *f; 367 368 f = calloc (1, sizeof (*f)); 369 370 if (f != NULL) { 371 f->ucl_emitter_append_character = ucl_file_append_character; 372 f->ucl_emitter_append_double = ucl_file_append_double; 373 f->ucl_emitter_append_int = ucl_file_append_int; 374 f->ucl_emitter_append_len = ucl_file_append_len; 375 f->ucl_emitter_free_func = NULL; 376 f->ud = fp; 377 } 378 379 return f; 380 } 381 382 struct ucl_emitter_functions* 383 ucl_object_emit_fd_funcs (int fd) 384 { 385 struct ucl_emitter_functions *f; 386 int *ip; 387 388 f = calloc (1, sizeof (*f)); 389 390 if (f != NULL) { 391 ip = malloc (sizeof (fd)); 392 if (ip == NULL) { 393 free (f); 394 return NULL; 395 } 396 397 memcpy (ip, &fd, sizeof (fd)); 398 f->ucl_emitter_append_character = ucl_fd_append_character; 399 f->ucl_emitter_append_double = ucl_fd_append_double; 400 f->ucl_emitter_append_int = ucl_fd_append_int; 401 f->ucl_emitter_append_len = ucl_fd_append_len; 402 f->ucl_emitter_free_func = free; 403 f->ud = ip; 404 } 405 406 return f; 407 } 408 409 void 410 ucl_object_emit_funcs_free (struct ucl_emitter_functions *f) 411 { 412 if (f != NULL) { 413 if (f->ucl_emitter_free_func != NULL) { 414 f->ucl_emitter_free_func (f->ud); 415 } 416 free (f); 417 } 418 } 419 420 421 unsigned char * 422 ucl_object_emit_single_json (const ucl_object_t *obj) 423 { 424 UT_string *buf = NULL; 425 unsigned char *res = NULL; 426 427 if (obj == NULL) { 428 return NULL; 429 } 430 431 utstring_new (buf); 432 433 if (buf != NULL) { 434 switch (obj->type) { 435 case UCL_OBJECT: 436 ucl_utstring_append_len ("object", 6, buf); 437 break; 438 case UCL_ARRAY: 439 ucl_utstring_append_len ("array", 5, buf); 440 break; 441 case UCL_INT: 442 ucl_utstring_append_int (obj->value.iv, buf); 443 break; 444 case UCL_FLOAT: 445 case UCL_TIME: 446 ucl_utstring_append_double (obj->value.dv, buf); 447 break; 448 case UCL_NULL: 449 ucl_utstring_append_len ("null", 4, buf); 450 break; 451 case UCL_BOOLEAN: 452 if (obj->value.iv) { 453 ucl_utstring_append_len ("true", 4, buf); 454 } 455 else { 456 ucl_utstring_append_len ("false", 5, buf); 457 } 458 break; 459 case UCL_STRING: 460 ucl_utstring_append_len (obj->value.sv, obj->len, buf); 461 break; 462 case UCL_USERDATA: 463 ucl_utstring_append_len ("userdata", 8, buf); 464 break; 465 } 466 res = utstring_body (buf); 467 free (buf); 468 } 469 470 return res; 471 } 472 473 #define LONG_STRING_LIMIT 80 474 475 bool 476 ucl_maybe_long_string (const ucl_object_t *obj) 477 { 478 if (obj->len > LONG_STRING_LIMIT || (obj->flags & UCL_OBJECT_MULTILINE)) { 479 /* String is long enough, so search for newline characters in it */ 480 if (memchr (obj->value.sv, '\n', obj->len) != NULL) { 481 return true; 482 } 483 } 484 485 return false; 486 } 487