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