Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/external/libucl/src/ucl_emitter.c
2066 views
1
/* Copyright (c) 2013, 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
#ifdef HAVE_FLOAT_H
32
#include <float.h>
33
#endif
34
#ifdef HAVE_MATH_H
35
#include <math.h>
36
#endif
37
38
/**
39
* @file ucl_emitter.c
40
* Serialise UCL object to various of output formats
41
*/
42
43
static void ucl_emitter_common_elt (struct ucl_emitter_context *ctx,
44
const ucl_object_t *obj, bool first, bool print_key, bool compact);
45
46
#define UCL_EMIT_TYPE_OPS(type) \
47
static void ucl_emit_ ## type ## _elt (struct ucl_emitter_context *ctx, \
48
const ucl_object_t *obj, bool first, bool print_key); \
49
static void ucl_emit_ ## type ## _start_obj (struct ucl_emitter_context *ctx, \
50
const ucl_object_t *obj, bool first, bool print_key); \
51
static void ucl_emit_ ## type## _start_array (struct ucl_emitter_context *ctx, \
52
const ucl_object_t *obj, bool first, bool print_key); \
53
static void ucl_emit_ ##type## _end_object (struct ucl_emitter_context *ctx, \
54
const ucl_object_t *obj); \
55
static void ucl_emit_ ##type## _end_array (struct ucl_emitter_context *ctx, \
56
const ucl_object_t *obj)
57
58
/*
59
* JSON format operations
60
*/
61
UCL_EMIT_TYPE_OPS(json);
62
UCL_EMIT_TYPE_OPS(json_compact);
63
UCL_EMIT_TYPE_OPS(config);
64
UCL_EMIT_TYPE_OPS(yaml);
65
UCL_EMIT_TYPE_OPS(msgpack);
66
67
#define UCL_EMIT_TYPE_CONTENT(type) { \
68
.ucl_emitter_write_elt = ucl_emit_ ## type ## _elt, \
69
.ucl_emitter_start_object = ucl_emit_ ## type ##_start_obj, \
70
.ucl_emitter_start_array = ucl_emit_ ## type ##_start_array, \
71
.ucl_emitter_end_object = ucl_emit_ ## type ##_end_object, \
72
.ucl_emitter_end_array = ucl_emit_ ## type ##_end_array \
73
}
74
75
const struct ucl_emitter_operations ucl_standartd_emitter_ops[] = {
76
[UCL_EMIT_JSON] = UCL_EMIT_TYPE_CONTENT(json),
77
[UCL_EMIT_JSON_COMPACT] = UCL_EMIT_TYPE_CONTENT(json_compact),
78
[UCL_EMIT_CONFIG] = UCL_EMIT_TYPE_CONTENT(config),
79
[UCL_EMIT_YAML] = UCL_EMIT_TYPE_CONTENT(yaml),
80
[UCL_EMIT_MSGPACK] = UCL_EMIT_TYPE_CONTENT(msgpack)
81
};
82
83
/*
84
* Utility to check whether we need a top object
85
*/
86
#define UCL_EMIT_IDENT_TOP_OBJ(ctx, obj) ((ctx)->top != (obj) || \
87
((ctx)->id == UCL_EMIT_JSON_COMPACT || (ctx)->id == UCL_EMIT_JSON))
88
89
90
/**
91
* Add tabulation to the output buffer
92
* @param buf target buffer
93
* @param tabs number of tabs to add
94
*/
95
static inline void
96
ucl_add_tabs (const struct ucl_emitter_functions *func, unsigned int tabs,
97
bool compact)
98
{
99
if (!compact && tabs > 0) {
100
func->ucl_emitter_append_character (' ', tabs * 4, func->ud);
101
}
102
}
103
104
/**
105
* Print key for the element
106
* @param ctx
107
* @param obj
108
*/
109
static void
110
ucl_emitter_print_key (bool print_key, struct ucl_emitter_context *ctx,
111
const ucl_object_t *obj, bool compact)
112
{
113
const struct ucl_emitter_functions *func = ctx->func;
114
115
if (!print_key) {
116
return;
117
}
118
119
if (ctx->id == UCL_EMIT_CONFIG) {
120
if (obj->flags & UCL_OBJECT_NEED_KEY_ESCAPE) {
121
ucl_elt_string_write_json (obj->key, obj->keylen, ctx);
122
}
123
else {
124
func->ucl_emitter_append_len (obj->key, obj->keylen, func->ud);
125
}
126
127
if (obj->type != UCL_OBJECT && obj->type != UCL_ARRAY) {
128
func->ucl_emitter_append_len (" = ", 3, func->ud);
129
}
130
else {
131
func->ucl_emitter_append_character (' ', 1, func->ud);
132
}
133
}
134
else if (ctx->id == UCL_EMIT_YAML) {
135
if (obj->keylen > 0 && (obj->flags & UCL_OBJECT_NEED_KEY_ESCAPE)) {
136
ucl_elt_string_write_json (obj->key, obj->keylen, ctx);
137
}
138
else if (obj->keylen > 0) {
139
func->ucl_emitter_append_len (obj->key, obj->keylen, func->ud);
140
}
141
else {
142
func->ucl_emitter_append_len ("null", 4, func->ud);
143
}
144
145
func->ucl_emitter_append_len (": ", 2, func->ud);
146
}
147
else {
148
if (obj->keylen > 0) {
149
ucl_elt_string_write_json (obj->key, obj->keylen, ctx);
150
}
151
else {
152
func->ucl_emitter_append_len ("null", 4, func->ud);
153
}
154
155
if (compact) {
156
func->ucl_emitter_append_character (':', 1, func->ud);
157
}
158
else {
159
func->ucl_emitter_append_len (": ", 2, func->ud);
160
}
161
}
162
}
163
164
static void
165
ucl_emitter_finish_object (struct ucl_emitter_context *ctx,
166
const ucl_object_t *obj, bool compact, bool is_array)
167
{
168
const struct ucl_emitter_functions *func = ctx->func;
169
170
if (ctx->id == UCL_EMIT_CONFIG && obj != ctx->top) {
171
if (obj->type != UCL_OBJECT && obj->type != UCL_ARRAY) {
172
if (!is_array) {
173
/* Objects are split by ';' */
174
func->ucl_emitter_append_len (";\n", 2, func->ud);
175
}
176
else {
177
/* Use commas for arrays */
178
func->ucl_emitter_append_len (",\n", 2, func->ud);
179
}
180
}
181
else {
182
func->ucl_emitter_append_character ('\n', 1, func->ud);
183
}
184
}
185
}
186
187
/**
188
* End standard ucl object
189
* @param ctx emitter context
190
* @param compact compact flag
191
*/
192
static void
193
ucl_emitter_common_end_object (struct ucl_emitter_context *ctx,
194
const ucl_object_t *obj, bool compact)
195
{
196
const struct ucl_emitter_functions *func = ctx->func;
197
198
if (UCL_EMIT_IDENT_TOP_OBJ(ctx, obj)) {
199
ctx->indent --;
200
if (compact) {
201
func->ucl_emitter_append_character ('}', 1, func->ud);
202
}
203
else {
204
if (ctx->id != UCL_EMIT_CONFIG) {
205
/* newline is already added for this format */
206
func->ucl_emitter_append_character ('\n', 1, func->ud);
207
}
208
ucl_add_tabs (func, ctx->indent, compact);
209
func->ucl_emitter_append_character ('}', 1, func->ud);
210
}
211
}
212
213
ucl_emitter_finish_object (ctx, obj, compact, false);
214
}
215
216
/**
217
* End standard ucl array
218
* @param ctx emitter context
219
* @param compact compact flag
220
*/
221
static void
222
ucl_emitter_common_end_array (struct ucl_emitter_context *ctx,
223
const ucl_object_t *obj, bool compact)
224
{
225
const struct ucl_emitter_functions *func = ctx->func;
226
227
ctx->indent --;
228
if (compact) {
229
func->ucl_emitter_append_character (']', 1, func->ud);
230
}
231
else {
232
if (ctx->id != UCL_EMIT_CONFIG) {
233
/* newline is already added for this format */
234
func->ucl_emitter_append_character ('\n', 1, func->ud);
235
}
236
ucl_add_tabs (func, ctx->indent, compact);
237
func->ucl_emitter_append_character (']', 1, func->ud);
238
}
239
240
ucl_emitter_finish_object (ctx, obj, compact, true);
241
}
242
243
/**
244
* Start emit standard UCL array
245
* @param ctx emitter context
246
* @param obj object to write
247
* @param compact compact flag
248
*/
249
static void
250
ucl_emitter_common_start_array (struct ucl_emitter_context *ctx,
251
const ucl_object_t *obj, bool first, bool print_key, bool compact)
252
{
253
const ucl_object_t *cur;
254
ucl_object_iter_t iter = NULL;
255
const struct ucl_emitter_functions *func = ctx->func;
256
bool first_key = true;
257
258
if (ctx->id != UCL_EMIT_CONFIG && !first) {
259
if (compact) {
260
func->ucl_emitter_append_character (',', 1, func->ud);
261
}
262
else {
263
if (ctx->id == UCL_EMIT_YAML && ctx->indent == 0) {
264
func->ucl_emitter_append_len ("\n", 1, func->ud);
265
} else {
266
func->ucl_emitter_append_len (",\n", 2, func->ud);
267
}
268
}
269
ucl_add_tabs (func, ctx->indent, compact);
270
}
271
272
ucl_emitter_print_key (print_key, ctx, obj, compact);
273
274
if (compact) {
275
func->ucl_emitter_append_character ('[', 1, func->ud);
276
}
277
else {
278
func->ucl_emitter_append_len ("[\n", 2, func->ud);
279
}
280
281
ctx->indent ++;
282
283
if (obj->type == UCL_ARRAY) {
284
/* explicit array */
285
while ((cur = ucl_object_iterate (obj, &iter, true)) != NULL) {
286
ucl_emitter_common_elt (ctx, cur, first_key, false, compact);
287
first_key = false;
288
}
289
}
290
else {
291
/* implicit array */
292
cur = obj;
293
while (cur) {
294
ucl_emitter_common_elt (ctx, cur, first_key, false, compact);
295
first_key = false;
296
cur = cur->next;
297
}
298
}
299
300
301
}
302
303
/**
304
* Start emit standard UCL object
305
* @param ctx emitter context
306
* @param obj object to write
307
* @param compact compact flag
308
*/
309
static void
310
ucl_emitter_common_start_object (struct ucl_emitter_context *ctx,
311
const ucl_object_t *obj, bool first, bool print_key, bool compact)
312
{
313
ucl_hash_iter_t it = NULL;
314
const ucl_object_t *cur, *elt;
315
const struct ucl_emitter_functions *func = ctx->func;
316
bool first_key = true;
317
318
if (ctx->id != UCL_EMIT_CONFIG && !first) {
319
if (compact) {
320
func->ucl_emitter_append_character (',', 1, func->ud);
321
}
322
else {
323
if (ctx->id == UCL_EMIT_YAML && ctx->indent == 0) {
324
func->ucl_emitter_append_len ("\n", 1, func->ud);
325
} else {
326
func->ucl_emitter_append_len (",\n", 2, func->ud);
327
}
328
}
329
ucl_add_tabs (func, ctx->indent, compact);
330
}
331
332
ucl_emitter_print_key (print_key, ctx, obj, compact);
333
/*
334
* Print <ident_level>{
335
* <ident_level + 1><object content>
336
*/
337
if (UCL_EMIT_IDENT_TOP_OBJ(ctx, obj)) {
338
if (compact) {
339
func->ucl_emitter_append_character ('{', 1, func->ud);
340
}
341
else {
342
func->ucl_emitter_append_len ("{\n", 2, func->ud);
343
}
344
ctx->indent ++;
345
}
346
347
while ((cur = ucl_hash_iterate (obj->value.ov, &it))) {
348
349
if (ctx->id == UCL_EMIT_CONFIG) {
350
LL_FOREACH (cur, elt) {
351
ucl_emitter_common_elt (ctx, elt, first_key, true, compact);
352
}
353
}
354
else {
355
/* Expand implicit arrays */
356
if (cur->next != NULL) {
357
if (!first_key) {
358
if (compact) {
359
func->ucl_emitter_append_character (',', 1, func->ud);
360
}
361
else {
362
func->ucl_emitter_append_len (",\n", 2, func->ud);
363
}
364
}
365
ucl_add_tabs (func, ctx->indent, compact);
366
ucl_emitter_common_start_array (ctx, cur, first_key, true, compact);
367
ucl_emitter_common_end_array (ctx, cur, compact);
368
}
369
else {
370
ucl_emitter_common_elt (ctx, cur, first_key, true, compact);
371
}
372
}
373
374
first_key = false;
375
}
376
}
377
378
/**
379
* Common choice of object emitting
380
* @param ctx emitter context
381
* @param obj object to print
382
* @param first flag to mark the first element
383
* @param print_key print key of an object
384
* @param compact compact output
385
*/
386
static void
387
ucl_emitter_common_elt (struct ucl_emitter_context *ctx,
388
const ucl_object_t *obj, bool first, bool print_key, bool compact)
389
{
390
const struct ucl_emitter_functions *func = ctx->func;
391
bool flag;
392
struct ucl_object_userdata *ud;
393
const ucl_object_t *comment = NULL, *cur_comment;
394
const char *ud_out = "";
395
396
if (ctx->id != UCL_EMIT_CONFIG && !first) {
397
if (compact) {
398
func->ucl_emitter_append_character (',', 1, func->ud);
399
}
400
else {
401
if (ctx->id == UCL_EMIT_YAML && ctx->indent == 0) {
402
func->ucl_emitter_append_len ("\n", 1, func->ud);
403
} else {
404
func->ucl_emitter_append_len (",\n", 2, func->ud);
405
}
406
}
407
}
408
409
ucl_add_tabs (func, ctx->indent, compact);
410
411
if (ctx->comments && ctx->id == UCL_EMIT_CONFIG) {
412
comment = ucl_object_lookup_len (ctx->comments, (const char *)&obj,
413
sizeof (void *));
414
415
if (comment) {
416
if (!(comment->flags & UCL_OBJECT_INHERITED)) {
417
DL_FOREACH (comment, cur_comment) {
418
func->ucl_emitter_append_len (cur_comment->value.sv,
419
cur_comment->len,
420
func->ud);
421
func->ucl_emitter_append_character ('\n', 1, func->ud);
422
ucl_add_tabs (func, ctx->indent, compact);
423
}
424
425
comment = NULL;
426
}
427
}
428
}
429
430
switch (obj->type) {
431
case UCL_INT:
432
ucl_emitter_print_key (print_key, ctx, obj, compact);
433
func->ucl_emitter_append_int (ucl_object_toint (obj), func->ud);
434
ucl_emitter_finish_object (ctx, obj, compact, !print_key);
435
break;
436
case UCL_FLOAT:
437
case UCL_TIME:
438
ucl_emitter_print_key (print_key, ctx, obj, compact);
439
func->ucl_emitter_append_double (ucl_object_todouble (obj), func->ud);
440
ucl_emitter_finish_object (ctx, obj, compact, !print_key);
441
break;
442
case UCL_BOOLEAN:
443
ucl_emitter_print_key (print_key, ctx, obj, compact);
444
flag = ucl_object_toboolean (obj);
445
if (flag) {
446
func->ucl_emitter_append_len ("true", 4, func->ud);
447
}
448
else {
449
func->ucl_emitter_append_len ("false", 5, func->ud);
450
}
451
ucl_emitter_finish_object (ctx, obj, compact, !print_key);
452
break;
453
case UCL_STRING:
454
ucl_emitter_print_key (print_key, ctx, obj, compact);
455
if (ctx->id == UCL_EMIT_CONFIG) {
456
if (ucl_maybe_long_string (obj)) {
457
ucl_elt_string_write_multiline (obj->value.sv, obj->len, ctx);
458
} else {
459
if (obj->flags & UCL_OBJECT_SQUOTED) {
460
ucl_elt_string_write_squoted (obj->value.sv, obj->len, ctx);
461
} else {
462
ucl_elt_string_write_json (obj->value.sv, obj->len, ctx);
463
}
464
}
465
}
466
else {
467
ucl_elt_string_write_json (obj->value.sv, obj->len, ctx);
468
}
469
ucl_emitter_finish_object (ctx, obj, compact, !print_key);
470
break;
471
case UCL_NULL:
472
ucl_emitter_print_key (print_key, ctx, obj, compact);
473
func->ucl_emitter_append_len ("null", 4, func->ud);
474
ucl_emitter_finish_object (ctx, obj, compact, !print_key);
475
break;
476
case UCL_OBJECT:
477
ucl_emitter_common_start_object (ctx, obj, true, print_key, compact);
478
ucl_emitter_common_end_object (ctx, obj, compact);
479
break;
480
case UCL_ARRAY:
481
ucl_emitter_common_start_array (ctx, obj, true, print_key, compact);
482
ucl_emitter_common_end_array (ctx, obj, compact);
483
break;
484
case UCL_USERDATA:
485
ud = (struct ucl_object_userdata *)obj;
486
ucl_emitter_print_key (print_key, ctx, obj, compact);
487
if (ud->emitter) {
488
ud_out = ud->emitter (obj->value.ud);
489
if (ud_out == NULL) {
490
ud_out = "null";
491
}
492
}
493
ucl_elt_string_write_json (ud_out, strlen (ud_out), ctx);
494
ucl_emitter_finish_object (ctx, obj, compact, !print_key);
495
break;
496
}
497
498
if (comment) {
499
DL_FOREACH (comment, cur_comment) {
500
func->ucl_emitter_append_len (cur_comment->value.sv,
501
cur_comment->len,
502
func->ud);
503
func->ucl_emitter_append_character ('\n', 1, func->ud);
504
505
if (cur_comment->next) {
506
ucl_add_tabs (func, ctx->indent, compact);
507
}
508
}
509
}
510
}
511
512
/*
513
* Specific standard implementations of the emitter functions
514
*/
515
#define UCL_EMIT_TYPE_IMPL(type, compact) \
516
static void ucl_emit_ ## type ## _elt (struct ucl_emitter_context *ctx, \
517
const ucl_object_t *obj, bool first, bool print_key) { \
518
ucl_emitter_common_elt (ctx, obj, first, print_key, (compact)); \
519
} \
520
static void ucl_emit_ ## type ## _start_obj (struct ucl_emitter_context *ctx, \
521
const ucl_object_t *obj, bool first, bool print_key) { \
522
ucl_emitter_common_start_object (ctx, obj, first, print_key, (compact)); \
523
} \
524
static void ucl_emit_ ## type## _start_array (struct ucl_emitter_context *ctx, \
525
const ucl_object_t *obj, bool first, bool print_key) { \
526
ucl_emitter_common_start_array (ctx, obj, first, print_key, (compact)); \
527
} \
528
static void ucl_emit_ ##type## _end_object (struct ucl_emitter_context *ctx, \
529
const ucl_object_t *obj) { \
530
ucl_emitter_common_end_object (ctx, obj, (compact)); \
531
} \
532
static void ucl_emit_ ##type## _end_array (struct ucl_emitter_context *ctx, \
533
const ucl_object_t *obj) { \
534
ucl_emitter_common_end_array (ctx, obj, (compact)); \
535
}
536
537
UCL_EMIT_TYPE_IMPL(json, false)
538
UCL_EMIT_TYPE_IMPL(json_compact, true)
539
UCL_EMIT_TYPE_IMPL(config, false)
540
UCL_EMIT_TYPE_IMPL(yaml, false)
541
542
static void
543
ucl_emit_msgpack_elt (struct ucl_emitter_context *ctx,
544
const ucl_object_t *obj, bool _first, bool print_key)
545
{
546
ucl_object_iter_t it;
547
struct ucl_object_userdata *ud;
548
const char *ud_out;
549
const ucl_object_t *cur, *celt;
550
551
switch (obj->type) {
552
case UCL_INT:
553
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
554
ucl_emitter_print_int_msgpack (ctx, ucl_object_toint (obj));
555
break;
556
557
case UCL_FLOAT:
558
case UCL_TIME:
559
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
560
ucl_emitter_print_double_msgpack (ctx, ucl_object_todouble (obj));
561
break;
562
563
case UCL_BOOLEAN:
564
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
565
ucl_emitter_print_bool_msgpack (ctx, ucl_object_toboolean (obj));
566
break;
567
568
case UCL_STRING:
569
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
570
571
if (obj->flags & UCL_OBJECT_BINARY) {
572
ucl_emitter_print_binary_string_msgpack (ctx, obj->value.sv,
573
obj->len);
574
}
575
else {
576
ucl_emitter_print_string_msgpack (ctx, obj->value.sv, obj->len);
577
}
578
break;
579
580
case UCL_NULL:
581
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
582
ucl_emitter_print_null_msgpack (ctx);
583
break;
584
585
case UCL_OBJECT:
586
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
587
ucl_emit_msgpack_start_obj (ctx, obj, false, print_key);
588
it = NULL;
589
590
while ((cur = ucl_object_iterate (obj, &it, true)) != NULL) {
591
LL_FOREACH (cur, celt) {
592
ucl_emit_msgpack_elt (ctx, celt, false, true);
593
/* XXX:
594
* in msgpack the length of objects is encoded within a single elt
595
* so in case of multi-value keys we are using merely the first
596
* element ignoring others
597
*/
598
break;
599
}
600
}
601
602
break;
603
604
case UCL_ARRAY:
605
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
606
ucl_emit_msgpack_start_array (ctx, obj, false, print_key);
607
it = NULL;
608
609
while ((cur = ucl_object_iterate (obj, &it, true)) != NULL) {
610
ucl_emit_msgpack_elt (ctx, cur, false, false);
611
}
612
613
break;
614
615
case UCL_USERDATA:
616
ud = (struct ucl_object_userdata *)obj;
617
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
618
619
if (ud->emitter) {
620
ud_out = ud->emitter (obj->value.ud);
621
if (ud_out == NULL) {
622
ud_out = "null";
623
}
624
}
625
ucl_emitter_print_string_msgpack (ctx, obj->value.sv, obj->len);
626
break;
627
}
628
}
629
630
static void
631
ucl_emit_msgpack_start_obj (struct ucl_emitter_context *ctx,
632
const ucl_object_t *obj, bool _first, bool _print_key)
633
{
634
ucl_emitter_print_object_msgpack (ctx, obj->len);
635
}
636
637
static void
638
ucl_emit_msgpack_start_array (struct ucl_emitter_context *ctx,
639
const ucl_object_t *obj, bool _first, bool _print_key)
640
{
641
ucl_emitter_print_array_msgpack (ctx, obj->len);
642
}
643
644
static void
645
ucl_emit_msgpack_end_object (struct ucl_emitter_context *ctx,
646
const ucl_object_t *obj)
647
{
648
649
}
650
651
static void
652
ucl_emit_msgpack_end_array (struct ucl_emitter_context *ctx,
653
const ucl_object_t *obj)
654
{
655
656
}
657
658
unsigned char *
659
ucl_object_emit (const ucl_object_t *obj, enum ucl_emitter emit_type)
660
{
661
return ucl_object_emit_len (obj, emit_type, NULL);
662
}
663
664
unsigned char *
665
ucl_object_emit_len (const ucl_object_t *obj, enum ucl_emitter emit_type,
666
size_t *outlen)
667
{
668
unsigned char *res = NULL;
669
struct ucl_emitter_functions *func;
670
UT_string *s;
671
672
if (obj == NULL) {
673
return NULL;
674
}
675
676
func = ucl_object_emit_memory_funcs ((void **)&res);
677
678
if (func != NULL) {
679
s = func->ud;
680
ucl_object_emit_full (obj, emit_type, func, NULL);
681
682
if (outlen != NULL) {
683
*outlen = s->i;
684
}
685
686
ucl_object_emit_funcs_free (func);
687
}
688
689
return res;
690
}
691
692
bool
693
ucl_object_emit_full (const ucl_object_t *obj, enum ucl_emitter emit_type,
694
struct ucl_emitter_functions *emitter,
695
const ucl_object_t *comments)
696
{
697
const struct ucl_emitter_context *ctx;
698
struct ucl_emitter_context my_ctx;
699
bool res = false;
700
701
ctx = ucl_emit_get_standard_context (emit_type);
702
if (ctx != NULL) {
703
memcpy (&my_ctx, ctx, sizeof (my_ctx));
704
my_ctx.func = emitter;
705
my_ctx.indent = 0;
706
my_ctx.top = obj;
707
my_ctx.comments = comments;
708
709
my_ctx.ops->ucl_emitter_write_elt (&my_ctx, obj, true, false);
710
res = true;
711
}
712
713
return res;
714
}
715
716