Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/external/libucl/src/ucl_internal.h
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
#ifndef UCL_INTERNAL_H_
25
#define UCL_INTERNAL_H_
26
27
#ifdef HAVE_CONFIG_H
28
#include "config.h"
29
#else
30
/* Help embedded builds */
31
#define HAVE_SYS_TYPES_H
32
#define HAVE_SYS_MMAN_H
33
#define HAVE_SYS_STAT_H
34
#define HAVE_SYS_PARAM_H
35
#define HAVE_LIMITS_H
36
#define HAVE_FCNTL_H
37
#define HAVE_ERRNO_H
38
#define HAVE_UNISTD_H
39
#define HAVE_CTYPE_H
40
#define HAVE_STDIO_H
41
#define HAVE_STRING_H
42
#define HAVE_FLOAT_H
43
#define HAVE_LIBGEN_H
44
#define HAVE_MATH_H
45
#define HAVE_STDBOOL_H
46
#define HAVE_STDINT_H
47
#define HAVE_STDARG_H
48
#ifndef _WIN32
49
# define HAVE_REGEX_H
50
#endif
51
#endif
52
53
#ifdef HAVE_SYS_TYPES_H
54
#include <sys/types.h>
55
#endif
56
57
#ifdef HAVE_SYS_MMAN_H
58
# ifndef _WIN32
59
# include <sys/mman.h>
60
# endif
61
#endif
62
#ifdef HAVE_SYS_STAT_H
63
#include <sys/stat.h>
64
#endif
65
#ifdef HAVE_SYS_PARAM_H
66
# ifndef _WIN32
67
# include <sys/param.h>
68
# endif
69
#endif
70
71
#ifdef HAVE_LIMITS_H
72
#include <limits.h>
73
#endif
74
#ifdef HAVE_FCNTL_H
75
#include <fcntl.h>
76
#endif
77
#ifdef HAVE_ERRNO_H
78
#include <errno.h>
79
#endif
80
#ifdef HAVE_UNISTD_H
81
# ifndef _WIN32
82
# include <unistd.h>
83
# endif
84
#endif
85
#ifdef HAVE_CTYPE_H
86
#include <ctype.h>
87
#endif
88
#ifdef HAVE_STDIO_H
89
#include <stdio.h>
90
#endif
91
#ifdef HAVE_STRING_H
92
#include <string.h>
93
#endif
94
#ifdef HAVE_STRINGS_H
95
#include <strings.h>
96
#endif
97
98
#if defined(_MSC_VER)
99
/* Windows hacks */
100
#include <BaseTsd.h>
101
#include <inttypes.h>
102
typedef SSIZE_T ssize_t;
103
#define strdup _strdup
104
#define snprintf _snprintf
105
#define vsnprintf _vsnprintf
106
#define strcasecmp _stricmp
107
#define strncasecmp _strnicmp
108
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
109
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
110
#if _MSC_VER >= 1900
111
#include <../ucrt/stdlib.h>
112
#else
113
#include <../include/stdlib.h>
114
#endif
115
#ifndef PATH_MAX
116
#define PATH_MAX _MAX_PATH
117
#endif
118
119
/* Dirname, basename implementations */
120
121
122
#endif
123
124
#include "utlist.h"
125
#include "utstring.h"
126
#include "uthash.h"
127
#include "ucl.h"
128
#include "ucl_hash.h"
129
130
#ifdef HAVE_OPENSSL
131
#include <openssl/evp.h>
132
#endif
133
134
#ifndef __DECONST
135
#define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
136
#endif
137
138
/**
139
* @file rcl_internal.h
140
* Internal structures and functions of UCL library
141
*/
142
143
#define UCL_MAX_RECURSION 16
144
#define UCL_TRASH_KEY 0
145
#define UCL_TRASH_VALUE 1
146
147
enum ucl_parser_state {
148
UCL_STATE_INIT = 0,
149
UCL_STATE_OBJECT,
150
UCL_STATE_ARRAY,
151
UCL_STATE_KEY,
152
UCL_STATE_KEY_OBRACE,
153
UCL_STATE_VALUE,
154
UCL_STATE_AFTER_VALUE,
155
UCL_STATE_ARRAY_VALUE,
156
UCL_STATE_SCOMMENT,
157
UCL_STATE_MCOMMENT,
158
UCL_STATE_MACRO_NAME,
159
UCL_STATE_MACRO,
160
UCL_STATE_ERROR
161
};
162
163
enum ucl_character_type {
164
UCL_CHARACTER_DENIED = (1 << 0),
165
UCL_CHARACTER_KEY = (1 << 1),
166
UCL_CHARACTER_KEY_START = (1 << 2),
167
UCL_CHARACTER_WHITESPACE = (1 << 3),
168
UCL_CHARACTER_WHITESPACE_UNSAFE = (1 << 4),
169
UCL_CHARACTER_VALUE_END = (1 << 5),
170
UCL_CHARACTER_VALUE_STR = (1 << 6),
171
UCL_CHARACTER_VALUE_DIGIT = (1 << 7),
172
UCL_CHARACTER_VALUE_DIGIT_START = (1 << 8),
173
UCL_CHARACTER_ESCAPE = (1 << 9),
174
UCL_CHARACTER_KEY_SEP = (1 << 10),
175
UCL_CHARACTER_JSON_UNSAFE = (1 << 11),
176
UCL_CHARACTER_UCL_UNSAFE = (1 << 12)
177
};
178
179
struct ucl_macro {
180
char *name;
181
union _ucl_macro {
182
ucl_macro_handler handler;
183
ucl_context_macro_handler context_handler;
184
} h;
185
void* ud;
186
bool is_context;
187
UT_hash_handle hh;
188
};
189
190
enum ucl_stack_flags {
191
UCL_STACK_HAS_OBRACE = (1u << 0),
192
UCL_STACK_MAX = (1u << 1),
193
};
194
195
struct ucl_stack {
196
ucl_object_t *obj;
197
struct ucl_stack *next;
198
union {
199
struct {
200
uint16_t level;
201
uint16_t flags;
202
uint32_t line;
203
} params;
204
uint64_t len;
205
} e;
206
struct ucl_chunk *chunk;
207
};
208
209
struct ucl_parser_special_handler_chain {
210
unsigned char *begin;
211
size_t len;
212
struct ucl_parser_special_handler *special_handler;
213
struct ucl_parser_special_handler_chain *next;
214
};
215
216
struct ucl_chunk {
217
const unsigned char *begin;
218
const unsigned char *end;
219
const unsigned char *pos;
220
char *fname;
221
size_t remain;
222
unsigned int line;
223
unsigned int column;
224
unsigned priority;
225
enum ucl_duplicate_strategy strategy;
226
enum ucl_parse_type parse_type;
227
struct ucl_parser_special_handler_chain *special_handlers;
228
struct ucl_chunk *next;
229
};
230
231
#ifdef HAVE_OPENSSL
232
struct ucl_pubkey {
233
EVP_PKEY *key;
234
struct ucl_pubkey *next;
235
};
236
#else
237
struct ucl_pubkey {
238
struct ucl_pubkey *next;
239
};
240
#endif
241
242
struct ucl_variable {
243
char *var;
244
char *value;
245
size_t var_len;
246
size_t value_len;
247
struct ucl_variable *prev, *next;
248
};
249
250
struct ucl_parser {
251
enum ucl_parser_state state;
252
enum ucl_parser_state prev_state;
253
unsigned int recursion;
254
int flags;
255
unsigned default_priority;
256
int err_code;
257
ucl_object_t *top_obj;
258
ucl_object_t *cur_obj;
259
ucl_object_t *trash_objs;
260
ucl_object_t *includepaths;
261
char *cur_file;
262
struct ucl_macro *macroes;
263
struct ucl_stack *stack;
264
struct ucl_chunk *chunks;
265
struct ucl_pubkey *keys;
266
struct ucl_parser_special_handler *special_handlers;
267
ucl_include_trace_func_t *include_trace_func;
268
void *include_trace_ud;
269
struct ucl_variable *variables;
270
ucl_variable_handler var_handler;
271
void *var_data;
272
ucl_object_t *comments;
273
ucl_object_t *last_comment;
274
UT_string *err;
275
};
276
277
struct ucl_object_userdata {
278
ucl_object_t obj;
279
ucl_userdata_dtor dtor;
280
ucl_userdata_emitter emitter;
281
};
282
283
/**
284
* Unescape json string inplace
285
* @param str
286
*/
287
size_t ucl_unescape_json_string (char *str, size_t len);
288
289
290
/**
291
* Unescape single quoted string inplace
292
* @param str
293
*/
294
size_t ucl_unescape_squoted_string (char *str, size_t len);
295
296
/**
297
* Handle include macro
298
* @param data include data
299
* @param len length of data
300
* @param args UCL object representing arguments to the macro
301
* @param ud user data
302
* @return
303
*/
304
bool ucl_include_handler (const unsigned char *data, size_t len,
305
const ucl_object_t *args, void* ud);
306
307
/**
308
* Handle tryinclude macro
309
* @param data include data
310
* @param len length of data
311
* @param args UCL object representing arguments to the macro
312
* @param ud user data
313
* @return
314
*/
315
bool ucl_try_include_handler (const unsigned char *data, size_t len,
316
const ucl_object_t *args, void* ud);
317
318
/**
319
* Handle includes macro
320
* @param data include data
321
* @param len length of data
322
* @param args UCL object representing arguments to the macro
323
* @param ud user data
324
* @return
325
*/
326
bool ucl_includes_handler (const unsigned char *data, size_t len,
327
const ucl_object_t *args, void* ud);
328
329
/**
330
* Handle priority macro
331
* @param data include data
332
* @param len length of data
333
* @param args UCL object representing arguments to the macro
334
* @param ud user data
335
* @return
336
*/
337
bool ucl_priority_handler (const unsigned char *data, size_t len,
338
const ucl_object_t *args, void* ud);
339
340
/**
341
* Handle load macro
342
* @param data include data
343
* @param len length of data
344
* @param args UCL object representing arguments to the macro
345
* @param ud user data
346
* @return
347
*/
348
bool ucl_load_handler (const unsigned char *data, size_t len,
349
const ucl_object_t *args, void* ud);
350
/**
351
* Handle inherit macro
352
* @param data include data
353
* @param len length of data
354
* @param args UCL object representing arguments to the macro
355
* @param ctx the current context object
356
* @param ud user data
357
* @return
358
*/
359
bool ucl_inherit_handler (const unsigned char *data, size_t len,
360
const ucl_object_t *args, const ucl_object_t *ctx, void* ud);
361
362
size_t ucl_strlcpy (char *dst, const char *src, size_t siz);
363
size_t ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz);
364
size_t ucl_strlcpy_tolower (char *dst, const char *src, size_t siz);
365
366
char *ucl_strnstr (const char *s, const char *find, int len);
367
char *ucl_strncasestr (const char *s, const char *find, int len);
368
369
#ifdef __GNUC__
370
static inline void
371
ucl_create_err (UT_string **err, const char *fmt, ...)
372
__attribute__ (( format( printf, 2, 3) ));
373
#endif
374
375
#undef UCL_FATAL_ERRORS
376
377
static inline void
378
ucl_create_err (UT_string **err, const char *fmt, ...)
379
{
380
if (*err == NULL) {
381
utstring_new (*err);
382
va_list ap;
383
va_start (ap, fmt);
384
utstring_printf_va (*err, fmt, ap);
385
va_end (ap);
386
}
387
388
#ifdef UCL_FATAL_ERRORS
389
assert (0);
390
#endif
391
}
392
393
/**
394
* Check whether a given string contains a boolean value
395
* @param obj object to set
396
* @param start start of a string
397
* @param len length of a string
398
* @return true if a string is a boolean value
399
*/
400
static inline bool
401
ucl_maybe_parse_boolean (ucl_object_t *obj, const unsigned char *start, size_t len)
402
{
403
const char *p = (const char *)start;
404
bool ret = false, val = false;
405
406
if (len == 5) {
407
if ((p[0] == 'f' || p[0] == 'F') && strncasecmp (p, "false", 5) == 0) {
408
ret = true;
409
val = false;
410
}
411
}
412
else if (len == 4) {
413
if ((p[0] == 't' || p[0] == 'T') && strncasecmp (p, "true", 4) == 0) {
414
ret = true;
415
val = true;
416
}
417
}
418
else if (len == 3) {
419
if ((p[0] == 'y' || p[0] == 'Y') && strncasecmp (p, "yes", 3) == 0) {
420
ret = true;
421
val = true;
422
}
423
else if ((p[0] == 'o' || p[0] == 'O') && strncasecmp (p, "off", 3) == 0) {
424
ret = true;
425
val = false;
426
}
427
}
428
else if (len == 2) {
429
if ((p[0] == 'n' || p[0] == 'N') && strncasecmp (p, "no", 2) == 0) {
430
ret = true;
431
val = false;
432
}
433
else if ((p[0] == 'o' || p[0] == 'O') && strncasecmp (p, "on", 2) == 0) {
434
ret = true;
435
val = true;
436
}
437
}
438
439
if (ret && obj != NULL) {
440
obj->type = UCL_BOOLEAN;
441
obj->value.iv = val;
442
}
443
444
return ret;
445
}
446
447
/**
448
* Check numeric string
449
* @param obj object to set if a string is numeric
450
* @param start start of string
451
* @param end end of string
452
* @param pos position where parsing has stopped
453
* @param allow_double allow parsing of floating point values
454
* @return 0 if string is numeric and error code (EINVAL or ERANGE) in case of conversion error
455
*/
456
int ucl_maybe_parse_number (ucl_object_t *obj,
457
const char *start, const char *end, const char **pos,
458
bool allow_double, bool number_bytes, bool allow_time);
459
460
461
static inline const ucl_object_t *
462
ucl_hash_search_obj (ucl_hash_t* hashlin, ucl_object_t *obj)
463
{
464
return (const ucl_object_t *)ucl_hash_search (hashlin, obj->key, obj->keylen);
465
}
466
467
static inline ucl_hash_t * ucl_hash_insert_object (ucl_hash_t *hashlin,
468
const ucl_object_t *obj,
469
bool ignore_case) UCL_WARN_UNUSED_RESULT;
470
471
static inline ucl_hash_t *
472
ucl_hash_insert_object (ucl_hash_t *hashlin,
473
const ucl_object_t *obj,
474
bool ignore_case)
475
{
476
ucl_hash_t *nhp;
477
478
if (hashlin == NULL) {
479
nhp = ucl_hash_create (ignore_case);
480
if (nhp == NULL) {
481
return NULL;
482
}
483
} else {
484
nhp = hashlin;
485
}
486
if (!ucl_hash_insert (nhp, obj, obj->key, obj->keylen)) {
487
if (nhp != hashlin) {
488
ucl_hash_destroy(nhp, NULL);
489
}
490
return NULL;
491
}
492
493
return nhp;
494
}
495
496
/**
497
* Get standard emitter context for a specified emit_type
498
* @param emit_type type of emitter
499
* @return context or NULL if input is invalid
500
*/
501
const struct ucl_emitter_context *
502
ucl_emit_get_standard_context (enum ucl_emitter emit_type);
503
504
/**
505
* Serialize string as JSON string
506
* @param str string to emit
507
* @param buf target buffer
508
*/
509
void ucl_elt_string_write_json (const char *str, size_t size,
510
struct ucl_emitter_context *ctx);
511
512
513
/**
514
* Serialize string as single quoted string
515
* @param str string to emit
516
* @param buf target buffer
517
*/
518
void
519
ucl_elt_string_write_squoted (const char *str, size_t size,
520
struct ucl_emitter_context *ctx);
521
522
/**
523
* Write multiline string using `EOD` as string terminator
524
* @param str
525
* @param size
526
* @param ctx
527
*/
528
void ucl_elt_string_write_multiline (const char *str, size_t size,
529
struct ucl_emitter_context *ctx);
530
531
/**
532
* Emit a single object to string
533
* @param obj
534
* @return
535
*/
536
unsigned char * ucl_object_emit_single_json (const ucl_object_t *obj);
537
538
/**
539
* Check whether a specified string is long and should be likely printed in
540
* multiline mode
541
* @param obj
542
* @return
543
*/
544
bool ucl_maybe_long_string (const ucl_object_t *obj);
545
546
/**
547
* Print integer to the msgpack output
548
* @param ctx
549
* @param val
550
*/
551
void ucl_emitter_print_int_msgpack (struct ucl_emitter_context *ctx,
552
int64_t val);
553
/**
554
* Print integer to the msgpack output
555
* @param ctx
556
* @param val
557
*/
558
void ucl_emitter_print_double_msgpack (struct ucl_emitter_context *ctx,
559
double val);
560
/**
561
* Print double to the msgpack output
562
* @param ctx
563
* @param val
564
*/
565
void ucl_emitter_print_bool_msgpack (struct ucl_emitter_context *ctx,
566
bool val);
567
/**
568
* Print string to the msgpack output
569
* @param ctx
570
* @param s
571
* @param len
572
*/
573
void ucl_emitter_print_string_msgpack (struct ucl_emitter_context *ctx,
574
const char *s, size_t len);
575
576
/**
577
* Print binary string to the msgpack output
578
* @param ctx
579
* @param s
580
* @param len
581
*/
582
void ucl_emitter_print_binary_string_msgpack (struct ucl_emitter_context *ctx,
583
const char *s, size_t len);
584
585
/**
586
* Print array preamble for msgpack
587
* @param ctx
588
* @param len
589
*/
590
void ucl_emitter_print_array_msgpack (struct ucl_emitter_context *ctx,
591
size_t len);
592
593
/**
594
* Print object preamble for msgpack
595
* @param ctx
596
* @param len
597
*/
598
void ucl_emitter_print_object_msgpack (struct ucl_emitter_context *ctx,
599
size_t len);
600
/**
601
* Print NULL to the msgpack output
602
* @param ctx
603
*/
604
void ucl_emitter_print_null_msgpack (struct ucl_emitter_context *ctx);
605
/**
606
* Print object's key if needed to the msgpack output
607
* @param print_key
608
* @param ctx
609
* @param obj
610
*/
611
void ucl_emitter_print_key_msgpack (bool print_key,
612
struct ucl_emitter_context *ctx,
613
const ucl_object_t *obj);
614
615
/**
616
* Fetch URL into a buffer
617
* @param url url to fetch
618
* @param buf pointer to buffer (must be freed by callee)
619
* @param buflen pointer to buffer length
620
* @param err pointer to error argument
621
* @param must_exist fail if cannot find a url
622
*/
623
bool ucl_fetch_url (const unsigned char *url,
624
unsigned char **buf,
625
size_t *buflen,
626
UT_string **err,
627
bool must_exist);
628
629
/**
630
* Fetch a file and save results to the memory buffer
631
* @param filename filename to fetch
632
* @param len length of filename
633
* @param buf target buffer
634
* @param buflen target length
635
* @return
636
*/
637
bool ucl_fetch_file (const unsigned char *filename,
638
unsigned char **buf,
639
size_t *buflen,
640
UT_string **err,
641
bool must_exist);
642
643
/**
644
* Add new element to an object using the current merge strategy and priority
645
* @param parser
646
* @param nobj
647
* @return
648
*/
649
bool ucl_parser_process_object_element (struct ucl_parser *parser,
650
ucl_object_t *nobj);
651
652
/**
653
* Parse msgpack chunk
654
* @param parser
655
* @return
656
*/
657
bool ucl_parse_msgpack (struct ucl_parser *parser);
658
659
bool ucl_parse_csexp (struct ucl_parser *parser);
660
661
/**
662
* Free ucl chunk
663
* @param chunk
664
*/
665
void ucl_chunk_free (struct ucl_chunk *chunk);
666
667
#endif /* UCL_INTERNAL_H_ */
668
669