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 free(buf); 293 return -1; 294 } 295 free (buf); 296 } 297 } 298 299 return 0; 300 } 301 302 static int 303 ucl_fd_append_len (const unsigned char *str, size_t len, void *ud) 304 { 305 int fd = *(int *)ud; 306 307 return write (fd, str, len); 308 } 309 310 static int 311 ucl_fd_append_int (int64_t val, void *ud) 312 { 313 int fd = *(int *)ud; 314 char intbuf[64]; 315 316 snprintf (intbuf, sizeof (intbuf), "%jd", (intmax_t)val); 317 return write (fd, intbuf, strlen (intbuf)); 318 } 319 320 static int 321 ucl_fd_append_double (double val, void *ud) 322 { 323 int fd = *(int *)ud; 324 const double delta = 0.0000001; 325 char nbuf[64]; 326 327 if (val == (double)(int)val) { 328 snprintf (nbuf, sizeof (nbuf), "%.1lf", val); 329 } 330 else if (fabs (val - (double)(int)val) < delta) { 331 /* Write at maximum precision */ 332 snprintf (nbuf, sizeof (nbuf), "%.*lg", DBL_DIG, val); 333 } 334 else { 335 snprintf (nbuf, sizeof (nbuf), "%lf", val); 336 } 337 338 return write (fd, nbuf, strlen (nbuf)); 339 } 340 341 struct ucl_emitter_functions* 342 ucl_object_emit_memory_funcs (void **pmem) 343 { 344 struct ucl_emitter_functions *f; 345 UT_string *s; 346 347 f = calloc (1, sizeof (*f)); 348 349 if (f != NULL) { 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; 355 utstring_new (s); 356 f->ud = s; 357 *pmem = s->d; 358 s->pd = pmem; 359 } 360 361 return f; 362 } 363 364 struct ucl_emitter_functions* 365 ucl_object_emit_file_funcs (FILE *fp) 366 { 367 struct ucl_emitter_functions *f; 368 369 f = calloc (1, sizeof (*f)); 370 371 if (f != NULL) { 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; 377 f->ud = fp; 378 } 379 380 return f; 381 } 382 383 struct ucl_emitter_functions* 384 ucl_object_emit_fd_funcs (int fd) 385 { 386 struct ucl_emitter_functions *f; 387 int *ip; 388 389 f = calloc (1, sizeof (*f)); 390 391 if (f != NULL) { 392 ip = malloc (sizeof (fd)); 393 if (ip == NULL) { 394 free (f); 395 return NULL; 396 } 397 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; 404 f->ud = ip; 405 } 406 407 return f; 408 } 409 410 void 411 ucl_object_emit_funcs_free (struct ucl_emitter_functions *f) 412 { 413 if (f != NULL) { 414 if (f->ucl_emitter_free_func != NULL) { 415 f->ucl_emitter_free_func (f->ud); 416 } 417 free (f); 418 } 419 } 420 421 422 unsigned char * 423 ucl_object_emit_single_json (const ucl_object_t *obj) 424 { 425 UT_string *buf = NULL; 426 unsigned char *res = NULL; 427 428 if (obj == NULL) { 429 return NULL; 430 } 431 432 utstring_new (buf); 433 434 if (buf != NULL) { 435 switch (obj->type) { 436 case UCL_OBJECT: 437 ucl_utstring_append_len ("object", 6, buf); 438 break; 439 case UCL_ARRAY: 440 ucl_utstring_append_len ("array", 5, buf); 441 break; 442 case UCL_INT: 443 ucl_utstring_append_int (obj->value.iv, buf); 444 break; 445 case UCL_FLOAT: 446 case UCL_TIME: 447 ucl_utstring_append_double (obj->value.dv, buf); 448 break; 449 case UCL_NULL: 450 ucl_utstring_append_len ("null", 4, buf); 451 break; 452 case UCL_BOOLEAN: 453 if (obj->value.iv) { 454 ucl_utstring_append_len ("true", 4, buf); 455 } 456 else { 457 ucl_utstring_append_len ("false", 5, buf); 458 } 459 break; 460 case UCL_STRING: 461 ucl_utstring_append_len (obj->value.sv, obj->len, buf); 462 break; 463 case UCL_USERDATA: 464 ucl_utstring_append_len ("userdata", 8, buf); 465 break; 466 } 467 res = utstring_body (buf); 468 free (buf); 469 } 470 471 return res; 472 } 473 474 #define LONG_STRING_LIMIT 80 475 476 bool 477 ucl_maybe_long_string (const ucl_object_t *obj) 478 { 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) { 482 return true; 483 } 484 } 485 486 return false; 487 } 488