#include "uthash.h"
#include "utlist.h"
-#include "utstring.h"
/**
* @file rcl.h
UCL_ESSL //!< UCL_ESSL
};
+/**
+ * Object types
+ */
enum ucl_type {
- UCL_OBJECT = 0,
- UCL_ARRAY,
- UCL_INT,
- UCL_FLOAT,
- UCL_STRING,
- UCL_BOOLEAN,
- UCL_TIME,
- UCL_USERDATA
+ UCL_OBJECT = 0,//!< UCL_OBJECT
+ UCL_ARRAY, //!< UCL_ARRAY
+ UCL_INT, //!< UCL_INT
+ UCL_FLOAT, //!< UCL_FLOAT
+ UCL_STRING, //!< UCL_STRING
+ UCL_BOOLEAN, //!< UCL_BOOLEAN
+ UCL_TIME, //!< UCL_TIME
+ UCL_USERDATA //!< UCL_USERDATA
};
+/**
+ * Emitting types
+ */
enum ucl_emitter {
- UCL_EMIT_JSON = 0,
- UCL_EMIT_JSON_COMPACT,
- UCL_EMIT_CONFIG,
- UCL_EMIT_YAML
+ UCL_EMIT_JSON = 0, //!< UCL_EMIT_JSON
+ UCL_EMIT_JSON_COMPACT,//!< UCL_EMIT_JSON_COMPACT
+ UCL_EMIT_CONFIG, //!< UCL_EMIT_CONFIG
+ UCL_EMIT_YAML //!< UCL_EMIT_YAML
+};
+
+/**
+ * Parsing flags
+ */
+enum ucl_parser_flags {
+ UCL_PARSER_KEY_LOWERCASE = 0x1,//!< UCL_FLAG_KEY_LOWERCASE
+ UCL_PARSER_ZEROCOPY = 0x2 //!< UCL_FLAG_ZEROCOPY
+};
+
+/**
+ * String conversion flags
+ */
+enum ucl_string_flags {
+ UCL_STRING_ESCAPE = 0x1, /**< UCL_STRING_ESCAPE perform JSON escape */
+ UCL_STRING_TRIM = 0x2, /**< UCL_STRING_TRIM trim leading and trailing whitespaces */
+ UCL_STRING_PARSE_BOOLEAN = 0x4, /**< UCL_STRING_PARSE_BOOLEAN parse passed string and detect boolean */
+ UCL_STRING_PARSE_INT = 0x8, /**< UCL_STRING_PARSE_INT parse passed string and detect integer number */
+ UCL_STRING_PARSE_DOUBLE = 0x10, /**< UCL_STRING_PARSE_DOUBLE parse passed string and detect integer or float number */
+ UCL_STRING_PARSE_NUMBER = UCL_STRING_PARSE_INT|UCL_STRING_PARSE_DOUBLE , /**<
+ UCL_STRING_PARSE_NUMBER parse passed string and detect number */
+ UCL_STRING_PARSE = UCL_STRING_PARSE_BOOLEAN|UCL_STRING_PARSE_NUMBER /**<
+ UCL_STRING_PARSE parse passed string (and detect booleans and numbers) */
};
-enum ucl_flags {
- UCL_FLAG_KEY_LOWERCASE = 0x1,
- UCL_FLAG_ZEROCOPY = 0x2
+/**
+ * Basic flags for an object
+ */
+enum ucl_object_flags {
+ UCL_OBJECT_ALLOCATED_KEY = 1, //!< UCL_OBJECT_ALLOCATED_KEY
+ UCL_OBJECT_ALLOCATED_VALUE = 2, //!< UCL_OBJECT_ALLOCATED_VALUE
+ UCL_OBJECT_NEED_KEY_ESCAPE = 4 //!< UCL_OBJECT_NEED_KEY_ESCAPE
};
+/**
+ * UCL object
+ */
typedef struct ucl_object_s {
union {
int64_t iv; /**< int value of an object */
void* ud; /**< opaque user data */
} value;
enum ucl_type type; /**< real type */
- int ref; /**< reference count */
+ short int ref; /**< reference count */
+ short int flags; /**< object flags */
size_t len; /**< size of an object */
struct ucl_object_s *next; /**< array handle */
struct ucl_object_s *prev; /**< array handle */
return new;
}
-/**
- * String conversion flags
- */
-enum ucl_string_flags {
- UCL_STRING_ESCAPE = 0x1, /**< UCL_STRING_ESCAPE perform JSON escape */
- UCL_STRING_TRIM = 0x2, /**< UCL_STRING_TRIM trim leading and trailing whitespaces */
- UCL_STRING_PARSE_BOOLEAN = 0x4, /**< UCL_STRING_PARSE_BOOLEAN parse passed string and detect boolean */
- UCL_STRING_PARSE_INT = 0x8, /**< UCL_STRING_PARSE_INT parse passed string and detect integer number */
- UCL_STRING_PARSE_DOUBLE = 0x10, /**< UCL_STRING_PARSE_DOUBLE parse passed string and detect integer or float number */
- UCL_STRING_PARSE_NUMBER = UCL_STRING_PARSE_INT|UCL_STRING_PARSE_DOUBLE , /**<
- UCL_STRING_PARSE_NUMBER parse passed string and detect number */
- UCL_STRING_PARSE = UCL_STRING_PARSE_BOOLEAN|UCL_STRING_PARSE_NUMBER /**<
- UCL_STRING_PARSE parse passed string (and detect booleans and numbers) */
-};
-
/**
* Convert any string to an ucl object making the specified transformations
* @param str fixed size or NULL terminated string
* @param copy_key make an internal copy of key
* @return new value of top object
*/
-static inline ucl_object_t *
-ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt,
- const char *key, size_t keylen, bool copy_key)
-{
- ucl_object_t *found;
-
- if (elt == NULL || key == NULL) {
- return NULL;
- }
-
- if (top == NULL) {
- top = ucl_object_new ();
- top->type = UCL_OBJECT;
- }
- if (keylen == 0) {
- keylen = strlen (key);
- }
-
- HASH_FIND (hh, top->value.ov, key, keylen, found);
-
- if (!found) {
- HASH_ADD_KEYPTR (hh, top->value.ov, key, keylen, elt);
- }
- DL_APPEND (found, elt);
-
- if (copy_key) {
- ucl_copy_key_trash (elt);
- }
-
- return top;
-}
+ucl_object_t* ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt,
+ const char *key, size_t keylen, bool copy_key);
/**
* Append an element to the array object
* @param err error pointer
* @return true if macro has been parsed
*/
-typedef bool (*ucl_macro_handler) (const unsigned char *data, size_t len, void* ud, UT_string **err);
+typedef bool (*ucl_macro_handler) (const unsigned char *data, size_t len, void* ud);
/* Opaque parser */
struct ucl_parser;
* @param err if *err is NULL it is set to parser error
* @return true if chunk has been added and false in case of error
*/
-bool ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data,
- size_t len, UT_string **err);
+bool ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, size_t len);
/**
* Load and add data from a file
* @param err if *err is NULL it is set to parser error
* @return true if chunk has been added and false in case of error
*/
-bool ucl_parser_add_file (struct ucl_parser *parser, const char *filename,
- UT_string **err);
+bool ucl_parser_add_file (struct ucl_parser *parser, const char *filename);
/**
* Get a top object for a parser
* @param err if *err is NULL it is set to parser error
* @return top parser object or NULL
*/
-ucl_object_t* ucl_parser_get_object (struct ucl_parser *parser, UT_string **err);
+ucl_object_t* ucl_parser_get_object (struct ucl_parser *parser);
+/**
+ * Get the error string if failing
+ * @param parser parser object
+ */
+const char *ucl_parser_get_error(struct ucl_parser *parser);
/**
* Free cl parser object
* @param parser parser object
* @param err if *err is NULL it is set to parser error
* @return true if a key has been successfully added
*/
-bool ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len, UT_string **err);
+bool ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len);
#endif /* RCL_H_ */
static const unsigned int ucl_chartable[255] = {
UCL_CHARACTER_VALUE_END, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
-UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_JSON_UNSAFE,
-UCL_CHARACTER_WHITESPACE|UCL_CHARACTER_WHITESPACE_UNSAFE|UCL_CHARACTER_KEY_SEP|UCL_CHARACTER_JSON_UNSAFE,
-UCL_CHARACTER_WHITESPACE_UNSAFE|UCL_CHARACTER_VALUE_END|UCL_CHARACTER_JSON_UNSAFE,
+UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
+UCL_CHARACTER_JSON_UNSAFE|UCL_CHARACTER_UCL_UNSAFE,
+UCL_CHARACTER_WHITESPACE|UCL_CHARACTER_WHITESPACE_UNSAFE|UCL_CHARACTER_KEY_SEP|UCL_CHARACTER_JSON_UNSAFE|UCL_CHARACTER_UCL_UNSAFE,
+UCL_CHARACTER_WHITESPACE_UNSAFE|UCL_CHARACTER_VALUE_END|UCL_CHARACTER_JSON_UNSAFE|UCL_CHARACTER_UCL_UNSAFE,
UCL_CHARACTER_WHITESPACE_UNSAFE,
-UCL_CHARACTER_WHITESPACE_UNSAFE|UCL_CHARACTER_JSON_UNSAFE,
-UCL_CHARACTER_WHITESPACE_UNSAFE|UCL_CHARACTER_VALUE_END|UCL_CHARACTER_JSON_UNSAFE,
+UCL_CHARACTER_WHITESPACE_UNSAFE|UCL_CHARACTER_JSON_UNSAFE|UCL_CHARACTER_UCL_UNSAFE,
+UCL_CHARACTER_WHITESPACE_UNSAFE|UCL_CHARACTER_VALUE_END|UCL_CHARACTER_JSON_UNSAFE|UCL_CHARACTER_UCL_UNSAFE,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
-UCL_CHARACTER_WHITESPACE|UCL_CHARACTER_WHITESPACE_UNSAFE|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_KEY_SEP /* */,
+UCL_CHARACTER_WHITESPACE|UCL_CHARACTER_WHITESPACE_UNSAFE|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_KEY_SEP|UCL_CHARACTER_UCL_UNSAFE /* */,
UCL_CHARACTER_VALUE_STR /* ! */,
-UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_ESCAPE|UCL_CHARACTER_JSON_UNSAFE /* " */,
+UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_ESCAPE|UCL_CHARACTER_JSON_UNSAFE|UCL_CHARACTER_UCL_UNSAFE /* " */,
UCL_CHARACTER_VALUE_END /* # */, UCL_CHARACTER_VALUE_STR /* $ */,
UCL_CHARACTER_VALUE_STR /* % */, UCL_CHARACTER_VALUE_STR /* & */,
UCL_CHARACTER_VALUE_STR /* ' */, UCL_CHARACTER_VALUE_STR /* ( */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT_START|UCL_CHARACTER_VALUE_DIGIT /* 7 */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT_START|UCL_CHARACTER_VALUE_DIGIT /* 8 */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT_START|UCL_CHARACTER_VALUE_DIGIT /* 9 */,
-UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_KEY_SEP /* : */,
+UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_KEY_SEP|UCL_CHARACTER_UCL_UNSAFE /* : */,
UCL_CHARACTER_VALUE_END /* ; */, UCL_CHARACTER_VALUE_STR /* < */,
-UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_KEY_SEP /* = */,
+UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_KEY_SEP|UCL_CHARACTER_UCL_UNSAFE /* = */,
UCL_CHARACTER_VALUE_STR /* > */, UCL_CHARACTER_VALUE_STR /* ? */,
UCL_CHARACTER_VALUE_STR /* @ */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* A */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* X */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* Y */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* Z */,
-UCL_CHARACTER_VALUE_STR /* [ */,
-UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_ESCAPE|UCL_CHARACTER_JSON_UNSAFE /* \ */,
+UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_UCL_UNSAFE /* [ */,
+UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_ESCAPE|UCL_CHARACTER_JSON_UNSAFE|UCL_CHARACTER_UCL_UNSAFE /* \ */,
UCL_CHARACTER_VALUE_END /* ] */, UCL_CHARACTER_VALUE_STR /* ^ */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR /* _ */,
UCL_CHARACTER_VALUE_STR /* ` */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* x */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* y */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* z */,
-UCL_CHARACTER_VALUE_STR /* { */, UCL_CHARACTER_VALUE_STR /* | */,
-UCL_CHARACTER_VALUE_END /* } */, UCL_CHARACTER_VALUE_STR /* ~ */,
-UCL_CHARACTER_DENIED,
+UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_UCL_UNSAFE /* { */,
+UCL_CHARACTER_VALUE_STR /* | */, UCL_CHARACTER_VALUE_END /* } */,
+UCL_CHARACTER_VALUE_STR /* ~ */, UCL_CHARACTER_DENIED,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
HASH_ITER (hh, obj, cur, tmp) {
ucl_add_tabs (buf, tabs + 1, is_top);
- utstring_append_len (buf, cur->hh.key, cur->hh.keylen);
+ if (cur->flags & UCL_OBJECT_NEED_KEY_ESCAPE) {
+ ucl_elt_string_write_json (cur->hh.key, cur->hh.keylen, buf);
+ }
+ else {
+ utstring_append_len (buf, cur->hh.key, cur->hh.keylen);
+ }
if (cur->type != UCL_OBJECT && cur->type != UCL_ARRAY) {
utstring_append_len (buf, " = ", 3);
}
HASH_ITER (hh, obj, cur, tmp) {
ucl_add_tabs (buf, tabs + 1, is_top);
- utstring_append_len (buf, cur->hh.key, cur->hh.keylen);
+ if (obj->flags & UCL_OBJECT_NEED_KEY_ESCAPE) {
+ ucl_elt_string_write_json (cur->hh.key, cur->hh.keylen, buf);
+ }
+ else {
+ utstring_append_len (buf, cur->hh.key, cur->hh.keylen);
+ }
if (cur->type != UCL_OBJECT && cur->type != UCL_ARRAY) {
utstring_append_len (buf, " : ", 3);
}
#include <ctype.h>
#include "utlist.h"
+#include "utstring.h"
#include "ucl.h"
#ifdef HAVE_OPENSSL
UCL_CHARACTER_VALUE_DIGIT_START = 1 << 7,
UCL_CHARACTER_ESCAPE = 1 << 8,
UCL_CHARACTER_KEY_SEP = 1 << 9,
- UCL_CHARACTER_JSON_UNSAFE = 1 << 10
+ UCL_CHARACTER_JSON_UNSAFE = 1 << 10,
+ UCL_CHARACTER_UCL_UNSAFE = 1 << 11
};
struct ucl_macro {
struct ucl_stack *stack;
struct ucl_chunk *chunks;
struct ucl_pubkey *keys;
+ UT_string *err;
};
/**
* @param err error ptr
* @return
*/
-bool ucl_include_handler (const unsigned char *data, size_t len, void* ud, UT_string **err);
+bool ucl_include_handler (const unsigned char *data, size_t len, void* ud);
/**
* Handle includes macro
* @param err error ptr
* @return
*/
-bool ucl_includes_handler (const unsigned char *data, size_t len, void* ud, UT_string **err);
+bool ucl_includes_handler (const unsigned char *data, size_t len, void* ud);
size_t ucl_strlcpy (char *dst, const char *src, size_t siz);
size_t ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz);
}
static bool
-ucl_skip_comments (struct ucl_parser *parser, UT_string **err)
+ucl_skip_comments (struct ucl_parser *parser)
{
struct ucl_chunk *chunk = parser->chunks;
const unsigned char *p;
ucl_chunk_skipc (chunk, p);
}
if (comments_nested != 0) {
- ucl_set_err (chunk, UCL_ENESTED, "comments nesting is invalid", err);
+ ucl_set_err (chunk, UCL_ENESTED, "comments nesting is invalid", &parser->err);
return false;
}
}
ucl_copy_or_store_ptr (struct ucl_parser *parser,
const unsigned char *src, unsigned char **dst,
const char **dst_const, size_t in_len,
- bool need_unescape, bool need_lowercase, UT_string **err)
+ bool need_unescape, bool need_lowercase)
{
size_t ret = 0;
- if (need_unescape || need_lowercase || !(parser->flags & UCL_FLAG_ZEROCOPY)) {
+ if (need_unescape || need_lowercase || !(parser->flags & UCL_PARSER_ZEROCOPY)) {
/* Copy string */
*dst = UCL_ALLOC (in_len + 1);
if (*dst == NULL) {
- ucl_set_err (parser->chunks, 0, "cannot allocate memory for a string", err);
+ ucl_set_err (parser->chunks, 0, "cannot allocate memory for a string", &parser->err);
return false;
}
if (need_lowercase) {
{
const char *p = start, *c = start;
char *endptr;
- bool got_dot = false, got_exp = false, need_double = false, is_date = false;
+ bool got_dot = false, got_exp = false, need_double = false, is_date = false, valid_start = false;
double dv;
int64_t lv;
}
while (p < end) {
if (isdigit (*p)) {
+ valid_start = true;
p ++;
}
else if (allow_double) {
}
}
+ if (!valid_start) {
+ *pos = start;
+ return EINVAL;
+ }
+
errno = 0;
if (need_double) {
dv = strtod (c, &endptr);
goto set_obj;
}
- if (endptr < end) {
+ if (endptr < end && endptr != start) {
p = endptr;
switch (*p) {
case 'm':
* Parse possible number
* @param parser
* @param chunk
- * @param err
* @return true if a number has been parsed
*/
static bool
ucl_lex_number (struct ucl_parser *parser,
- struct ucl_chunk *chunk, ucl_object_t *obj, UT_string **err)
+ struct ucl_chunk *chunk, ucl_object_t *obj)
{
const unsigned char *pos;
int ret;
return true;
}
else if (ret == ERANGE) {
- ucl_set_err (chunk, ERANGE, "numeric value out of range", err);
+ ucl_set_err (chunk, ERANGE, "numeric value out of range", &parser->err);
}
return false;
* Parse quoted string with possible escapes
* @param parser
* @param chunk
- * @param err
* @return true if a string has been parsed
*/
static bool
ucl_lex_json_string (struct ucl_parser *parser,
- struct ucl_chunk *chunk, bool *need_unescape, UT_string **err)
+ struct ucl_chunk *chunk, bool *need_unescape, bool *ucl_escape)
{
const unsigned char *p = chunk->pos;
unsigned char c;
if (c < 0x1F) {
/* Unmasked control character */
if (c == '\n') {
- ucl_set_err (chunk, UCL_ESYNTAX, "unexpected newline", err);
+ ucl_set_err (chunk, UCL_ESYNTAX, "unexpected newline", &parser->err);
}
else {
- ucl_set_err (chunk, UCL_ESYNTAX, "unexpected control character", err);
+ ucl_set_err (chunk, UCL_ESYNTAX, "unexpected control character", &parser->err);
}
return false;
}
ucl_chunk_skipc (chunk, p);
c = *p;
if (p >= chunk->end) {
- ucl_set_err (chunk, UCL_ESYNTAX, "unfinished escape character", err);
+ ucl_set_err (chunk, UCL_ESYNTAX, "unfinished escape character", &parser->err);
return false;
}
else if (ucl_test_character (c, UCL_CHARACTER_ESCAPE)) {
ucl_chunk_skipc (chunk, p);
for (i = 0; i < 4 && p < chunk->end; i ++) {
if (!isxdigit (*p)) {
- ucl_set_err (chunk, UCL_ESYNTAX, "invalid utf escape", err);
+ ucl_set_err (chunk, UCL_ESYNTAX, "invalid utf escape", &parser->err);
return false;
}
ucl_chunk_skipc (chunk, p);
}
if (p >= chunk->end) {
- ucl_set_err (chunk, UCL_ESYNTAX, "unfinished escape character", err);
+ ucl_set_err (chunk, UCL_ESYNTAX, "unfinished escape character", &parser->err);
return false;
}
}
}
}
else {
- ucl_set_err (chunk, UCL_ESYNTAX, "invalid escape character", err);
+ ucl_set_err (chunk, UCL_ESYNTAX, "invalid escape character", &parser->err);
return false;
}
*need_unescape = true;
+ *ucl_escape = true;
continue;
}
else if (c == '"') {
ucl_chunk_skipc (chunk, p);
return true;
}
+ else if (ucl_test_character (c, UCL_CHARACTER_UCL_UNSAFE)) {
+ *ucl_escape = true;
+ }
ucl_chunk_skipc (chunk, p);
}
- ucl_set_err (chunk, UCL_ESYNTAX, "no quote at the end of json string", err);
+ ucl_set_err (chunk, UCL_ESYNTAX, "no quote at the end of json string", &parser->err);
return false;
}
* Parse a key in an object
* @param parser
* @param chunk
- * @param err
* @return true if a key has been parsed
*/
static bool
-ucl_parse_key (struct ucl_parser *parser,
- struct ucl_chunk *chunk, UT_string **err)
+ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk)
{
const unsigned char *p, *c = NULL, *end;
const char *key;
- bool got_quote = false, got_eq = false, got_semicolon = false, need_unescape = false;
+ bool got_quote = false, got_eq = false, got_semicolon = false,
+ need_unescape = false, ucl_escape = false;
ucl_object_t *nobj, *tobj, *container;
size_t keylen;
*/
if (c == NULL) {
if (ucl_lex_is_comment (p[0], p[1])) {
- if (!ucl_skip_comments (parser, err)) {
+ if (!ucl_skip_comments (parser)) {
return false;
}
p = chunk->pos;
}
else {
/* Invalid identifier */
- ucl_set_err (chunk, UCL_ESYNTAX, "key must begin with a letter", err);
+ ucl_set_err (chunk, UCL_ESYNTAX, "key must begin with a letter", &parser->err);
return false;
}
}
break;
}
else {
- ucl_set_err (chunk, UCL_ESYNTAX, "invalid character in a key", err);
+ ucl_set_err (chunk, UCL_ESYNTAX, "invalid character in a key", &parser->err);
return false;
}
}
else {
/* We need to parse json like quoted string */
- if (!ucl_lex_json_string (parser, chunk, &need_unescape, err)) {
+ if (!ucl_lex_json_string (parser, chunk, &need_unescape, &ucl_escape)) {
return false;
}
+ /* Always escape keys obtained via json */
end = chunk->pos - 1;
p = chunk->pos;
break;
}
if (p >= chunk->end) {
- ucl_set_err (chunk, UCL_ESYNTAX, "unfinished key", err);
+ ucl_set_err (chunk, UCL_ESYNTAX, "unfinished key", &parser->err);
return false;
}
got_eq = true;
}
else {
- ucl_set_err (chunk, UCL_ESYNTAX, "unexpected '=' character", err);
+ ucl_set_err (chunk, UCL_ESYNTAX, "unexpected '=' character", &parser->err);
return false;
}
}
got_semicolon = true;
}
else {
- ucl_set_err (chunk, UCL_ESYNTAX, "unexpected ':' character", err);
+ ucl_set_err (chunk, UCL_ESYNTAX, "unexpected ':' character", &parser->err);
return false;
}
}
else if (ucl_lex_is_comment (p[0], p[1])) {
/* Check for comment */
- if (!ucl_skip_comments (parser, err)) {
+ if (!ucl_skip_comments (parser)) {
return false;
}
p = chunk->pos;
}
if (p >= chunk->end) {
- ucl_set_err (chunk, UCL_ESYNTAX, "unfinished key", err);
+ ucl_set_err (chunk, UCL_ESYNTAX, "unfinished key", &parser->err);
return false;
}
/* Create a new object */
nobj = ucl_object_new ();
keylen = ucl_copy_or_store_ptr (parser, c, &nobj->trash_stack[UCL_TRASH_KEY],
- &key, end - c, need_unescape, parser->flags & UCL_FLAG_KEY_LOWERCASE, err);
+ &key, end - c, need_unescape, parser->flags & UCL_PARSER_KEY_LOWERCASE);
if (keylen == 0) {
return false;
}
DL_APPEND (tobj, nobj);
}
+ if (ucl_escape) {
+ nobj->flags |= UCL_OBJECT_NEED_KEY_ESCAPE;
+ }
parser->stack->obj->value.ov = container;
parser->cur_obj = nobj;
* Parse a cl string
* @param parser
* @param chunk
- * @param err
* @return true if a key has been parsed
*/
static bool
ucl_parse_string_value (struct ucl_parser *parser,
- struct ucl_chunk *chunk, UT_string **err)
+ struct ucl_chunk *chunk)
{
const unsigned char *p;
enum {
}
if (p >= chunk->end) {
- ucl_set_err (chunk, UCL_ESYNTAX, "unfinished value", err);
+ ucl_set_err (chunk, UCL_ESYNTAX, "unfinished value", &parser->err);
return false;
}
* @param chunk
* @param term
* @param term_len
- * @param err
* @return size of multiline string or 0 in case of error
*/
static int
ucl_parse_multiline_string (struct ucl_parser *parser,
struct ucl_chunk *chunk, const unsigned char *term,
- int term_len, unsigned char const **beg, UT_string **err)
+ int term_len, unsigned char const **beg)
{
const unsigned char *p, *c;
bool newline = false;
* Handle value data
* @param parser
* @param chunk
- * @param err
* @return
*/
static bool
-ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk, UT_string **err)
+ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
{
const unsigned char *p, *c;
struct ucl_stack *st;
ucl_object_t *obj = NULL, *t;
unsigned int stripped_spaces;
int str_len;
- bool need_unescape = false;
+ bool need_unescape = false, ucl_escape = false;
p = chunk->pos;
switch (*p) {
case '"':
ucl_chunk_skipc (chunk, p);
- if (!ucl_lex_json_string (parser, chunk, &need_unescape, err)) {
+ if (!ucl_lex_json_string (parser, chunk, &need_unescape, &ucl_escape)) {
return false;
}
str_len = chunk->pos - c - 2;
obj->type = UCL_STRING;
if ((str_len = ucl_copy_or_store_ptr (parser, c + 1, &obj->trash_stack[UCL_TRASH_VALUE],
- &obj->value.sv, str_len, need_unescape, false, err)) == 0) {
+ &obj->value.sv, str_len, need_unescape, false)) == 0) {
return false;
}
obj->len = str_len;
chunk->column = 0;
chunk->line ++;
if ((str_len = ucl_parse_multiline_string (parser, chunk, c,
- p - c, &c, err)) == 0) {
- ucl_set_err (chunk, UCL_ESYNTAX, "unterminated multiline value", err);
+ p - c, &c)) == 0) {
+ ucl_set_err (chunk, UCL_ESYNTAX, "unterminated multiline value", &parser->err);
return false;
}
obj->type = UCL_STRING;
if ((str_len = ucl_copy_or_store_ptr (parser, c, &obj->trash_stack[UCL_TRASH_VALUE],
- &obj->value.sv, str_len - 1, false, false, err)) == 0) {
+ &obj->value.sv, str_len - 1, false, false)) == 0) {
return false;
}
obj->len = str_len;
while (p < chunk->end && ucl_test_character (*p, UCL_CHARACTER_WHITESPACE_UNSAFE)) {
ucl_chunk_skipc (chunk, p);
}
- if (!ucl_skip_comments (parser, err)) {
+ if (!ucl_skip_comments (parser)) {
return false;
}
p = chunk->pos;
}
/* Parse atom */
if (ucl_test_character (*p, UCL_CHARACTER_VALUE_DIGIT_START)) {
- if (!ucl_lex_number (parser, chunk, obj, err)) {
+ if (!ucl_lex_number (parser, chunk, obj)) {
if (parser->state == UCL_STATE_ERROR) {
return false;
}
- if (!ucl_parse_string_value (parser, chunk, err)) {
+ if (!ucl_parse_string_value (parser, chunk)) {
return false;
}
if (!ucl_maybe_parse_boolean (obj, c, chunk->pos - c)) {
}
str_len = chunk->pos - c - stripped_spaces;
if (str_len <= 0) {
- ucl_set_err (chunk, 0, "string value must not be empty", err);
+ ucl_set_err (chunk, 0, "string value must not be empty", &parser->err);
return false;
}
obj->type = UCL_STRING;
if ((str_len = ucl_copy_or_store_ptr (parser, c, &obj->trash_stack[UCL_TRASH_VALUE],
- &obj->value.sv, str_len, false, false, err)) == 0) {
+ &obj->value.sv, str_len, false, false)) == 0) {
return false;
}
obj->len = str_len;
}
}
else {
- if (!ucl_parse_string_value (parser, chunk, err)) {
+ if (!ucl_parse_string_value (parser, chunk)) {
return false;
}
if (!ucl_maybe_parse_boolean (obj, c, chunk->pos - c)) {
}
str_len = chunk->pos - c - stripped_spaces;
if (str_len <= 0) {
- ucl_set_err (chunk, 0, "string value must not be empty", err);
+ ucl_set_err (chunk, 0, "string value must not be empty", &parser->err);
return false;
}
obj->type = UCL_STRING;
if ((str_len = ucl_copy_or_store_ptr (parser, c, &obj->trash_stack[UCL_TRASH_VALUE],
- &obj->value.sv, str_len, false, false, err)) == 0) {
+ &obj->value.sv, str_len, false, false)) == 0) {
return false;
}
obj->len = str_len;
* Handle after value data
* @param parser
* @param chunk
- * @param err
* @return
*/
static bool
-ucl_parse_after_value (struct ucl_parser *parser, struct ucl_chunk *chunk, UT_string **err)
+ucl_parse_after_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
{
const unsigned char *p;
bool got_sep = false;
}
else if (ucl_lex_is_comment (p[0], p[1])) {
/* Skip comment */
- if (!ucl_skip_comments (parser, err)) {
+ if (!ucl_skip_comments (parser)) {
return false;
}
/* Treat comment as a separator */
else if (ucl_test_character (*p, UCL_CHARACTER_VALUE_END)) {
if (*p == '}' || *p == ']') {
if (parser->stack == NULL) {
- ucl_set_err (chunk, UCL_ESYNTAX, "unexpected } detected", err);
+ ucl_set_err (chunk, UCL_ESYNTAX, "unexpected } detected", &parser->err);
return false;
}
if ((*p == '}' && parser->stack->obj->type == UCL_OBJECT) ||
UCL_FREE (sizeof (struct ucl_stack), st);
}
else {
- ucl_set_err (chunk, UCL_ESYNTAX, "unexpected terminating symbol detected", err);
+ ucl_set_err (chunk, UCL_ESYNTAX, "unexpected terminating symbol detected", &parser->err);
return false;
}
else {
/* Anything else */
if (!got_sep) {
- ucl_set_err (chunk, UCL_ESYNTAX, "delimiter is missing", err);
+ ucl_set_err (chunk, UCL_ESYNTAX, "delimiter is missing", &parser->err);
return false;
}
return true;
* Handle macro data
* @param parser
* @param chunk
- * @param err
* @return
*/
static bool
ucl_parse_macro_value (struct ucl_parser *parser,
struct ucl_chunk *chunk, struct ucl_macro *macro,
- unsigned char const **macro_start, size_t *macro_len, UT_string **err)
+ unsigned char const **macro_start, size_t *macro_len)
{
const unsigned char *p, *c;
- bool need_unescape = false;
+ bool need_unescape = false, ucl_escape = false;
p = chunk->pos;
/* We have macro value encoded in quotes */
c = p;
ucl_chunk_skipc (chunk, p);
- if (!ucl_lex_json_string (parser, chunk, &need_unescape, err)) {
+ if (!ucl_lex_json_string (parser, chunk, &need_unescape, &ucl_escape)) {
return false;
}
* @param parser parser structure
* @param data the pointer to the beginning of a chunk
* @param len the length of a chunk
- * @param err if *err is NULL it is set to parser error
* @return true if chunk has been parsed and false in case of error
*/
static bool
-ucl_state_machine (struct ucl_parser *parser, UT_string **err)
+ucl_state_machine (struct ucl_parser *parser)
{
ucl_object_t *obj;
struct ucl_chunk *chunk = parser->chunks;
* if we got [ or { correspondingly or can just treat new data as
* a key of newly created object
*/
- if (!ucl_skip_comments (parser, err)) {
+ if (!ucl_skip_comments (parser)) {
parser->prev_state = parser->state;
parser->state = UCL_STATE_ERROR;
return false;
parser->state = UCL_STATE_AFTER_VALUE;
continue;
}
- if (!ucl_parse_key (parser, chunk, err)) {
+ if (!ucl_parse_key (parser, chunk)) {
parser->prev_state = parser->state;
parser->state = UCL_STATE_ERROR;
return false;
break;
case UCL_STATE_VALUE:
/* We need to check what we do have */
- if (!ucl_parse_value (parser, chunk, err)) {
+ if (!ucl_parse_value (parser, chunk)) {
parser->prev_state = parser->state;
parser->state = UCL_STATE_ERROR;
return false;
p = chunk->pos;
break;
case UCL_STATE_AFTER_VALUE:
- if (!ucl_parse_after_value (parser, chunk, err)) {
+ if (!ucl_parse_after_value (parser, chunk)) {
parser->prev_state = parser->state;
parser->state = UCL_STATE_ERROR;
return false;
/* We got macro name */
HASH_FIND (hh, parser->macroes, c, (p - c), macro);
if (macro == NULL) {
- ucl_set_err (chunk, UCL_EMACRO, "unknown macro", err);
+ ucl_set_err (chunk, UCL_EMACRO, "unknown macro", &parser->err);
parser->state = UCL_STATE_ERROR;
return false;
}
if (!ucl_test_character (*p, UCL_CHARACTER_WHITESPACE_UNSAFE)) {
if (ucl_lex_is_comment (p[0], p[1])) {
/* Skip comment */
- if (!ucl_skip_comments (parser, err)) {
+ if (!ucl_skip_comments (parser)) {
return false;
}
p = chunk->pos;
break;
case UCL_STATE_MACRO:
if (!ucl_parse_macro_value (parser, chunk, macro,
- ¯o_start, ¯o_len, err)) {
+ ¯o_start, ¯o_len)) {
parser->prev_state = parser->state;
parser->state = UCL_STATE_ERROR;
return false;
}
parser->state = parser->prev_state;
- if (!macro->handler (macro_start, macro_len, macro->ud, err)) {
+ if (!macro->handler (macro_start, macro_len, macro->ud)) {
return false;
}
p = chunk->pos;
break;
default:
/* TODO: add all states */
- ucl_set_err (chunk, UCL_EMACRO, "internal error: parser is in an unknown state", err);
+ ucl_set_err (chunk, UCL_EMACRO, "internal error: parser is in an unknown state", &parser->err);
parser->state = UCL_STATE_ERROR;
return false;
}
bool
ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data,
- size_t len, UT_string **err)
+ size_t len)
{
struct ucl_chunk *chunk;
LL_PREPEND (parser->chunks, chunk);
parser->recursion ++;
if (parser->recursion > UCL_MAX_RECURSION) {
- ucl_create_err (err, "maximum include nesting limit is reached: %d",
+ ucl_create_err (&parser->err, "maximum include nesting limit is reached: %d",
parser->recursion);
return false;
}
- return ucl_state_machine (parser, err);
+ return ucl_state_machine (parser);
}
- ucl_create_err (err, "a parser is in an invalid state");
+ ucl_create_err (&parser->err, "a parser is in an invalid state");
return false;
}
obj->trash_stack[UCL_TRASH_KEY][obj->hh.keylen] = '\0';
}
obj->hh.key = obj->trash_stack[UCL_TRASH_KEY];
+ obj->flags |= UCL_OBJECT_ALLOCATED_KEY;
}
return obj->trash_stack[UCL_TRASH_KEY];
if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
memcpy (obj->trash_stack[UCL_TRASH_VALUE], obj->value.sv, obj->len);
obj->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0';
+ obj->value.sv = obj->trash_stack[UCL_TRASH_VALUE];
}
}
else {
free (emitted);
}
}
+ obj->flags |= UCL_OBJECT_ALLOCATED_VALUE;
}
return obj->trash_stack[UCL_TRASH_VALUE];
}
ucl_object_t*
-ucl_parser_get_object (struct ucl_parser *parser, UT_string **err)
+ucl_parser_get_object (struct ucl_parser *parser)
{
if (parser->state != UCL_STATE_INIT && parser->state != UCL_STATE_ERROR) {
return ucl_object_ref (parser->top_obj);
UCL_FREE (sizeof (struct ucl_pubkey), key);
}
+ if (parser->err != NULL) {
+ utstring_free(parser->err);
+ }
+
UCL_FREE (sizeof (struct ucl_parser), parser);
}
+const char *
+ucl_parser_get_error(struct ucl_parser *parser)
+{
+ if (parser->err == NULL)
+ return NULL;
+
+ return utstring_body(parser->err);
+}
+
bool
-ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len, UT_string **err)
+ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len)
{
struct ucl_pubkey *nkey;
#ifndef HAVE_OPENSSL
- ucl_create_err (err, "cannot check signatures without openssl");
+ ucl_create_err (&parser->err, "cannot check signatures without openssl");
return false;
#else
# if (OPENSSL_VERSION_NUMBER < 0x10000000L)
BIO_free (mem);
if (nkey->key == NULL) {
UCL_FREE (sizeof (struct ucl_pubkey), nkey);
- ucl_create_err (err, "%s",
+ ucl_create_err (&parser->err, "%s",
ERR_error_string (ERR_get_error (), NULL));
return false;
}
}
*buflen = us.size;
- *buf = g_malloc (*buflen);
+ *buf = malloc (*buflen);
if (*buf == NULL) {
ucl_create_err (err, "cannot allocate buffer for URL %s: %s",
url, strerror (errno));
*/
static bool
ucl_include_url (const unsigned char *data, size_t len,
- struct ucl_parser *parser, bool check_signature, UT_string **err)
+ struct ucl_parser *parser, bool check_signature)
{
bool res;
snprintf (urlbuf, sizeof (urlbuf), "%.*s", (int)len, data);
- if (!ucl_fetch_url (urlbuf, &buf, &buflen, err)) {
+ if (!ucl_fetch_url (urlbuf, &buf, &buflen, &parser->err)) {
return false;
}
#if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
/* We need to check signature first */
snprintf (urlbuf, sizeof (urlbuf), "%.*s.sig", (int)len, data);
- if (!ucl_fetch_file (urlbuf, &sigbuf, &siglen, err)) {
+ if (!ucl_fetch_file (urlbuf, &sigbuf, &siglen, &parser->err)) {
return false;
}
if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
- ucl_create_err (err, "cannot verify url %s: %s",
+ ucl_create_err (&parser->err, "cannot verify url %s: %s",
urlbuf,
ERR_error_string (ERR_get_error (), NULL));
munmap (sigbuf, siglen);
#endif
}
- res = ucl_parser_add_chunk (parser, buf, buflen, err);
+ res = ucl_parser_add_chunk (parser, buf, buflen);
if (res == true) {
/* Remove chunk from the stack */
chunk = parser->chunks;
*/
static bool
ucl_include_file (const unsigned char *data, size_t len,
- struct ucl_parser *parser, bool check_signature, UT_string **err)
+ struct ucl_parser *parser, bool check_signature)
{
bool res;
struct ucl_chunk *chunk;
snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data);
if (realpath (filebuf, realbuf) == NULL) {
- ucl_create_err (err, "cannot open file %s: %s",
+ ucl_create_err (&parser->err, "cannot open file %s: %s",
filebuf,
strerror (errno));
return false;
}
- if (!ucl_fetch_file (realbuf, &buf, &buflen, err)) {
+ if (!ucl_fetch_file (realbuf, &buf, &buflen, &parser->err)) {
return false;
}
#if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
/* We need to check signature first */
snprintf (filebuf, sizeof (filebuf), "%s.sig", realbuf);
- if (!ucl_fetch_file (filebuf, &sigbuf, &siglen, err)) {
+ if (!ucl_fetch_file (filebuf, &sigbuf, &siglen, &parser->err)) {
return false;
}
if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
- ucl_create_err (err, "cannot verify file %s: %s",
+ ucl_create_err (&parser->err, "cannot verify file %s: %s",
filebuf,
ERR_error_string (ERR_get_error (), NULL));
munmap (sigbuf, siglen);
#endif
}
- res = ucl_parser_add_chunk (parser, buf, buflen, err);
+ res = ucl_parser_add_chunk (parser, buf, buflen);
if (res == true) {
/* Remove chunk from the stack */
chunk = parser->chunks;
* @return
*/
bool
-ucl_include_handler (const unsigned char *data, size_t len, void* ud, UT_string **err)
+ucl_include_handler (const unsigned char *data, size_t len, void* ud)
{
struct ucl_parser *parser = ud;
if (*data == '/' || *data == '.') {
/* Try to load a file */
- return ucl_include_file (data, len, parser, false, err);
+ return ucl_include_file (data, len, parser, false);
}
- return ucl_include_url (data, len, parser, false, err);
+ return ucl_include_url (data, len, parser, false);
}
/**
* @return
*/
bool
-ucl_includes_handler (const unsigned char *data, size_t len, void* ud, UT_string **err)
+ucl_includes_handler (const unsigned char *data, size_t len, void* ud)
{
struct ucl_parser *parser = ud;
if (*data == '/' || *data == '.') {
/* Try to load a file */
- return ucl_include_file (data, len, parser, true, err);
+ return ucl_include_file (data, len, parser, true);
}
- return ucl_include_url (data, len, parser, true, err);
+ return ucl_include_url (data, len, parser, true);
}
bool
-ucl_parser_add_file (struct ucl_parser *parser, const char *filename,
- UT_string **err)
+ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
{
unsigned char *buf;
size_t len;
bool ret;
- if (!ucl_fetch_file (filename, &buf, &len, err)) {
+ if (!ucl_fetch_file (filename, &buf, &len, &parser->err)) {
return false;
}
- ret = ucl_parser_add_chunk (parser, buf, len, err);
+ ret = ucl_parser_add_chunk (parser, buf, len);
munmap (buf, len);
return obj;
}
+
+ucl_object_t *
+ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt,
+ const char *key, size_t keylen, bool copy_key)
+{
+ ucl_object_t *found;
+ const char *p;
+
+ if (elt == NULL || key == NULL) {
+ return NULL;
+ }
+
+ if (top == NULL) {
+ top = ucl_object_new ();
+ top->type = UCL_OBJECT;
+ }
+ if (keylen == 0) {
+ keylen = strlen (key);
+ }
+
+ for (p = key; p < key + keylen; p ++) {
+ if (ucl_test_character (*p, UCL_CHARACTER_UCL_UNSAFE)) {
+ elt->flags |= UCL_OBJECT_NEED_KEY_ESCAPE;
+ break;
+ }
+ }
+
+ HASH_FIND (hh, top->value.ov, key, keylen, found);
+
+ if (!found) {
+ HASH_ADD_KEYPTR (hh, top->value.ov, key, keylen, elt);
+ }
+ DL_APPEND (found, elt);
+
+ if (copy_key) {
+ ucl_copy_key_trash (elt);
+ }
+
+ return top;
+}
key9 = 3.140000;
key10 = true;
key11 = false;
+key12 = "gslin@gslin.org";
+key13 = "#test";
+"k=3" = true;
struct ucl_parser *parser, *parser2;
ucl_object_t *obj;
FILE *in, *out;
- UT_string *err = NULL;
unsigned char *emitted;
const char *fname_in = NULL, *fname_out = NULL;
int ret = 0;
else {
in = stdin;
}
- parser = ucl_parser_new (UCL_FLAG_KEY_LOWERCASE);
+ parser = ucl_parser_new (UCL_PARSER_KEY_LOWERCASE);
while (!feof (in)) {
fread (inbuf, sizeof (inbuf), 1, in);
- ucl_parser_add_chunk (parser, inbuf, strlen (inbuf), &err);
+ ucl_parser_add_chunk (parser, inbuf, strlen (inbuf));
}
fclose (in);
else {
out = stdout;
}
- if (err != NULL) {
- fprintf (out, "Error occurred: %s\n", err->d);
+ if (ucl_parser_get_error(parser) != NULL) {
+ fprintf (out, "Error occurred: %s\n", ucl_parser_get_error(parser));
ret = 1;
goto end;
}
- obj = ucl_parser_get_object (parser, &err);
+ obj = ucl_parser_get_object (parser);
emitted = ucl_object_emit (obj, UCL_EMIT_CONFIG);
ucl_parser_free (parser);
ucl_object_unref (obj);
- parser2 = ucl_parser_new (UCL_FLAG_KEY_LOWERCASE);
- ucl_parser_add_chunk (parser2, emitted, strlen (emitted), &err);
+ parser2 = ucl_parser_new (UCL_PARSER_KEY_LOWERCASE);
+ ucl_parser_add_chunk (parser2, emitted, strlen (emitted));
- if (err != NULL) {
- fprintf (out, "Error occurred: %s\n", err->d);
+ if (ucl_parser_get_error(parser2) != NULL) {
+ fprintf (out, "Error occurred: %s\n", ucl_parser_get_error(parser2));
fprintf (out, "%s\n", emitted);
ret = 1;
goto end;
if (emitted != NULL) {
free (emitted);
}
- obj = ucl_parser_get_object (parser2, &err);
+ obj = ucl_parser_get_object (parser2);
emitted = ucl_object_emit (obj, UCL_EMIT_CONFIG);
fprintf (out, "%s\n", emitted);
if (parser2 != NULL) {
ucl_parser_free (parser2);
}
+
fclose (out);
return ret;
obj = ucl_object_insert_key (obj, cur, "key10", 0, false);
cur = ucl_object_fromstring_common (" off ", 0, UCL_STRING_PARSE | UCL_STRING_TRIM);
obj = ucl_object_insert_key (obj, cur, "key11", 0, false);
+ cur = ucl_object_fromstring_common ("gslin@gslin.org", 0, UCL_STRING_PARSE_INT);
+ obj = ucl_object_insert_key (obj, cur, "key12", 0, false);
+ cur = ucl_object_fromstring_common ("#test", 0, UCL_STRING_PARSE_INT);
+ obj = ucl_object_insert_key (obj, cur, "key13", 0, false);
+ cur = ucl_object_frombool (true);
+ obj = ucl_object_insert_key (obj, cur, "k=3", 0, false);
+
emitted = ucl_object_emit (obj, UCL_EMIT_CONFIG);
struct ucl_parser *parser;
ucl_object_t *obj;
int fin;
- UT_string *err = NULL;
unsigned char *emitted;
struct stat st;
const char *fname_in = NULL;
perror ("open failed");
exit (EXIT_FAILURE);
}
- parser = ucl_parser_new (UCL_FLAG_ZEROCOPY);
+ parser = ucl_parser_new (UCL_PARSER_ZEROCOPY);
(void)fstat (fin, &st);
map = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fin, 0);
close (fin);
clock_gettime (CLOCK_MONOTONIC, &start);
- ucl_parser_add_chunk (parser, map, st.st_size, &err);
+ ucl_parser_add_chunk (parser, map, st.st_size);
- obj = ucl_parser_get_object (parser, &err);
+ obj = ucl_parser_get_object (parser);
clock_gettime (CLOCK_MONOTONIC, &end);
seconds = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1000000000.;
printf ("ucl: parsed input in %.4f seconds\n", seconds);
- if (err != NULL) {
- printf ("Error occurred: %s\n", err->d);
+ if (ucl_parser_get_error(parser)) {
+ printf ("Error occurred: %s\n", ucl_parser_get_error(parser));
ret = 1;
}