Import libucl 0.4.0

Adapt pkg(7) to the new libucl API
This commit is contained in:
Baptiste Daroussin 2014-04-22 22:02:06 +00:00
commit b04a7a0baf
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=264789
19 changed files with 581 additions and 453 deletions

View File

@ -287,7 +287,7 @@ Each UCL object can be serialized to one of the three supported formats:
## Validation ## Validation
UCL allows validation of objects. It uses the same schema that is used for json: [json schema v4](http://json-schema.org). UCL supports the full set of json schema with the exception of remote references. This feature is unlikely useful for configuration objects. Of course, schema definition can be in UCL format instead of JSON that sinplifies schemas writing. Moreover, since UCL supports multiple values for keys in an object it is possible to specify generic integer constraints `maxValues` and `minValues` to define the limits of values in a single key. UCL currently is not absolutely strict about validation schemas themselves, therefore UCL users should supply valid schemas (as it is defined in json-schema draft v4) to ensure that input is validated properly. UCL allows validation of objects. It uses the same schema that is used for json: [json schema v4](http://json-schema.org). UCL supports the full set of json schema with the exception of remote references. This feature is unlikely useful for configuration objects. Of course, a schema definition can be in UCL format instead of JSON that simplifies schemas writing. Moreover, since UCL supports multiple values for keys in an object it is possible to specify generic integer constraints `maxValues` and `minValues` to define the limits of values count in a single key. UCL currently is not absolutely strict about validation schemas themselves, therefore UCL users should supply valid schemas (as it is defined in json-schema draft v4) to ensure that the input objects are validated properly.
## Performance ## Performance

View File

@ -1,5 +1,5 @@
m4_define([maj_ver], [0]) m4_define([maj_ver], [0])
m4_define([med_ver], [3]) m4_define([med_ver], [4])
m4_define([min_ver], [0]) m4_define([min_ver], [0])
m4_define([so_version], [maj_ver:med_ver]) m4_define([so_version], [maj_ver:med_ver])
m4_define([ucl_version], [maj_ver.med_ver.min_ver]) m4_define([ucl_version], [maj_ver.med_ver.min_ver])
@ -48,11 +48,17 @@ AC_CHECK_HEADERS_ONCE([float.h])
AC_CHECK_HEADERS_ONCE([math.h]) AC_CHECK_HEADERS_ONCE([math.h])
dnl Example of default-disabled feature dnl Example of default-disabled feature
AC_ARG_ENABLE([urls], AS_HELP_STRING([--enable-urls], [Enable URLs fetch (requires libfetch or libcurl)])) AC_ARG_ENABLE([urls], AS_HELP_STRING([--enable-urls],
[Enable URLs fetch (requires libfetch or libcurl) @<:@default=no@:>@]), [],
[enable_urls=no])
AC_ARG_ENABLE([regex], AS_HELP_STRING([--enable-regex],
[Enable regex checking for schema @<:@default=yes@:>@]), [],
[enable_regex=yes])
AC_ARG_ENABLE([signatures], AS_HELP_STRING([--enable-signatures], AC_ARG_ENABLE([signatures], AS_HELP_STRING([--enable-signatures],
[Enable signatures check (requires openssl)])) [Enable signatures check (requires openssl) @<:@default=no@:>@]), [],
[enable_signatures=no])
AC_ARG_ENABLE([utils], AC_ARG_ENABLE([utils],
[--enable-utils Build and install utils], AS_HELP_STRING([--enable-utils], [Build and install utils @<:@default=no@:>@]),
[case "${enableval}" in [case "${enableval}" in
yes) utils=true ;; yes) utils=true ;;
no) utils=false ;; no) utils=false ;;
@ -63,11 +69,11 @@ AM_CONDITIONAL([UTILS], [test x$utils = xtrue])
AS_IF([test "x$enable_signatures" = "xyes"], [ AS_IF([test "x$enable_signatures" = "xyes"], [
AC_SEARCH_LIBS([EVP_MD_CTX_create], [crypto], [ AC_SEARCH_LIBS([EVP_MD_CTX_create], [crypto], [
AC_DEFINE(HAVE_OPENSSL, 1, [Define to 1 if you have the 'crypto' library (-lcrypto).]) AC_DEFINE(HAVE_OPENSSL, 1, [Define to 1 if you have the 'crypto' library (-lcrypto).])
LIBSSL_LIB="-lcrypto" LIBCRYPTO_LIB="-lcrypto"
LIBS_EXTRA="${LIBS_EXTRA} -lcrypto" LIBS_EXTRA="${LIBS_EXTRA} -lcrypto"
], [AC_MSG_ERROR([unable to find the EVP_MD_CTX_create() function])]) ], [AC_MSG_ERROR([unable to find the EVP_MD_CTX_create() function])])
]) ])
AC_SUBST(LIBCRYPTO_LIB)
AC_PATH_PROG(PANDOC, pandoc, [/non/existent]) AC_PATH_PROG(PANDOC, pandoc, [/non/existent])
AC_SEARCH_LIBS([clock_gettime], [rt], [], [ AC_SEARCH_LIBS([clock_gettime], [rt], [], [
@ -77,11 +83,21 @@ AC_SEARCH_LIBS([clock_gettime], [rt], [], [
]) ])
AC_SEARCH_LIBS([remainder], [m], [], [AC_MSG_ERROR([unable to find remainder() function])]) AC_SEARCH_LIBS([remainder], [m], [], [AC_MSG_ERROR([unable to find remainder() function])])
AC_CHECK_HEADER([regex.h], [ AS_IF([test "x$enable_regex" = "xyes"], [
AC_DEFINE(HAVE_REGEX_H, 1, [Define to 1 if you have the <regex.h> header file.]) AC_CHECK_HEADER([regex.h], [
], AC_DEFINE(HAVE_REGEX_H, 1, [Define to 1 if you have the <regex.h> header file.])
[AC_MSG_ERROR([unable to find the regex.h header])], AC_SEARCH_LIBS([regexec], [regex], [
[#include <sys/types.h>]) AS_IF([test "x$ac_cv_search_regexec" = "x-lregex"], [
LIBREGEX_LIB="-lregex"
LIBS_EXTRA="${LIBS_EXTRA} -lregex"
]
)],
[AC_MSG_ERROR([unable to find the regexec() function])])],
[AC_MSG_ERROR([unable to find the regex.h header])
],
[#include <sys/types.h>])
])
AC_SUBST(LIBREGEX_LIB)
AS_IF([test "x$enable_urls" = "xyes"], [ AS_IF([test "x$enable_urls" = "xyes"], [
AC_CHECK_HEADER([fetch.h], [ AC_CHECK_HEADER([fetch.h], [
@ -114,6 +130,29 @@ AS_IF([test "x$enable_urls" = "xyes"], [
AC_SUBST(LIBS_EXTRA) AC_SUBST(LIBS_EXTRA)
AC_MSG_CHECKING(for GCC atomic builtins)
AC_LINK_IFELSE([
AC_LANG_SOURCE([[
int main() {
volatile unsigned long val = 1;
__sync_synchronize();
__sync_val_compare_and_swap(&val, 1, 0);
__sync_add_and_fetch(&val, 1);
__sync_sub_and_fetch(&val, 1);
return 0;
}
]])
],
[
AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_ATOMIC_BUILTINS], [1], [Has gcc/MSVC atomic intrinsics])
],
[
AC_MSG_RESULT([no])
AC_DEFINE([HAVE_ATOMIC_BUILTINS], [0], [Has gcc/MSVC atomic intrinsics])
AC_MSG_WARN([Libucl references could be thread-unsafe because atomic builtins are missing])
])
AC_CONFIG_FILES(Makefile \ AC_CONFIG_FILES(Makefile \
src/Makefile \ src/Makefile \
tests/Makefile \ tests/Makefile \

View File

@ -282,7 +282,7 @@ Libucl provides the following functions for emitting UCL objects:
### ucl_object_emit ### ucl_object_emit
~~~C ~~~C
unsigned char *ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type); unsigned char *ucl_object_emit (const ucl_object_t *obj, enum ucl_emitter emit_type);
~~~ ~~~
Allocate a string that is suitable to fit the underlying UCL object `obj` and fill it with the textual representation of the object `obj` according to style `emit_type`. The caller should free the returned string after using. Allocate a string that is suitable to fit the underlying UCL object `obj` and fill it with the textual representation of the object `obj` according to style `emit_type`. The caller should free the returned string after using.
@ -290,7 +290,7 @@ Allocate a string that is suitable to fit the underlying UCL object `obj` and fi
### ucl_object_emit_full ### ucl_object_emit_full
~~~C ~~~C
bool ucl_object_emit_full (ucl_object_t *obj, enum ucl_emitter emit_type, bool ucl_object_emit_full (const ucl_object_t *obj, enum ucl_emitter emit_type,
struct ucl_emitter_functions *emitter); struct ucl_emitter_functions *emitter);
~~~ ~~~
@ -381,7 +381,7 @@ Iteration are used to iterate over UCL compound types: arrays and objects. Moreo
## ucl_iterate_object ## ucl_iterate_object
~~~C ~~~C
ucl_object_t* ucl_iterate_object (ucl_object_t *obj, const ucl_object_t* ucl_iterate_object (const ucl_object_t *obj,
ucl_object_iter_t *iter, bool expand_values); ucl_object_iter_t *iter, bool expand_values);
~~~ ~~~
@ -389,7 +389,7 @@ This function accept opaque iterator pointer `iter`. In the first call this iter
~~~C ~~~C
ucl_object_iter_t it = NULL, it_obj = NULL; ucl_object_iter_t it = NULL, it_obj = NULL;
ucl_object_t *cur, *tmp; const ucl_object_t *cur, *tmp;
/* Iterate over the object */ /* Iterate over the object */
while ((obj = ucl_iterate_object (top, &it, true))) { while ((obj = ucl_iterate_object (top, &it, true))) {
@ -408,8 +408,8 @@ Currently, there is only one validation function called `ucl_object_validate`. I
## ucl_object_validate ## ucl_object_validate
~~~C ~~~C
bool ucl_object_validate (ucl_object_t *schema, bool ucl_object_validate (const ucl_object_t *schema,
ucl_object_t *obj, struct ucl_schema_error *err); const ucl_object_t *obj, struct ucl_schema_error *err);
~~~ ~~~
This function uses ucl object `schema`, that must be valid in terms of `json-schema` draft v4, to validate input object `obj`. If this function returns `true` then validation procedure has been succeed. Otherwise, `false` is returned and `err` is set to a specific value. If caller set `err` to NULL then this function does not set any error just returning `false`. Error is the structure defined as following: This function uses ucl object `schema`, that must be valid in terms of `json-schema` draft v4, to validate input object `obj`. If this function returns `true` then validation procedure has been succeed. Otherwise, `false` is returned and `err` is set to a specific value. If caller set `err` to NULL then this function does not set any error just returning `false`. Error is the structure defined as following:

View File

@ -6,11 +6,11 @@
\f[B]ucl_parser_add_string\f[], \f[B]ucl_parser_add_file\f[], \f[B]ucl_parser_add_string\f[], \f[B]ucl_parser_add_file\f[],
\f[B]ucl_parser_get_object\f[], \f[B]ucl_parser_get_error\f[], \f[B]ucl_parser_get_object\f[], \f[B]ucl_parser_get_error\f[],
\f[B]ucl_parser_free\f[], \f[B]ucl_pubkey_add\f[], \f[B]ucl_parser_free\f[], \f[B]ucl_pubkey_add\f[],
\f[B]ucl_parser_set_filevars\f[] - universal configuration library \f[B]ucl_parser_set_filevars\f[] \- universal configuration library
parser and utility functions parser and utility functions
.SH LIBRARY .SH LIBRARY
.PP .PP
UCL library (libucl, -lucl) UCL library (libucl, \-lucl)
.SH SYNOPSIS .SH SYNOPSIS
.PP .PP
\f[C]#include\ <ucl.h>\f[] \f[C]#include\ <ucl.h>\f[]
@ -32,12 +32,12 @@ In future, this limitation can be removed.
Convert \f[C]ucl\f[] objects to some textual or binary representation. Convert \f[C]ucl\f[] objects to some textual or binary representation.
Currently, libucl supports the following exports: Currently, libucl supports the following exports:
.IP \[bu] 2 .IP \[bu] 2
\f[C]JSON\f[] - valid json format (can possibly loose some original \f[C]JSON\f[] \- valid json format (can possibly loose some original
data, such as implicit arrays) data, such as implicit arrays)
.IP \[bu] 2 .IP \[bu] 2
\f[C]Config\f[] - human-readable configuration format (losseless) \f[C]Config\f[] \- human\-readable configuration format (losseless)
.IP \[bu] 2 .IP \[bu] 2
\f[C]YAML\f[] - embedded yaml format (has the same limitations as \f[C]YAML\f[] \- embedded yaml format (has the same limitations as
\f[C]json\f[] output) \f[C]json\f[] output)
.SS Conversion functions .SS Conversion functions
.PP .PP
@ -57,7 +57,7 @@ as implicit array or implicit consolidation).
.SS Validation functions .SS Validation functions
.PP .PP
Validation functions are used to validate some object \f[C]obj\f[] using Validation functions are used to validate some object \f[C]obj\f[] using
json-schema compatible object \f[C]schema\f[]. json\-schema compatible object \f[C]schema\f[].
Both input and schema must be UCL objects to perform validation. Both input and schema must be UCL objects to perform validation.
.SS Utility functions .SS Utility functions
.PP .PP
@ -76,13 +76,13 @@ struct\ ucl_parser*\ ucl_parser_new\ (int\ flags);
.PP .PP
Creates new parser with the specified flags: Creates new parser with the specified flags:
.IP \[bu] 2 .IP \[bu] 2
\f[C]UCL_PARSER_KEY_LOWERCASE\f[] - lowercase keys parsed \f[C]UCL_PARSER_KEY_LOWERCASE\f[] \- lowercase keys parsed
.IP \[bu] 2 .IP \[bu] 2
\f[C]UCL_PARSER_ZEROCOPY\f[] - try to use zero-copy mode when reading \f[C]UCL_PARSER_ZEROCOPY\f[] \- try to use zero\-copy mode when reading
files (in zero-copy mode text chunk being parsed without copying strings files (in zero\-copy mode text chunk being parsed without copying
so it should exist till any object parsed is used) strings so it should exist till any object parsed is used)
.IP \[bu] 2 .IP \[bu] 2
\f[C]UCL_PARSER_NO_TIME\f[] - treat time values as strings without \f[C]UCL_PARSER_NO_TIME\f[] \- treat time values as strings without
parsing them as floats parsing them as floats
.SS ucl_parser_register_macro .SS ucl_parser_register_macro
.IP .IP
@ -161,7 +161,7 @@ bool\ ucl_parser_add_string\ (struct\ ucl_parser\ *parser,\
.PP .PP
This function acts exactly like \f[C]ucl_parser_add_chunk\f[] does but This function acts exactly like \f[C]ucl_parser_add_chunk\f[] does but
if \f[C]len\f[] argument is zero, then the string \f[C]data\f[] must be if \f[C]len\f[] argument is zero, then the string \f[C]data\f[] must be
zero-terminated and the actual length is calculated up to \f[C]\\0\f[] zero\-terminated and the actual length is calculated up to \f[C]\\0\f[]
character. character.
.SS ucl_parser_add_file .SS ucl_parser_add_file
.IP .IP
@ -229,7 +229,7 @@ bool\ ucl_pubkey_add\ (struct\ ucl_parser\ *parser,\
This function adds a public key from text blob \f[C]key\f[] of length This function adds a public key from text blob \f[C]key\f[] of length
\f[C]len\f[] to the \f[C]parser\f[] object. \f[C]len\f[] to the \f[C]parser\f[] object.
This public key should be in the \f[C]PEM\f[] format and can be used by This public key should be in the \f[C]PEM\f[] format and can be used by
\f[C].includes\f[] macro for checking signatures of files included. \f[C]\&.includes\f[] macro for checking signatures of files included.
\f[C]Openssl\f[] support should be enabled to make this function \f[C]Openssl\f[] support should be enabled to make this function
working. working.
If a key cannot be added (e.g. If a key cannot be added (e.g.
@ -247,25 +247,26 @@ bool\ ucl_parser_set_filevars\ (struct\ ucl_parser\ *parser,\
Add the standard file variables to the \f[C]parser\f[] based on the Add the standard file variables to the \f[C]parser\f[] based on the
\f[C]filename\f[] specified: \f[C]filename\f[] specified:
.IP \[bu] 2 .IP \[bu] 2
\f[C]$FILENAME\f[] - a filename of \f[C]ucl\f[] input \f[C]$FILENAME\f[] \- a filename of \f[C]ucl\f[] input
.IP \[bu] 2 .IP \[bu] 2
\f[C]$CURDIR\f[] - a current directory of the input \f[C]$CURDIR\f[] \- a current directory of the input
.PP .PP
For example, if a \f[C]filename\f[] param is \f[C]../something.conf\f[] For example, if a \f[C]filename\f[] param is
then the variables will have the following values: \f[C]\&../something.conf\f[] then the variables will have the following
values:
.IP \[bu] 2 .IP \[bu] 2
\f[C]$FILENAME\f[] - "../something.conf" \f[C]$FILENAME\f[] \- "../something.conf"
.IP \[bu] 2 .IP \[bu] 2
\f[C]$CURDIR\f[] - ".." \f[C]$CURDIR\f[] \- ".."
.PP .PP
if \f[C]need_expand\f[] parameter is \f[C]true\f[] then all relative if \f[C]need_expand\f[] parameter is \f[C]true\f[] then all relative
paths are expanded using \f[C]realpath\f[] call. paths are expanded using \f[C]realpath\f[] call.
In this example if \f[C]..\f[] is \f[C]/etc/dir\f[] then variables will In this example if \f[C]\&..\f[] is \f[C]/etc/dir\f[] then variables
have these values: will have these values:
.IP \[bu] 2 .IP \[bu] 2
\f[C]$FILENAME\f[] - "/etc/something.conf" \f[C]$FILENAME\f[] \- "/etc/something.conf"
.IP \[bu] 2 .IP \[bu] 2
\f[C]$CURDIR\f[] - "/etc" \f[C]$CURDIR\f[] \- "/etc"
.SS Parser usage example .SS Parser usage example
.PP .PP
The following example loads, parses and extracts \f[C]ucl\f[] object The following example loads, parses and extracts \f[C]ucl\f[] object
@ -283,7 +284,7 @@ FILE\ *in;
in\ =\ stdin; in\ =\ stdin;
parser\ =\ ucl_parser_new\ (0); parser\ =\ ucl_parser_new\ (0);
while\ (!feof\ (in)\ &&\ r\ <\ (int)sizeof\ (inbuf))\ { while\ (!feof\ (in)\ &&\ r\ <\ (int)sizeof\ (inbuf))\ {
\ \ \ \ r\ +=\ fread\ (inbuf\ +\ r,\ 1,\ sizeof\ (inbuf)\ -\ r,\ in); \ \ \ \ r\ +=\ fread\ (inbuf\ +\ r,\ 1,\ sizeof\ (inbuf)\ \-\ r,\ in);
} }
ucl_parser_add_chunk\ (parser,\ inbuf,\ r); ucl_parser_add_chunk\ (parser,\ inbuf,\ r);
fclose\ (in); fclose\ (in);
@ -309,20 +310,20 @@ return\ ret;
.PP .PP
Libucl can transform UCL objects to a number of tectual formats: Libucl can transform UCL objects to a number of tectual formats:
.IP \[bu] 2 .IP \[bu] 2
configuration (\f[C]UCL_EMIT_CONFIG\f[]) - nginx like human readable configuration (\f[C]UCL_EMIT_CONFIG\f[]) \- nginx like human readable
configuration file where implicit arrays are transformed to the configuration file where implicit arrays are transformed to the
duplicate keys duplicate keys
.IP \[bu] 2 .IP \[bu] 2
compact json: \f[C]UCL_EMIT_JSON_COMPACT\f[] - single line valid json compact json: \f[C]UCL_EMIT_JSON_COMPACT\f[] \- single line valid json
without spaces without spaces
.IP \[bu] 2 .IP \[bu] 2
formatted json: \f[C]UCL_EMIT_JSON\f[] - pretty formatted JSON with formatted json: \f[C]UCL_EMIT_JSON\f[] \- pretty formatted JSON with
newlines and spaces newlines and spaces
.IP \[bu] 2 .IP \[bu] 2
compact yaml: \f[C]UCL_EMIT_YAML\f[] - compact YAML output compact yaml: \f[C]UCL_EMIT_YAML\f[] \- compact YAML output
.PP .PP
Moreover, libucl API allows to select a custom set of emitting functions Moreover, libucl API allows to select a custom set of emitting functions
allowing efficent and zero-copy output of libucl objects. allowing efficent and zero\-copy output of libucl objects.
Libucl uses the following structure to support this feature: Libucl uses the following structure to support this feature:
.IP .IP
.nf .nf
@ -344,17 +345,17 @@ struct\ ucl_emitter_functions\ {
.PP .PP
This structure defines the following callbacks: This structure defines the following callbacks:
.IP \[bu] 2 .IP \[bu] 2
\f[C]ucl_emitter_append_character\f[] - a function that is called to \f[C]ucl_emitter_append_character\f[] \- a function that is called to
append \f[C]nchars\f[] characters equal to \f[C]c\f[] append \f[C]nchars\f[] characters equal to \f[C]c\f[]
.IP \[bu] 2 .IP \[bu] 2
\f[C]ucl_emitter_append_len\f[] - used to append a string of length \f[C]ucl_emitter_append_len\f[] \- used to append a string of length
\f[C]len\f[] starting from pointer \f[C]str\f[] \f[C]len\f[] starting from pointer \f[C]str\f[]
.IP \[bu] 2 .IP \[bu] 2
\f[C]ucl_emitter_append_int\f[] - this function applies to integer \f[C]ucl_emitter_append_int\f[] \- this function applies to integer
numbers numbers
.IP \[bu] 2 .IP \[bu] 2
\f[C]ucl_emitter_append_double\f[] - this function is intended to output \f[C]ucl_emitter_append_double\f[] \- this function is intended to
floating point variable output floating point variable
.PP .PP
The set of these functions could be used to output text formats of The set of these functions could be used to output text formats of
\f[C]UCL\f[] objects to different structures or streams. \f[C]UCL\f[] objects to different structures or streams.
@ -364,7 +365,7 @@ Libucl provides the following functions for emitting UCL objects:
.IP .IP
.nf .nf
\f[C] \f[C]
unsigned\ char\ *ucl_object_emit\ (ucl_object_t\ *obj,\ enum\ ucl_emitter\ emit_type); unsigned\ char\ *ucl_object_emit\ (const\ ucl_object_t\ *obj,\ enum\ ucl_emitter\ emit_type);
\f[] \f[]
.fi .fi
.PP .PP
@ -376,7 +377,7 @@ The caller should free the returned string after using.
.IP .IP
.nf .nf
\f[C] \f[C]
bool\ ucl_object_emit_full\ (ucl_object_t\ *obj,\ enum\ ucl_emitter\ emit_type, bool\ ucl_object_emit_full\ (const\ ucl_object_t\ *obj,\ enum\ ucl_emitter\ emit_type,
\ \ \ \ \ \ \ \ struct\ ucl_emitter_functions\ *emitter); \ \ \ \ \ \ \ \ struct\ ucl_emitter_functions\ *emitter);
\f[] \f[]
.fi .fi
@ -400,26 +401,26 @@ cannot be converted then some reasonable default is returned (NULL for
strings and 0 for numbers) strings and 0 for numbers)
.PP .PP
Also there is a single \f[C]ucl_object_tostring_forced\f[] function that Also there is a single \f[C]ucl_object_tostring_forced\f[] function that
converts any UCL object (including compound types - arrays and objects) converts any UCL object (including compound types \- arrays and objects)
to a string representation. to a string representation.
For compound and numeric types this function performs emitting to a For compound and numeric types this function performs emitting to a
compact json format actually. compact json format actually.
.PP .PP
Here is a list of all conversion functions: Here is a list of all conversion functions:
.IP \[bu] 2 .IP \[bu] 2
\f[C]ucl_object_toint\f[] - returns \f[C]int64_t\f[] of UCL object \f[C]ucl_object_toint\f[] \- returns \f[C]int64_t\f[] of UCL object
.IP \[bu] 2 .IP \[bu] 2
\f[C]ucl_object_todouble\f[] - returns \f[C]double\f[] of UCL object \f[C]ucl_object_todouble\f[] \- returns \f[C]double\f[] of UCL object
.IP \[bu] 2 .IP \[bu] 2
\f[C]ucl_object_toboolean\f[] - returns \f[C]bool\f[] of UCL object \f[C]ucl_object_toboolean\f[] \- returns \f[C]bool\f[] of UCL object
.IP \[bu] 2 .IP \[bu] 2
\f[C]ucl_object_tostring\f[] - returns \f[C]const\ char\ *\f[] of UCL \f[C]ucl_object_tostring\f[] \- returns \f[C]const\ char\ *\f[] of UCL
object (this string is NULL terminated) object (this string is NULL terminated)
.IP \[bu] 2 .IP \[bu] 2
\f[C]ucl_object_tolstring\f[] - returns \f[C]const\ char\ *\f[] and \f[C]ucl_object_tolstring\f[] \- returns \f[C]const\ char\ *\f[] and
\f[C]size_t\f[] len of UCL object (string can be not NULL terminated) \f[C]size_t\f[] len of UCL object (string can be not NULL terminated)
.IP \[bu] 2 .IP \[bu] 2
\f[C]ucl_object_tostring_forced\f[] - returns string representation of \f[C]ucl_object_tostring_forced\f[] \- returns string representation of
any UCL object any UCL object
.PP .PP
Strings returned by these pointers are associated with the UCL object Strings returned by these pointers are associated with the UCL object
@ -448,26 +449,28 @@ ucl_object_t\ *\ ucl_object_typed_new\ (unsigned\ int\ type)
\f[] \f[]
.fi .fi
.PP .PP
Create an object of a specified type: - \f[C]UCL_OBJECT\f[] - UCL object Create an object of a specified type: \- \f[C]UCL_OBJECT\f[] \- UCL
- key/value pairs - \f[C]UCL_ARRAY\f[] - UCL array - \f[C]UCL_INT\f[] - object \- key/value pairs \- \f[C]UCL_ARRAY\f[] \- UCL array \-
integer number - \f[C]UCL_FLOAT\f[] - floating point number - \f[C]UCL_INT\f[] \- integer number \- \f[C]UCL_FLOAT\f[] \- floating
\f[C]UCL_STRING\f[] - NULL terminated string - \f[C]UCL_BOOLEAN\f[] - point number \- \f[C]UCL_STRING\f[] \- NULL terminated string \-
boolean value - \f[C]UCL_TIME\f[] - time value (floating point number of \f[C]UCL_BOOLEAN\f[] \- boolean value \- \f[C]UCL_TIME\f[] \- time value
seconds) - \f[C]UCL_USERDATA\f[] - opaque userdata pointer (may be used (floating point number of seconds) \- \f[C]UCL_USERDATA\f[] \- opaque
in macros) - \f[C]UCL_NULL\f[] - null value userdata pointer (may be used in macros) \- \f[C]UCL_NULL\f[] \- null
value
.PP .PP
This object should be released by caller. This object should be released by caller.
.SS Primitive objects generation .SS Primitive objects generation
.PP .PP
Libucl provides the functions similar to inverse conversion functions Libucl provides the functions similar to inverse conversion functions
called with the specific C type: - \f[C]ucl_object_fromint\f[] - called with the specific C type: \- \f[C]ucl_object_fromint\f[] \-
converts \f[C]int64_t\f[] to UCL object - \f[C]ucl_object_fromdouble\f[] converts \f[C]int64_t\f[] to UCL object \-
- converts \f[C]double\f[] to UCL object - \f[C]ucl_object_fromdouble\f[] \- converts \f[C]double\f[] to UCL object
\f[C]ucl_object_fromboolean\f[] - converts \f[C]bool\f[] to UCL object - \- \f[C]ucl_object_fromboolean\f[] \- converts \f[C]bool\f[] to UCL
\f[C]ucl_object_fromstring\f[] - converts \f[C]const\ char\ *\f[] to UCL object \- \f[C]ucl_object_fromstring\f[] \- converts
object (this string is NULL terminated) - \f[C]const\ char\ *\f[] to UCL object (this string is NULL terminated)
\f[C]ucl_object_fromlstring\f[] - converts \f[C]const\ char\ *\f[] and \- \f[C]ucl_object_fromlstring\f[] \- converts \f[C]const\ char\ *\f[]
\f[C]size_t\f[] len to UCL object (string can be not NULL terminated) and \f[C]size_t\f[] len to UCL object (string can be not NULL
terminated)
.PP .PP
Also there is a function to generate UCL object from a string performing Also there is a function to generate UCL object from a string performing
various parsing or conversion operations called various parsing or conversion operations called
@ -484,35 +487,35 @@ ucl_object_t\ *\ ucl_object_fromstring_common\ (const\ char\ *str,\
This function is used to convert a string \f[C]str\f[] of size This function is used to convert a string \f[C]str\f[] of size
\f[C]len\f[] to an UCL objects applying \f[C]flags\f[] conversions. \f[C]len\f[] to an UCL objects applying \f[C]flags\f[] conversions.
If \f[C]len\f[] is equal to zero then a \f[C]str\f[] is assumed as If \f[C]len\f[] is equal to zero then a \f[C]str\f[] is assumed as
NULL-terminated. NULL\-terminated.
This function supports the following flags (a set of flags can be This function supports the following flags (a set of flags can be
specified using logical \f[C]OR\f[] operation): specified using logical \f[C]OR\f[] operation):
.IP \[bu] 2 .IP \[bu] 2
\f[C]UCL_STRING_ESCAPE\f[] - perform JSON escape \f[C]UCL_STRING_ESCAPE\f[] \- perform JSON escape
.IP \[bu] 2 .IP \[bu] 2
\f[C]UCL_STRING_TRIM\f[] - trim leading and trailing whitespaces \f[C]UCL_STRING_TRIM\f[] \- trim leading and trailing whitespaces
.IP \[bu] 2 .IP \[bu] 2
\f[C]UCL_STRING_PARSE_BOOLEAN\f[] - parse passed string and detect \f[C]UCL_STRING_PARSE_BOOLEAN\f[] \- parse passed string and detect
boolean boolean
.IP \[bu] 2 .IP \[bu] 2
\f[C]UCL_STRING_PARSE_INT\f[] - parse passed string and detect integer \f[C]UCL_STRING_PARSE_INT\f[] \- parse passed string and detect integer
number number
.IP \[bu] 2 .IP \[bu] 2
\f[C]UCL_STRING_PARSE_DOUBLE\f[] - parse passed string and detect \f[C]UCL_STRING_PARSE_DOUBLE\f[] \- parse passed string and detect
integer or float number integer or float number
.IP \[bu] 2 .IP \[bu] 2
\f[C]UCL_STRING_PARSE_TIME\f[] - parse time values as floating point \f[C]UCL_STRING_PARSE_TIME\f[] \- parse time values as floating point
numbers numbers
.IP \[bu] 2 .IP \[bu] 2
\f[C]UCL_STRING_PARSE_NUMBER\f[] - parse passed string and detect number \f[C]UCL_STRING_PARSE_NUMBER\f[] \- parse passed string and detect
(both float, integer and time types) number (both float, integer and time types)
.IP \[bu] 2 .IP \[bu] 2
\f[C]UCL_STRING_PARSE\f[] - parse passed string (and detect booleans, \f[C]UCL_STRING_PARSE\f[] \- parse passed string (and detect booleans,
numbers and time values) numbers and time values)
.IP \[bu] 2 .IP \[bu] 2
\f[C]UCL_STRING_PARSE_BYTES\f[] - assume that numeric multipliers are in \f[C]UCL_STRING_PARSE_BYTES\f[] \- assume that numeric multipliers are
bytes notation, for example \f[C]10k\f[] means \f[C]10*1024\f[] and not in bytes notation, for example \f[C]10k\f[] means \f[C]10*1024\f[] and
\f[C]10*1000\f[] as assumed without this flag not \f[C]10*1000\f[] as assumed without this flag
.PP .PP
If parsing operations fail then the resulting UCL object will be a If parsing operations fail then the resulting UCL object will be a
\f[C]UCL_STRING\f[]. \f[C]UCL_STRING\f[].
@ -530,7 +533,7 @@ is a function \f[C]ucl_iterate_object\f[].
.IP .IP
.nf .nf
\f[C] \f[C]
ucl_object_t*\ ucl_iterate_object\ (ucl_object_t\ *obj,\ const\ ucl_object_t*\ ucl_iterate_object\ (const\ ucl_object_t\ *obj,\
\ \ \ \ ucl_object_iter_t\ *iter,\ bool\ expand_values); \ \ \ \ ucl_object_iter_t\ *iter,\ bool\ expand_values);
\f[] \f[]
.fi .fi
@ -561,7 +564,7 @@ Here is an example of iteration over the objects using libucl API
.nf .nf
\f[C] \f[C]
ucl_object_iter_t\ it\ =\ NULL,\ it_obj\ =\ NULL; ucl_object_iter_t\ it\ =\ NULL,\ it_obj\ =\ NULL;
ucl_object_t\ *cur,\ *tmp; const\ ucl_object_t\ *cur,\ *tmp;
/*\ Iterate\ over\ the\ object\ */ /*\ Iterate\ over\ the\ object\ */
while\ ((obj\ =\ ucl_iterate_object\ (top,\ &it,\ true)))\ { while\ ((obj\ =\ ucl_iterate_object\ (top,\ &it,\ true)))\ {
@ -584,13 +587,13 @@ This function is defined as following:
.IP .IP
.nf .nf
\f[C] \f[C]
bool\ ucl_object_validate\ (ucl_object_t\ *schema, bool\ ucl_object_validate\ (const\ ucl_object_t\ *schema,
\ \ \ \ ucl_object_t\ *obj,\ struct\ ucl_schema_error\ *err); \ \ \ \ const\ ucl_object_t\ *obj,\ struct\ ucl_schema_error\ *err);
\f[] \f[]
.fi .fi
.PP .PP
This function uses ucl object \f[C]schema\f[], that must be valid in This function uses ucl object \f[C]schema\f[], that must be valid in
terms of \f[C]json-schema\f[] draft v4, to validate input object terms of \f[C]json\-schema\f[] draft v4, to validate input object
\f[C]obj\f[]. \f[C]obj\f[].
If this function returns \f[C]true\f[] then validation procedure has If this function returns \f[C]true\f[] then validation procedure has
been succeed. been succeed.

View File

@ -81,6 +81,14 @@ extern "C" {
#define UCL_WARN_UNUSED_RESULT #define UCL_WARN_UNUSED_RESULT
#endif #endif
#ifdef __GNUC__
#define UCL_DEPRECATED(func) func __attribute__ ((deprecated))
#elif defined(_MSC_VER)
#define UCL_DEPRECATED(func) __declspec(deprecated) func
#else
#define UCL_DEPRECATED(func) func
#endif
/** /**
* @defgroup structures Structures and types * @defgroup structures Structures and types
* UCL defines several enumeration types used for error reporting or specifying flags and attributes. * UCL defines several enumeration types used for error reporting or specifying flags and attributes.
@ -208,14 +216,14 @@ typedef struct ucl_object_s {
* @param obj CL object * @param obj CL object
* @return zero terminated key * @return zero terminated key
*/ */
UCL_EXTERN char* ucl_copy_key_trash (ucl_object_t *obj); UCL_EXTERN char* ucl_copy_key_trash (const ucl_object_t *obj);
/** /**
* Copy and return a string value of an object, returned key is zero-terminated * Copy and return a string value of an object, returned key is zero-terminated
* @param obj CL object * @param obj CL object
* @return zero terminated string representation of object value * @return zero terminated string representation of object value
*/ */
UCL_EXTERN char* ucl_copy_value_trash (ucl_object_t *obj); UCL_EXTERN char* ucl_copy_value_trash (const ucl_object_t *obj);
/** /**
* Creates a new object * Creates a new object
@ -245,7 +253,7 @@ UCL_EXTERN ucl_object_t * ucl_object_fromstring_common (const char *str, size_t
* @param str NULL terminated string, will be json escaped * @param str NULL terminated string, will be json escaped
* @return new object * @return new object
*/ */
UCL_EXTERN ucl_object_t *ucl_object_fromstring (const char *str); UCL_EXTERN ucl_object_t *ucl_object_fromstring (const char *str) UCL_WARN_UNUSED_RESULT;
/** /**
* Create a UCL object from the specified string * Create a UCL object from the specified string
@ -253,28 +261,29 @@ UCL_EXTERN ucl_object_t *ucl_object_fromstring (const char *str);
* @param len length of a string * @param len length of a string
* @return new object * @return new object
*/ */
UCL_EXTERN ucl_object_t *ucl_object_fromlstring (const char *str, size_t len); UCL_EXTERN ucl_object_t *ucl_object_fromlstring (const char *str,
size_t len) UCL_WARN_UNUSED_RESULT;
/** /**
* Create an object from an integer number * Create an object from an integer number
* @param iv number * @param iv number
* @return new object * @return new object
*/ */
UCL_EXTERN ucl_object_t* ucl_object_fromint (int64_t iv); UCL_EXTERN ucl_object_t* ucl_object_fromint (int64_t iv) UCL_WARN_UNUSED_RESULT;
/** /**
* Create an object from a float number * Create an object from a float number
* @param dv number * @param dv number
* @return new object * @return new object
*/ */
UCL_EXTERN ucl_object_t* ucl_object_fromdouble (double dv); UCL_EXTERN ucl_object_t* ucl_object_fromdouble (double dv) UCL_WARN_UNUSED_RESULT;
/** /**
* Create an object from a boolean * Create an object from a boolean
* @param bv bool value * @param bv bool value
* @return new object * @return new object
*/ */
UCL_EXTERN ucl_object_t* ucl_object_frombool (bool bv); UCL_EXTERN ucl_object_t* ucl_object_frombool (bool bv) UCL_WARN_UNUSED_RESULT;
/** /**
* Insert a object 'elt' to the hash 'top' and associate it with key 'key' * Insert a object 'elt' to the hash 'top' and associate it with key 'key'
@ -283,10 +292,10 @@ UCL_EXTERN ucl_object_t* ucl_object_frombool (bool bv);
* @param key key to associate with this object (either const or preallocated) * @param key key to associate with this object (either const or preallocated)
* @param keylen length of the key (or 0 for NULL terminated keys) * @param keylen length of the key (or 0 for NULL terminated keys)
* @param copy_key make an internal copy of key * @param copy_key make an internal copy of key
* @return new value of top object * @return true if key has been inserted
*/ */
UCL_EXTERN ucl_object_t* ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, UCL_EXTERN bool ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt,
const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; const char *key, size_t keylen, bool copy_key);
/** /**
* Replace a object 'elt' to the hash 'top' and associate it with key 'key', old object will be unrefed, * Replace a object 'elt' to the hash 'top' and associate it with key 'key', old object will be unrefed,
@ -296,10 +305,10 @@ UCL_EXTERN ucl_object_t* ucl_object_insert_key (ucl_object_t *top, ucl_object_t
* @param key key to associate with this object (either const or preallocated) * @param key key to associate with this object (either const or preallocated)
* @param keylen length of the key (or 0 for NULL terminated keys) * @param keylen length of the key (or 0 for NULL terminated keys)
* @param copy_key make an internal copy of key * @param copy_key make an internal copy of key
* @return new value of top object * @return true if key has been inserted
*/ */
UCL_EXTERN ucl_object_t* ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt, UCL_EXTERN bool ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt,
const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; const char *key, size_t keylen, bool copy_key);
/** /**
* Delete a object associated with key 'key', old object will be unrefered, * Delete a object associated with key 'key', old object will be unrefered,
@ -307,14 +316,16 @@ UCL_EXTERN ucl_object_t* ucl_object_replace_key (ucl_object_t *top, ucl_object_t
* @param key key associated to the object to remove * @param key key associated to the object to remove
* @param keylen length of the key (or 0 for NULL terminated keys) * @param keylen length of the key (or 0 for NULL terminated keys)
*/ */
UCL_EXTERN bool ucl_object_delete_keyl (ucl_object_t *top, const char *key, size_t keylen); UCL_EXTERN bool ucl_object_delete_keyl (ucl_object_t *top,
const char *key, size_t keylen);
/** /**
* Delete a object associated with key 'key', old object will be unrefered, * Delete a object associated with key 'key', old object will be unrefered,
* @param top object * @param top object
* @param key key associated to the object to remove * @param key key associated to the object to remove
*/ */
UCL_EXTERN bool ucl_object_delete_key (ucl_object_t *top, const char *key); UCL_EXTERN bool ucl_object_delete_key (ucl_object_t *top,
const char *key);
/** /**
@ -346,28 +357,28 @@ UCL_EXTERN ucl_object_t* ucl_object_pop_key (ucl_object_t *top, const char *key)
* @param key key to associate with this object (either const or preallocated) * @param key key to associate with this object (either const or preallocated)
* @param keylen length of the key (or 0 for NULL terminated keys) * @param keylen length of the key (or 0 for NULL terminated keys)
* @param copy_key make an internal copy of key * @param copy_key make an internal copy of key
* @return new value of top object * @return true if key has been inserted
*/ */
UCL_EXTERN ucl_object_t* ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt, UCL_EXTERN bool ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt,
const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; const char *key, size_t keylen, bool copy_key);
/** /**
* Append an element to the front of array object * Append an element to the front of array object
* @param top destination object (will be created automatically if top is NULL) * @param top destination object (will be created automatically if top is NULL)
* @param elt element to append (must NOT be NULL) * @param elt element to append (must NOT be NULL)
* @return new value of top object * @return true if value has been inserted
*/ */
UCL_EXTERN ucl_object_t* ucl_array_append (ucl_object_t *top, UCL_EXTERN bool ucl_array_append (ucl_object_t *top,
ucl_object_t *elt) UCL_WARN_UNUSED_RESULT; ucl_object_t *elt);
/** /**
* Append an element to the start of array object * Append an element to the start of array object
* @param top destination object (will be created automatically if top is NULL) * @param top destination object (will be created automatically if top is NULL)
* @param elt element to append (must NOT be NULL) * @param elt element to append (must NOT be NULL)
* @return new value of top object * @return true if value has been inserted
*/ */
UCL_EXTERN ucl_object_t* ucl_array_prepend (ucl_object_t *top, UCL_EXTERN bool ucl_array_prepend (ucl_object_t *top,
ucl_object_t *elt) UCL_WARN_UNUSED_RESULT; ucl_object_t *elt);
/** /**
* Removes an element `elt` from the array `top`. Caller must unref the returned object when it is not * Removes an element `elt` from the array `top`. Caller must unref the returned object when it is not
@ -376,21 +387,22 @@ UCL_EXTERN ucl_object_t* ucl_array_prepend (ucl_object_t *top,
* @param elt element to remove * @param elt element to remove
* @return removed element or NULL if `top` is NULL or not an array * @return removed element or NULL if `top` is NULL or not an array
*/ */
UCL_EXTERN ucl_object_t* ucl_array_delete (ucl_object_t *top, ucl_object_t *elt); UCL_EXTERN ucl_object_t* ucl_array_delete (ucl_object_t *top,
ucl_object_t *elt);
/** /**
* Returns the first element of the array `top` * Returns the first element of the array `top`
* @param top array ucl object * @param top array ucl object
* @return element or NULL if `top` is NULL or not an array * @return element or NULL if `top` is NULL or not an array
*/ */
UCL_EXTERN ucl_object_t* ucl_array_head (ucl_object_t *top); UCL_EXTERN const ucl_object_t* ucl_array_head (const ucl_object_t *top);
/** /**
* Returns the last element of the array `top` * Returns the last element of the array `top`
* @param top array ucl object * @param top array ucl object
* @return element or NULL if `top` is NULL or not an array * @return element or NULL if `top` is NULL or not an array
*/ */
UCL_EXTERN ucl_object_t* ucl_array_tail (ucl_object_t *top); UCL_EXTERN const ucl_object_t* ucl_array_tail (const ucl_object_t *top);
/** /**
* Removes the last element from the array `top`. Caller must unref the returned object when it is not * Removes the last element from the array `top`. Caller must unref the returned object when it is not
@ -412,10 +424,10 @@ UCL_EXTERN ucl_object_t* ucl_array_pop_first (ucl_object_t *top);
* Append a element to another element forming an implicit array * Append a element to another element forming an implicit array
* @param head head to append (may be NULL) * @param head head to append (may be NULL)
* @param elt new element * @param elt new element
* @return new head if applicable * @return true if element has been inserted
*/ */
UCL_EXTERN ucl_object_t* ucl_elt_append (ucl_object_t *head, UCL_EXTERN ucl_object_t * ucl_elt_append (ucl_object_t *head,
ucl_object_t *elt) UCL_WARN_UNUSED_RESULT; ucl_object_t *elt);
/** /**
* Converts an object to double value * Converts an object to double value
@ -423,14 +435,14 @@ UCL_EXTERN ucl_object_t* ucl_elt_append (ucl_object_t *head,
* @param target target double variable * @param target target double variable
* @return true if conversion was successful * @return true if conversion was successful
*/ */
UCL_EXTERN bool ucl_object_todouble_safe (ucl_object_t *obj, double *target); UCL_EXTERN bool ucl_object_todouble_safe (const ucl_object_t *obj, double *target);
/** /**
* Unsafe version of \ref ucl_obj_todouble_safe * Unsafe version of \ref ucl_obj_todouble_safe
* @param obj CL object * @param obj CL object
* @return double value * @return double value
*/ */
UCL_EXTERN double ucl_object_todouble (ucl_object_t *obj); UCL_EXTERN double ucl_object_todouble (const ucl_object_t *obj);
/** /**
* Converts an object to integer value * Converts an object to integer value
@ -438,14 +450,14 @@ UCL_EXTERN double ucl_object_todouble (ucl_object_t *obj);
* @param target target integer variable * @param target target integer variable
* @return true if conversion was successful * @return true if conversion was successful
*/ */
UCL_EXTERN bool ucl_object_toint_safe (ucl_object_t *obj, int64_t *target); UCL_EXTERN bool ucl_object_toint_safe (const ucl_object_t *obj, int64_t *target);
/** /**
* Unsafe version of \ref ucl_obj_toint_safe * Unsafe version of \ref ucl_obj_toint_safe
* @param obj CL object * @param obj CL object
* @return int value * @return int value
*/ */
UCL_EXTERN int64_t ucl_object_toint (ucl_object_t *obj); UCL_EXTERN int64_t ucl_object_toint (const ucl_object_t *obj);
/** /**
* Converts an object to boolean value * Converts an object to boolean value
@ -453,14 +465,14 @@ UCL_EXTERN int64_t ucl_object_toint (ucl_object_t *obj);
* @param target target boolean variable * @param target target boolean variable
* @return true if conversion was successful * @return true if conversion was successful
*/ */
UCL_EXTERN bool ucl_object_toboolean_safe (ucl_object_t *obj, bool *target); UCL_EXTERN bool ucl_object_toboolean_safe (const ucl_object_t *obj, bool *target);
/** /**
* Unsafe version of \ref ucl_obj_toboolean_safe * Unsafe version of \ref ucl_obj_toboolean_safe
* @param obj CL object * @param obj CL object
* @return boolean value * @return boolean value
*/ */
UCL_EXTERN bool ucl_object_toboolean (ucl_object_t *obj); UCL_EXTERN bool ucl_object_toboolean (const ucl_object_t *obj);
/** /**
* Converts an object to string value * Converts an object to string value
@ -468,21 +480,21 @@ UCL_EXTERN bool ucl_object_toboolean (ucl_object_t *obj);
* @param target target string variable, no need to free value * @param target target string variable, no need to free value
* @return true if conversion was successful * @return true if conversion was successful
*/ */
UCL_EXTERN bool ucl_object_tostring_safe (ucl_object_t *obj, const char **target); UCL_EXTERN bool ucl_object_tostring_safe (const ucl_object_t *obj, const char **target);
/** /**
* Unsafe version of \ref ucl_obj_tostring_safe * Unsafe version of \ref ucl_obj_tostring_safe
* @param obj CL object * @param obj CL object
* @return string value * @return string value
*/ */
UCL_EXTERN const char* ucl_object_tostring (ucl_object_t *obj); UCL_EXTERN const char* ucl_object_tostring (const ucl_object_t *obj);
/** /**
* Convert any object to a string in JSON notation if needed * Convert any object to a string in JSON notation if needed
* @param obj CL object * @param obj CL object
* @return string value * @return string value
*/ */
UCL_EXTERN const char* ucl_object_tostring_forced (ucl_object_t *obj); UCL_EXTERN const char* ucl_object_tostring_forced (const ucl_object_t *obj);
/** /**
* Return string as char * and len, string may be not zero terminated, more efficient that \ref ucl_obj_tostring as it * Return string as char * and len, string may be not zero terminated, more efficient that \ref ucl_obj_tostring as it
@ -492,7 +504,7 @@ UCL_EXTERN const char* ucl_object_tostring_forced (ucl_object_t *obj);
* @param tlen target length * @param tlen target length
* @return true if conversion was successful * @return true if conversion was successful
*/ */
UCL_EXTERN bool ucl_object_tolstring_safe (ucl_object_t *obj, UCL_EXTERN bool ucl_object_tolstring_safe (const ucl_object_t *obj,
const char **target, size_t *tlen); const char **target, size_t *tlen);
/** /**
@ -500,7 +512,7 @@ UCL_EXTERN bool ucl_object_tolstring_safe (ucl_object_t *obj,
* @param obj CL object * @param obj CL object
* @return string value * @return string value
*/ */
UCL_EXTERN const char* ucl_object_tolstring (ucl_object_t *obj, size_t *tlen); UCL_EXTERN const char* ucl_object_tolstring (const ucl_object_t *obj, size_t *tlen);
/** /**
* Return object identified by a key in the specified object * Return object identified by a key in the specified object
@ -508,7 +520,8 @@ UCL_EXTERN const char* ucl_object_tolstring (ucl_object_t *obj, size_t *tlen);
* @param key key to search * @param key key to search
* @return object matched the specified key or NULL if key is not found * @return object matched the specified key or NULL if key is not found
*/ */
UCL_EXTERN ucl_object_t* ucl_object_find_key (ucl_object_t *obj, const char *key); UCL_EXTERN const ucl_object_t* ucl_object_find_key (const ucl_object_t *obj,
const char *key);
/** /**
* Return object identified by a fixed size key in the specified object * Return object identified by a fixed size key in the specified object
@ -517,14 +530,15 @@ UCL_EXTERN ucl_object_t* ucl_object_find_key (ucl_object_t *obj, const char *key
* @param klen length of a key * @param klen length of a key
* @return object matched the specified key or NULL if key is not found * @return object matched the specified key or NULL if key is not found
*/ */
UCL_EXTERN ucl_object_t* ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen); UCL_EXTERN const ucl_object_t* ucl_object_find_keyl (const ucl_object_t *obj,
const char *key, size_t klen);
/** /**
* Returns a key of an object as a NULL terminated string * Returns a key of an object as a NULL terminated string
* @param obj CL object * @param obj CL object
* @return key or NULL if there is no key * @return key or NULL if there is no key
*/ */
UCL_EXTERN const char* ucl_object_key (ucl_object_t *obj); UCL_EXTERN const char* ucl_object_key (const ucl_object_t *obj);
/** /**
* Returns a key of an object as a fixed size string (may be more efficient) * Returns a key of an object as a fixed size string (may be more efficient)
@ -532,19 +546,19 @@ UCL_EXTERN const char* ucl_object_key (ucl_object_t *obj);
* @param len target key length * @param len target key length
* @return key pointer * @return key pointer
*/ */
UCL_EXTERN const char* ucl_object_keyl (ucl_object_t *obj, size_t *len); UCL_EXTERN const char* ucl_object_keyl (const ucl_object_t *obj, size_t *len);
/**
* Free ucl object
* @param obj ucl object to free
*/
UCL_EXTERN void ucl_object_free (ucl_object_t *obj);
/** /**
* Increase reference count for an object * Increase reference count for an object
* @param obj object to ref * @param obj object to ref
*/ */
UCL_EXTERN ucl_object_t* ucl_object_ref (ucl_object_t *obj); UCL_EXTERN ucl_object_t* ucl_object_ref (const ucl_object_t *obj);
/**
* Free ucl object
* @param obj ucl object to free
*/
UCL_DEPRECATED(UCL_EXTERN void ucl_object_free (ucl_object_t *obj));
/** /**
* Decrease reference count for an object * Decrease reference count for an object
@ -562,7 +576,8 @@ UCL_EXTERN void ucl_object_unref (ucl_object_t *obj);
* 2) Size of objects * 2) Size of objects
* 3) Content of objects * 3) Content of objects
*/ */
UCL_EXTERN int ucl_object_compare (ucl_object_t *o1, ucl_object_t *o2); UCL_EXTERN int ucl_object_compare (const ucl_object_t *o1,
const ucl_object_t *o2);
/** /**
* Sort UCL array using `cmp` compare function * Sort UCL array using `cmp` compare function
@ -570,7 +585,7 @@ UCL_EXTERN int ucl_object_compare (ucl_object_t *o1, ucl_object_t *o2);
* @param cmp * @param cmp
*/ */
UCL_EXTERN void ucl_object_array_sort (ucl_object_t *ar, UCL_EXTERN void ucl_object_array_sort (ucl_object_t *ar,
int (*cmp)(ucl_object_t *o1, ucl_object_t *o2)); int (*cmp)(const ucl_object_t *o1, const ucl_object_t *o2));
/** /**
* Opaque iterator object * Opaque iterator object
@ -585,7 +600,8 @@ typedef void* ucl_object_iter_t;
* while ((cur = ucl_iterate_object (obj, &it)) != NULL) ... * while ((cur = ucl_iterate_object (obj, &it)) != NULL) ...
* @return the next object or NULL * @return the next object or NULL
*/ */
UCL_EXTERN ucl_object_t* ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values); UCL_EXTERN const ucl_object_t* ucl_iterate_object (const ucl_object_t *obj,
ucl_object_iter_t *iter, bool expand_values);
/** @} */ /** @} */
@ -663,10 +679,21 @@ UCL_EXTERN bool ucl_parser_add_string (struct ucl_parser *parser,
* @param err if *err is NULL it is set to parser error * @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 * @return true if chunk has been added and false in case of error
*/ */
UCL_EXTERN bool ucl_parser_add_file (struct ucl_parser *parser, const char *filename); UCL_EXTERN bool ucl_parser_add_file (struct ucl_parser *parser,
const char *filename);
/** /**
* Get a top object for a parser * Load and add data from a file descriptor
* @param parser parser structure
* @param filename the name of 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
*/
UCL_EXTERN bool ucl_parser_add_fd (struct ucl_parser *parser,
int fd);
/**
* Get a top object for a parser (refcount is increased)
* @param parser parser structure * @param parser parser structure
* @param err if *err is NULL it is set to parser error * @param err if *err is NULL it is set to parser error
* @return top parser object or NULL * @return top parser object or NULL
@ -736,7 +763,8 @@ struct ucl_emitter_functions {
* #UCL_EMIT_CONFIG then emit config like object * #UCL_EMIT_CONFIG then emit config like object
* @return dump of an object (must be freed after using) or NULL in case of error * @return dump of an object (must be freed after using) or NULL in case of error
*/ */
UCL_EXTERN unsigned char *ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type); UCL_EXTERN unsigned char *ucl_object_emit (const ucl_object_t *obj,
enum ucl_emitter emit_type);
/** /**
* Emit object to a string * Emit object to a string
@ -745,7 +773,8 @@ UCL_EXTERN unsigned char *ucl_object_emit (ucl_object_t *obj, enum ucl_emitter e
* #UCL_EMIT_CONFIG then emit config like object * #UCL_EMIT_CONFIG then emit config like object
* @return dump of an object (must be freed after using) or NULL in case of error * @return dump of an object (must be freed after using) or NULL in case of error
*/ */
UCL_EXTERN bool ucl_object_emit_full (ucl_object_t *obj, enum ucl_emitter emit_type, UCL_EXTERN bool ucl_object_emit_full (const ucl_object_t *obj,
enum ucl_emitter emit_type,
struct ucl_emitter_functions *emitter); struct ucl_emitter_functions *emitter);
/** @} */ /** @} */
@ -775,7 +804,7 @@ enum ucl_schema_error_code {
struct ucl_schema_error { struct ucl_schema_error {
enum ucl_schema_error_code code; /**< error code */ enum ucl_schema_error_code code; /**< error code */
char msg[128]; /**< error message */ char msg[128]; /**< error message */
ucl_object_t *obj; /**< object where error occured */ const ucl_object_t *obj; /**< object where error occured */
}; };
/** /**
@ -786,8 +815,8 @@ struct ucl_schema_error {
* occured, then `err` is filled with the exact error definition. * occured, then `err` is filled with the exact error definition.
* @return true if `obj` is valid using `schema` * @return true if `obj` is valid using `schema`
*/ */
UCL_EXTERN bool ucl_object_validate (ucl_object_t *schema, UCL_EXTERN bool ucl_object_validate (const ucl_object_t *schema,
ucl_object_t *obj, struct ucl_schema_error *err); const ucl_object_t *obj, struct ucl_schema_error *err);
/** @} */ /** @} */

View File

@ -13,6 +13,8 @@ libucl_la_CFLAGS= $(libucl_common_cflags) \
@CURL_CFLAGS@ @CURL_CFLAGS@
libucl_la_LDFLAGS = -version-info @SO_VERSION@ libucl_la_LDFLAGS = -version-info @SO_VERSION@
libucl_la_LIBADD= @LIBFETCH_LIBS@ \ libucl_la_LIBADD= @LIBFETCH_LIBS@ \
@LIBCRYPTO_LIB@ \
@LIBREGEX_LIB@ \
@CURL_LIBS@ @CURL_LIBS@
include_HEADERS= $(top_srcdir)/include/ucl.h include_HEADERS= $(top_srcdir)/include/ucl.h

View File

@ -41,29 +41,29 @@
*/ */
static void ucl_obj_write_json (ucl_object_t *obj, static void ucl_obj_write_json (const ucl_object_t *obj,
struct ucl_emitter_functions *func, struct ucl_emitter_functions *func,
unsigned int tabs, unsigned int tabs,
bool start_tabs, bool start_tabs,
bool compact); bool compact);
static void ucl_elt_write_json (ucl_object_t *obj, static void ucl_elt_write_json (const ucl_object_t *obj,
struct ucl_emitter_functions *func, struct ucl_emitter_functions *func,
unsigned int tabs, unsigned int tabs,
bool start_tabs, bool start_tabs,
bool compact); bool compact);
static void ucl_elt_write_config (ucl_object_t *obj, static void ucl_elt_write_config (const ucl_object_t *obj,
struct ucl_emitter_functions *func, struct ucl_emitter_functions *func,
unsigned int tabs, unsigned int tabs,
bool start_tabs, bool start_tabs,
bool is_top, bool is_top,
bool expand_array); bool expand_array);
static void ucl_elt_write_yaml (ucl_object_t *obj, static void ucl_elt_write_yaml (const ucl_object_t *obj,
struct ucl_emitter_functions *func, struct ucl_emitter_functions *func,
unsigned int tabs, unsigned int tabs,
bool start_tabs, bool start_tabs,
bool compact, bool compact,
bool expand_array); bool expand_array);
static void ucl_elt_array_write_yaml (ucl_object_t *obj, static void ucl_elt_array_write_yaml (const ucl_object_t *obj,
struct ucl_emitter_functions *func, struct ucl_emitter_functions *func,
unsigned int tabs, unsigned int tabs,
bool start_tabs, bool start_tabs,
@ -144,10 +144,10 @@ ucl_elt_string_write_json (const char *str, size_t size,
* @param buf target buffer * @param buf target buffer
*/ */
static void static void
ucl_elt_obj_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func, ucl_elt_obj_write_json (const ucl_object_t *obj, struct ucl_emitter_functions *func,
unsigned int tabs, bool start_tabs, bool compact) unsigned int tabs, bool start_tabs, bool compact)
{ {
ucl_object_t *cur; const ucl_object_t *cur;
ucl_hash_iter_t it = NULL; ucl_hash_iter_t it = NULL;
if (start_tabs) { if (start_tabs) {
@ -196,10 +196,10 @@ ucl_elt_obj_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func,
* @param buf target buffer * @param buf target buffer
*/ */
static void static void
ucl_elt_array_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func, ucl_elt_array_write_json (const ucl_object_t *obj, struct ucl_emitter_functions *func,
unsigned int tabs, bool start_tabs, bool compact) unsigned int tabs, bool start_tabs, bool compact)
{ {
ucl_object_t *cur = obj; const ucl_object_t *cur = obj;
if (start_tabs) { if (start_tabs) {
ucl_add_tabs (func, tabs, compact); ucl_add_tabs (func, tabs, compact);
@ -235,7 +235,7 @@ ucl_elt_array_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func,
* @param buf buffer * @param buf buffer
*/ */
static void static void
ucl_elt_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func, ucl_elt_write_json (const ucl_object_t *obj, struct ucl_emitter_functions *func,
unsigned int tabs, bool start_tabs, bool compact) unsigned int tabs, bool start_tabs, bool compact)
{ {
bool flag; bool flag;
@ -295,10 +295,10 @@ ucl_elt_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func,
* @param buf target buffer * @param buf target buffer
*/ */
static void static void
ucl_obj_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func, ucl_obj_write_json (const ucl_object_t *obj, struct ucl_emitter_functions *func,
unsigned int tabs, bool start_tabs, bool compact) unsigned int tabs, bool start_tabs, bool compact)
{ {
ucl_object_t *cur; const ucl_object_t *cur;
bool is_array = (obj->next != NULL); bool is_array = (obj->next != NULL);
if (is_array) { if (is_array) {
@ -339,7 +339,8 @@ ucl_obj_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func,
* @return json output (should be freed after using) * @return json output (should be freed after using)
*/ */
static void static void
ucl_object_emit_json (ucl_object_t *obj, bool compact, struct ucl_emitter_functions *func) ucl_object_emit_json (const ucl_object_t *obj, bool compact,
struct ucl_emitter_functions *func)
{ {
ucl_obj_write_json (obj, func, 0, false, compact); ucl_obj_write_json (obj, func, 0, false, compact);
} }
@ -350,10 +351,10 @@ ucl_object_emit_json (ucl_object_t *obj, bool compact, struct ucl_emitter_functi
* @param buf target buffer * @param buf target buffer
*/ */
static void static void
ucl_elt_obj_write_config (ucl_object_t *obj, struct ucl_emitter_functions *func, ucl_elt_obj_write_config (const ucl_object_t *obj, struct ucl_emitter_functions *func,
unsigned int tabs, bool start_tabs, bool is_top) unsigned int tabs, bool start_tabs, bool is_top)
{ {
ucl_object_t *cur, *cur_obj; const ucl_object_t *cur, *cur_obj;
ucl_hash_iter_t it = NULL; ucl_hash_iter_t it = NULL;
if (start_tabs) { if (start_tabs) {
@ -402,10 +403,10 @@ ucl_elt_obj_write_config (ucl_object_t *obj, struct ucl_emitter_functions *func,
* @param buf target buffer * @param buf target buffer
*/ */
static void static void
ucl_elt_array_write_config (ucl_object_t *obj, struct ucl_emitter_functions *func, ucl_elt_array_write_config (const ucl_object_t *obj, struct ucl_emitter_functions *func,
unsigned int tabs, bool start_tabs, bool is_top) unsigned int tabs, bool start_tabs, bool is_top)
{ {
ucl_object_t *cur = obj; const ucl_object_t *cur = obj;
if (start_tabs) { if (start_tabs) {
ucl_add_tabs (func, tabs, false); ucl_add_tabs (func, tabs, false);
@ -427,7 +428,7 @@ ucl_elt_array_write_config (ucl_object_t *obj, struct ucl_emitter_functions *fun
* @param buf buffer * @param buf buffer
*/ */
static void static void
ucl_elt_write_config (ucl_object_t *obj, struct ucl_emitter_functions *func, ucl_elt_write_config (const ucl_object_t *obj, struct ucl_emitter_functions *func,
unsigned int tabs, bool start_tabs, bool is_top, bool expand_array) unsigned int tabs, bool start_tabs, bool is_top, bool expand_array)
{ {
bool flag; bool flag;
@ -492,14 +493,14 @@ ucl_elt_write_config (ucl_object_t *obj, struct ucl_emitter_functions *func,
* @return rcl output (should be freed after using) * @return rcl output (should be freed after using)
*/ */
static void static void
ucl_object_emit_config (ucl_object_t *obj, struct ucl_emitter_functions *func) ucl_object_emit_config (const ucl_object_t *obj, struct ucl_emitter_functions *func)
{ {
ucl_elt_write_config (obj, func, 0, false, true, true); ucl_elt_write_config (obj, func, 0, false, true, true);
} }
static void static void
ucl_obj_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func, ucl_obj_write_yaml (const ucl_object_t *obj, struct ucl_emitter_functions *func,
unsigned int tabs, bool start_tabs) unsigned int tabs, bool start_tabs)
{ {
bool is_array = (obj->next != NULL); bool is_array = (obj->next != NULL);
@ -518,10 +519,10 @@ ucl_obj_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func,
* @param buf target buffer * @param buf target buffer
*/ */
static void static void
ucl_elt_obj_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func, ucl_elt_obj_write_yaml (const ucl_object_t *obj, struct ucl_emitter_functions *func,
unsigned int tabs, bool start_tabs, bool is_top) unsigned int tabs, bool start_tabs, bool is_top)
{ {
ucl_object_t *cur; const ucl_object_t *cur;
ucl_hash_iter_t it = NULL; ucl_hash_iter_t it = NULL;
if (start_tabs) { if (start_tabs) {
@ -566,10 +567,10 @@ ucl_elt_obj_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func,
* @param buf target buffer * @param buf target buffer
*/ */
static void static void
ucl_elt_array_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func, ucl_elt_array_write_yaml (const ucl_object_t *obj, struct ucl_emitter_functions *func,
unsigned int tabs, bool start_tabs, bool is_top) unsigned int tabs, bool start_tabs, bool is_top)
{ {
ucl_object_t *cur = obj; const ucl_object_t *cur = obj;
if (start_tabs) { if (start_tabs) {
ucl_add_tabs (func, tabs, false); ucl_add_tabs (func, tabs, false);
@ -591,7 +592,7 @@ ucl_elt_array_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func,
* @param buf buffer * @param buf buffer
*/ */
static void static void
ucl_elt_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func, ucl_elt_write_yaml (const ucl_object_t *obj, struct ucl_emitter_functions *func,
unsigned int tabs, bool start_tabs, bool is_top, bool expand_array) unsigned int tabs, bool start_tabs, bool is_top, bool expand_array)
{ {
bool flag; bool flag;
@ -656,7 +657,7 @@ ucl_elt_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func,
* @return rcl output (should be freed after using) * @return rcl output (should be freed after using)
*/ */
static void static void
ucl_object_emit_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func) ucl_object_emit_yaml (const ucl_object_t *obj, struct ucl_emitter_functions *func)
{ {
ucl_elt_write_yaml (obj, func, 0, false, true, true); ucl_elt_write_yaml (obj, func, 0, false, true, true);
} }
@ -723,7 +724,7 @@ ucl_utstring_append_double (double val, void *ud)
unsigned char * unsigned char *
ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type) ucl_object_emit (const ucl_object_t *obj, enum ucl_emitter emit_type)
{ {
UT_string *buf = NULL; UT_string *buf = NULL;
unsigned char *res = NULL; unsigned char *res = NULL;
@ -763,7 +764,7 @@ ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type)
} }
bool bool
ucl_object_emit_full (ucl_object_t *obj, enum ucl_emitter emit_type, ucl_object_emit_full (const ucl_object_t *obj, enum ucl_emitter emit_type,
struct ucl_emitter_functions *emitter) struct ucl_emitter_functions *emitter)
{ {
if (emit_type == UCL_EMIT_JSON) { if (emit_type == UCL_EMIT_JSON) {
@ -785,7 +786,7 @@ ucl_object_emit_full (ucl_object_t *obj, enum ucl_emitter emit_type,
unsigned char * unsigned char *
ucl_object_emit_single_json (ucl_object_t *obj) ucl_object_emit_single_json (const ucl_object_t *obj)
{ {
UT_string *buf = NULL; UT_string *buf = NULL;
unsigned char *res = NULL; unsigned char *res = NULL;

View File

@ -40,11 +40,15 @@ ucl_hash_create (void)
void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func *func) void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func *func)
{ {
ucl_hash_node_t *elt, *tmp; ucl_hash_node_t *elt, *tmp;
const ucl_object_t *cur, *otmp;
HASH_ITER (hh, hashlin->buckets, elt, tmp) { HASH_ITER (hh, hashlin->buckets, elt, tmp) {
HASH_DELETE (hh, hashlin->buckets, elt); HASH_DELETE (hh, hashlin->buckets, elt);
if (func) { if (func) {
func (elt->data); DL_FOREACH_SAFE (elt->data, cur, otmp) {
/* Need to deconst here */
func (__DECONST (ucl_object_t *, cur));
}
} }
UCL_FREE (sizeof (ucl_hash_node_t), elt); UCL_FREE (sizeof (ucl_hash_node_t), elt);
} }
@ -52,7 +56,8 @@ void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func *func)
} }
void void
ucl_hash_insert (ucl_hash_t* hashlin, ucl_object_t *obj, const char *key, unsigned keylen) ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj,
const char *key, unsigned keylen)
{ {
ucl_hash_node_t *node; ucl_hash_node_t *node;
@ -61,7 +66,7 @@ ucl_hash_insert (ucl_hash_t* hashlin, ucl_object_t *obj, const char *key, unsign
HASH_ADD_KEYPTR (hh, hashlin->buckets, key, keylen, node); HASH_ADD_KEYPTR (hh, hashlin->buckets, key, keylen, node);
} }
void* const void*
ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter) ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter)
{ {
ucl_hash_node_t *elt = *iter; ucl_hash_node_t *elt = *iter;
@ -92,7 +97,7 @@ ucl_hash_iter_has_next (ucl_hash_iter_t iter)
} }
ucl_object_t* const ucl_object_t*
ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen) ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen)
{ {
ucl_hash_node_t *found; ucl_hash_node_t *found;
@ -109,7 +114,7 @@ ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen)
} }
void void
ucl_hash_delete (ucl_hash_t* hashlin, ucl_object_t *obj) ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)
{ {
ucl_hash_node_t *found; ucl_hash_node_t *found;

View File

@ -31,7 +31,7 @@
typedef struct ucl_hash_node_s typedef struct ucl_hash_node_s
{ {
ucl_object_t *data; const ucl_object_t *data;
UT_hash_handle hh; UT_hash_handle hh;
} ucl_hash_node_t; } ucl_hash_node_t;
@ -62,17 +62,19 @@ void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func *func);
/** /**
* Inserts an element in the the hashtable. * Inserts an element in the the hashtable.
*/ */
void ucl_hash_insert (ucl_hash_t* hashlin, ucl_object_t *obj, const char *key, unsigned keylen); void ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj, const char *key,
unsigned keylen);
/** /**
* Delete an element from the the hashtable. * Delete an element from the the hashtable.
*/ */
void ucl_hash_delete (ucl_hash_t* hashlin, ucl_object_t *obj); void ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj);
/** /**
* Searches an element in the hashtable. * Searches an element in the hashtable.
*/ */
ucl_object_t* ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen); const ucl_object_t* ucl_hash_search (ucl_hash_t* hashlin, const char *key,
unsigned keylen);
/** /**
@ -81,7 +83,7 @@ ucl_object_t* ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned ke
* @param iter iterator (must be NULL on first iteration) * @param iter iterator (must be NULL on first iteration)
* @return the next object * @return the next object
*/ */
void* ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter); const void* ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter);
/** /**
* Check whether an iterator has next element * Check whether an iterator has next element

View File

@ -45,7 +45,9 @@
#define HAVE_STDBOOL_H #define HAVE_STDBOOL_H
#define HAVE_STDINT_H #define HAVE_STDINT_H
#define HAVE_STDARG_H #define HAVE_STDARG_H
#define HAVE_REGEX_H #ifndef _WIN32
# define HAVE_REGEX_H
#endif
#endif #endif
#ifdef HAVE_SYS_TYPES_H #ifdef HAVE_SYS_TYPES_H
@ -97,6 +99,10 @@
#include <openssl/evp.h> #include <openssl/evp.h>
#endif #endif
#ifndef __DECONST
#define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
#endif
/** /**
* @file rcl_internal.h * @file rcl_internal.h
* Internal structures and functions of UCL library * Internal structures and functions of UCL library
@ -314,17 +320,17 @@ int ucl_maybe_parse_number (ucl_object_t *obj,
bool allow_double, bool number_bytes, bool allow_time); bool allow_double, bool number_bytes, bool allow_time);
static inline ucl_object_t * static inline const ucl_object_t *
ucl_hash_search_obj (ucl_hash_t* hashlin, ucl_object_t *obj) ucl_hash_search_obj (ucl_hash_t* hashlin, ucl_object_t *obj)
{ {
return (ucl_object_t *)ucl_hash_search (hashlin, obj->key, obj->keylen); return (const ucl_object_t *)ucl_hash_search (hashlin, obj->key, obj->keylen);
} }
static inline ucl_hash_t * static inline ucl_hash_t *
ucl_hash_insert_object (ucl_hash_t *hashlin, ucl_object_t *obj) UCL_WARN_UNUSED_RESULT; ucl_hash_insert_object (ucl_hash_t *hashlin, const ucl_object_t *obj) UCL_WARN_UNUSED_RESULT;
static inline ucl_hash_t * static inline ucl_hash_t *
ucl_hash_insert_object (ucl_hash_t *hashlin, ucl_object_t *obj) ucl_hash_insert_object (ucl_hash_t *hashlin, const ucl_object_t *obj)
{ {
if (hashlin == NULL) { if (hashlin == NULL) {
hashlin = ucl_hash_create (); hashlin = ucl_hash_create ();
@ -339,6 +345,6 @@ ucl_hash_insert_object (ucl_hash_t *hashlin, ucl_object_t *obj)
* @param obj * @param obj
* @return * @return
*/ */
unsigned char * ucl_object_emit_single_json (ucl_object_t *obj); unsigned char * ucl_object_emit_single_json (const ucl_object_t *obj);
#endif /* UCL_INTERNAL_H_ */ #endif /* UCL_INTERNAL_H_ */

View File

@ -55,34 +55,6 @@ struct ucl_parser_saved_state {
(chunk)->remain --; \ (chunk)->remain --; \
} while (0) } while (0)
/**
* Save parser state
* @param chunk
* @param s
*/
static inline void
ucl_chunk_save_state (struct ucl_chunk *chunk, struct ucl_parser_saved_state *s)
{
s->column = chunk->column;
s->pos = chunk->pos;
s->line = chunk->line;
s->remain = chunk->remain;
}
/**
* Restore parser state
* @param chunk
* @param s
*/
static inline void
ucl_chunk_restore_state (struct ucl_chunk *chunk, struct ucl_parser_saved_state *s)
{
chunk->column = s->column;
chunk->pos = s->pos;
chunk->line = s->line;
chunk->remain = s->remain;
}
static inline void static inline void
ucl_set_err (struct ucl_chunk *chunk, int code, const char *str, UT_string **err) ucl_set_err (struct ucl_chunk *chunk, int code, const char *str, UT_string **err)
{ {
@ -1086,19 +1058,19 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke
keylen = ucl_copy_or_store_ptr (parser, c, &nobj->trash_stack[UCL_TRASH_KEY], keylen = ucl_copy_or_store_ptr (parser, c, &nobj->trash_stack[UCL_TRASH_KEY],
&key, end - c, need_unescape, parser->flags & UCL_PARSER_KEY_LOWERCASE, false); &key, end - c, need_unescape, parser->flags & UCL_PARSER_KEY_LOWERCASE, false);
if (keylen == -1) { if (keylen == -1) {
ucl_object_free(nobj); ucl_object_unref (nobj);
return false; return false;
} }
else if (keylen == 0) { else if (keylen == 0) {
ucl_set_err (chunk, UCL_ESYNTAX, "empty keys are not allowed", &parser->err); ucl_set_err (chunk, UCL_ESYNTAX, "empty keys are not allowed", &parser->err);
ucl_object_free(nobj); ucl_object_unref (nobj);
return false; return false;
} }
container = parser->stack->obj->value.ov; container = parser->stack->obj->value.ov;
nobj->key = key; nobj->key = key;
nobj->keylen = keylen; nobj->keylen = keylen;
tobj = ucl_hash_search_obj (container, nobj); tobj = __DECONST (ucl_object_t *, ucl_hash_search_obj (container, nobj));
if (tobj == NULL) { if (tobj == NULL) {
container = ucl_hash_insert_object (container, nobj); container = ucl_hash_insert_object (container, nobj);
nobj->prev = nobj; nobj->prev = nobj;

View File

@ -40,10 +40,10 @@
#include <math.h> #include <math.h>
#endif #endif
static bool ucl_schema_validate (ucl_object_t *schema, static bool ucl_schema_validate (const ucl_object_t *schema,
ucl_object_t *obj, bool try_array, const ucl_object_t *obj, bool try_array,
struct ucl_schema_error *err, struct ucl_schema_error *err,
ucl_object_t *root); const ucl_object_t *root);
static bool static bool
ucl_string_to_type (const char *input, ucl_type_t *res) ucl_string_to_type (const char *input, ucl_type_t *res)
@ -115,7 +115,7 @@ ucl_object_type_to_string (ucl_type_t type)
*/ */
static void static void
ucl_schema_create_error (struct ucl_schema_error *err, ucl_schema_create_error (struct ucl_schema_error *err,
enum ucl_schema_error_code code, ucl_object_t *obj, enum ucl_schema_error_code code, const ucl_object_t *obj,
const char *fmt, ...) const char *fmt, ...)
{ {
va_list va; va_list va;
@ -132,11 +132,13 @@ ucl_schema_create_error (struct ucl_schema_error *err,
/* /*
* Check whether we have a pattern specified * Check whether we have a pattern specified
*/ */
static ucl_object_t * static const ucl_object_t *
ucl_schema_test_pattern (ucl_object_t *obj, const char *pattern) ucl_schema_test_pattern (const ucl_object_t *obj, const char *pattern)
{ {
const ucl_object_t *res = NULL;
#ifdef HAVE_REGEX_H
regex_t reg; regex_t reg;
ucl_object_t *res = NULL, *elt; const ucl_object_t *elt;
ucl_object_iter_t iter = NULL; ucl_object_iter_t iter = NULL;
if (regcomp (&reg, pattern, REG_EXTENDED | REG_NOSUB) == 0) { if (regcomp (&reg, pattern, REG_EXTENDED | REG_NOSUB) == 0) {
@ -148,7 +150,7 @@ ucl_schema_test_pattern (ucl_object_t *obj, const char *pattern)
} }
regfree (&reg); regfree (&reg);
} }
#endif
return res; return res;
} }
@ -156,11 +158,11 @@ ucl_schema_test_pattern (ucl_object_t *obj, const char *pattern)
* Check dependencies for an object * Check dependencies for an object
*/ */
static bool static bool
ucl_schema_validate_dependencies (ucl_object_t *deps, ucl_schema_validate_dependencies (const ucl_object_t *deps,
ucl_object_t *obj, struct ucl_schema_error *err, const ucl_object_t *obj, struct ucl_schema_error *err,
ucl_object_t *root) const ucl_object_t *root)
{ {
ucl_object_t *elt, *cur, *cur_dep; const ucl_object_t *elt, *cur, *cur_dep;
ucl_object_iter_t iter = NULL, piter; ucl_object_iter_t iter = NULL, piter;
bool ret = true; bool ret = true;
@ -193,11 +195,11 @@ ucl_schema_validate_dependencies (ucl_object_t *deps,
* Validate object * Validate object
*/ */
static bool static bool
ucl_schema_validate_object (ucl_object_t *schema, ucl_schema_validate_object (const ucl_object_t *schema,
ucl_object_t *obj, struct ucl_schema_error *err, const ucl_object_t *obj, struct ucl_schema_error *err,
ucl_object_t *root) const ucl_object_t *root)
{ {
ucl_object_t *elt, *prop, *found, *additional_schema = NULL, const ucl_object_t *elt, *prop, *found, *additional_schema = NULL,
*required = NULL, *pat, *pelt; *required = NULL, *pat, *pelt;
ucl_object_iter_t iter = NULL, piter = NULL; ucl_object_iter_t iter = NULL, piter = NULL;
bool ret = true, allow_additional = true; bool ret = true, allow_additional = true;
@ -334,10 +336,10 @@ ucl_schema_validate_object (ucl_object_t *schema,
} }
static bool static bool
ucl_schema_validate_number (ucl_object_t *schema, ucl_schema_validate_number (const ucl_object_t *schema,
ucl_object_t *obj, struct ucl_schema_error *err) const ucl_object_t *obj, struct ucl_schema_error *err)
{ {
ucl_object_t *elt, *test; const ucl_object_t *elt, *test;
ucl_object_iter_t iter = NULL; ucl_object_iter_t iter = NULL;
bool ret = true, exclusive = false; bool ret = true, exclusive = false;
double constraint, val; double constraint, val;
@ -400,14 +402,16 @@ ucl_schema_validate_number (ucl_object_t *schema,
} }
static bool static bool
ucl_schema_validate_string (ucl_object_t *schema, ucl_schema_validate_string (const ucl_object_t *schema,
ucl_object_t *obj, struct ucl_schema_error *err) const ucl_object_t *obj, struct ucl_schema_error *err)
{ {
ucl_object_t *elt; const ucl_object_t *elt;
ucl_object_iter_t iter = NULL; ucl_object_iter_t iter = NULL;
bool ret = true; bool ret = true;
int64_t constraint; int64_t constraint;
#ifdef HAVE_REGEX_H
regex_t re; regex_t re;
#endif
while (ret && (elt = ucl_iterate_object (schema, &iter, true)) != NULL) { while (ret && (elt = ucl_iterate_object (schema, &iter, true)) != NULL) {
if (elt->type == UCL_INT && if (elt->type == UCL_INT &&
@ -432,6 +436,7 @@ ucl_schema_validate_string (ucl_object_t *schema,
break; break;
} }
} }
#ifdef HAVE_REGEX_H
else if (elt->type == UCL_STRING && else if (elt->type == UCL_STRING &&
strcmp (ucl_object_key (elt), "pattern") == 0) { strcmp (ucl_object_key (elt), "pattern") == 0) {
if (regcomp (&re, ucl_object_tostring (elt), if (regcomp (&re, ucl_object_tostring (elt),
@ -449,13 +454,14 @@ ucl_schema_validate_string (ucl_object_t *schema,
} }
regfree (&re); regfree (&re);
} }
#endif
} }
return ret; return ret;
} }
struct ucl_compare_node { struct ucl_compare_node {
ucl_object_t *obj; const ucl_object_t *obj;
TREE_ENTRY(ucl_compare_node) link; TREE_ENTRY(ucl_compare_node) link;
struct ucl_compare_node *next; struct ucl_compare_node *next;
}; };
@ -467,17 +473,17 @@ TREE_DEFINE(ucl_compare_node, link)
static int static int
ucl_schema_elt_compare (struct ucl_compare_node *n1, struct ucl_compare_node *n2) ucl_schema_elt_compare (struct ucl_compare_node *n1, struct ucl_compare_node *n2)
{ {
ucl_object_t *o1 = n1->obj, *o2 = n2->obj; const ucl_object_t *o1 = n1->obj, *o2 = n2->obj;
return ucl_object_compare (o1, o2); return ucl_object_compare (o1, o2);
} }
static bool static bool
ucl_schema_array_is_unique (ucl_object_t *obj, struct ucl_schema_error *err) ucl_schema_array_is_unique (const ucl_object_t *obj, struct ucl_schema_error *err)
{ {
ucl_compare_tree_t tree = TREE_INITIALIZER (ucl_schema_elt_compare); ucl_compare_tree_t tree = TREE_INITIALIZER (ucl_schema_elt_compare);
ucl_object_iter_t iter = NULL; ucl_object_iter_t iter = NULL;
ucl_object_t *elt; const ucl_object_t *elt;
struct ucl_compare_node *node, test, *nodes = NULL, *tmp; struct ucl_compare_node *node, test, *nodes = NULL, *tmp;
bool ret = true; bool ret = true;
@ -510,11 +516,11 @@ ucl_schema_array_is_unique (ucl_object_t *obj, struct ucl_schema_error *err)
} }
static bool static bool
ucl_schema_validate_array (ucl_object_t *schema, ucl_schema_validate_array (const ucl_object_t *schema,
ucl_object_t *obj, struct ucl_schema_error *err, const ucl_object_t *obj, struct ucl_schema_error *err,
ucl_object_t *root) const ucl_object_t *root)
{ {
ucl_object_t *elt, *it, *found, *additional_schema = NULL, const ucl_object_t *elt, *it, *found, *additional_schema = NULL,
*first_unvalidated = NULL; *first_unvalidated = NULL;
ucl_object_iter_t iter = NULL, piter = NULL; ucl_object_iter_t iter = NULL, piter = NULL;
bool ret = true, allow_additional = true, need_unique = false; bool ret = true, allow_additional = true, need_unique = false;
@ -627,11 +633,11 @@ ucl_schema_validate_array (ucl_object_t *schema,
* Returns whether this object is allowed for this type * Returns whether this object is allowed for this type
*/ */
static bool static bool
ucl_schema_type_is_allowed (ucl_object_t *type, ucl_object_t *obj, ucl_schema_type_is_allowed (const ucl_object_t *type, const ucl_object_t *obj,
struct ucl_schema_error *err) struct ucl_schema_error *err)
{ {
ucl_object_iter_t iter = NULL; ucl_object_iter_t iter = NULL;
ucl_object_t *elt; const ucl_object_t *elt;
const char *type_str; const char *type_str;
ucl_type_t t; ucl_type_t t;
@ -683,11 +689,11 @@ ucl_schema_type_is_allowed (ucl_object_t *type, ucl_object_t *obj,
* Check if object is equal to one of elements of enum * Check if object is equal to one of elements of enum
*/ */
static bool static bool
ucl_schema_validate_enum (ucl_object_t *en, ucl_object_t *obj, ucl_schema_validate_enum (const ucl_object_t *en, const ucl_object_t *obj,
struct ucl_schema_error *err) struct ucl_schema_error *err)
{ {
ucl_object_iter_t iter = NULL; ucl_object_iter_t iter = NULL;
ucl_object_t *elt; const ucl_object_t *elt;
bool ret = false; bool ret = false;
while ((elt = ucl_iterate_object (en, &iter, true)) != NULL) { while ((elt = ucl_iterate_object (en, &iter, true)) != NULL) {
@ -709,12 +715,12 @@ ucl_schema_validate_enum (ucl_object_t *en, ucl_object_t *obj,
/* /*
* Check a single ref component * Check a single ref component
*/ */
static ucl_object_t * static const ucl_object_t *
ucl_schema_resolve_ref_component (ucl_object_t *cur, ucl_schema_resolve_ref_component (const ucl_object_t *cur,
const char *refc, int len, const char *refc, int len,
struct ucl_schema_error *err) struct ucl_schema_error *err)
{ {
ucl_object_t *res = NULL; const ucl_object_t *res = NULL;
char *err_str; char *err_str;
int num, i; int num, i;
@ -762,12 +768,12 @@ ucl_schema_resolve_ref_component (ucl_object_t *cur,
/* /*
* Find reference schema * Find reference schema
*/ */
static ucl_object_t * static const ucl_object_t *
ucl_schema_resolve_ref (ucl_object_t *root, const char *ref, ucl_schema_resolve_ref (const ucl_object_t *root, const char *ref,
struct ucl_schema_error *err) struct ucl_schema_error *err)
{ {
const char *p, *c; const char *p, *c;
ucl_object_t *res = NULL; const ucl_object_t *res = NULL;
if (ref[0] != '#') { if (ref[0] != '#') {
@ -822,10 +828,10 @@ ucl_schema_resolve_ref (ucl_object_t *root, const char *ref,
} }
static bool static bool
ucl_schema_validate_values (ucl_object_t *schema, ucl_object_t *obj, ucl_schema_validate_values (const ucl_object_t *schema, const ucl_object_t *obj,
struct ucl_schema_error *err) struct ucl_schema_error *err)
{ {
ucl_object_t *elt, *cur; const ucl_object_t *elt, *cur;
int64_t constraint, i; int64_t constraint, i;
elt = ucl_object_find_key (schema, "maxValues"); elt = ucl_object_find_key (schema, "maxValues");
@ -868,12 +874,12 @@ ucl_schema_validate_values (ucl_object_t *schema, ucl_object_t *obj,
} }
static bool static bool
ucl_schema_validate (ucl_object_t *schema, ucl_schema_validate (const ucl_object_t *schema,
ucl_object_t *obj, bool try_array, const ucl_object_t *obj, bool try_array,
struct ucl_schema_error *err, struct ucl_schema_error *err,
ucl_object_t *root) const ucl_object_t *root)
{ {
ucl_object_t *elt, *cur; const ucl_object_t *elt, *cur;
ucl_object_iter_t iter = NULL; ucl_object_iter_t iter = NULL;
bool ret; bool ret;
@ -1001,8 +1007,8 @@ ucl_schema_validate (ucl_object_t *schema,
} }
bool bool
ucl_object_validate (ucl_object_t *schema, ucl_object_validate (const ucl_object_t *schema,
ucl_object_t *obj, struct ucl_schema_error *err) const ucl_object_t *obj, struct ucl_schema_error *err)
{ {
return ucl_schema_validate (schema, obj, true, err, schema); return ucl_schema_validate (schema, obj, true, err, schema);
} }

View File

@ -134,35 +134,76 @@ static char* ucl_realpath(const char *path, char *resolved_path) {
* Utilities for rcl parsing * Utilities for rcl parsing
*/ */
typedef void (*ucl_object_dtor) (ucl_object_t *obj);
static void ucl_object_free_internal (ucl_object_t *obj, bool allow_rec,
ucl_object_dtor dtor);
static void ucl_object_dtor_unref (ucl_object_t *obj);
static void static void
ucl_object_free_internal (ucl_object_t *obj, bool allow_rec) ucl_object_dtor_free (ucl_object_t *obj)
{
if (obj->trash_stack[UCL_TRASH_KEY] != NULL) {
UCL_FREE (obj->hh.keylen, obj->trash_stack[UCL_TRASH_KEY]);
}
if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
UCL_FREE (obj->len, obj->trash_stack[UCL_TRASH_VALUE]);
}
UCL_FREE (sizeof (ucl_object_t), obj);
}
/*
* This is a helper function that performs exactly the same as
* `ucl_object_unref` but it doesn't iterate over elements allowing
* to use it for individual elements of arrays and multiple values
*/
static void
ucl_object_dtor_unref_single (ucl_object_t *obj)
{
if (obj != NULL) {
#ifdef HAVE_ATOMIC_BUILTINS
unsigned int rc = __sync_sub_and_fetch (&obj->ref, 1);
if (rc == 0) {
#else
if (--obj->ref == 0) {
#endif
ucl_object_free_internal (obj, false, ucl_object_dtor_unref);
}
}
}
static void
ucl_object_dtor_unref (ucl_object_t *obj)
{
if (obj->ref == 0) {
ucl_object_dtor_free (obj);
}
else {
/* This may cause dtor unref being called one more time */
ucl_object_dtor_unref_single (obj);
}
}
static void
ucl_object_free_internal (ucl_object_t *obj, bool allow_rec, ucl_object_dtor dtor)
{ {
ucl_object_t *sub, *tmp; ucl_object_t *sub, *tmp;
while (obj != NULL) { while (obj != NULL) {
if (obj->trash_stack[UCL_TRASH_KEY] != NULL) {
UCL_FREE (obj->hh.keylen, obj->trash_stack[UCL_TRASH_KEY]);
}
if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
UCL_FREE (obj->len, obj->trash_stack[UCL_TRASH_VALUE]);
}
if (obj->type == UCL_ARRAY) { if (obj->type == UCL_ARRAY) {
sub = obj->value.av; sub = obj->value.av;
while (sub != NULL) { while (sub != NULL) {
tmp = sub->next; tmp = sub->next;
ucl_object_free_internal (sub, false); dtor (sub);
sub = tmp; sub = tmp;
} }
} }
else if (obj->type == UCL_OBJECT) { else if (obj->type == UCL_OBJECT) {
if (obj->value.ov != NULL) { if (obj->value.ov != NULL) {
ucl_hash_destroy (obj->value.ov, (ucl_hash_free_func *)ucl_object_unref); ucl_hash_destroy (obj->value.ov, (ucl_hash_free_func *)dtor);
} }
} }
tmp = obj->next; tmp = obj->next;
UCL_FREE (sizeof (ucl_object_t), obj); dtor (obj);
obj = tmp; obj = tmp;
if (!allow_rec) { if (!allow_rec) {
@ -174,7 +215,7 @@ ucl_object_free_internal (ucl_object_t *obj, bool allow_rec)
void void
ucl_object_free (ucl_object_t *obj) ucl_object_free (ucl_object_t *obj)
{ {
ucl_object_free_internal (obj, true); ucl_object_free_internal (obj, true, ucl_object_dtor_free);
} }
size_t size_t
@ -282,47 +323,54 @@ ucl_unescape_json_string (char *str, size_t len)
return (t - str); return (t - str);
} }
UCL_EXTERN char * char *
ucl_copy_key_trash (ucl_object_t *obj) ucl_copy_key_trash (const ucl_object_t *obj)
{ {
ucl_object_t *deconst;
if (obj == NULL) { if (obj == NULL) {
return NULL; return NULL;
} }
if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->key != NULL) { if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->key != NULL) {
obj->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1); deconst = __DECONST (ucl_object_t *, obj);
if (obj->trash_stack[UCL_TRASH_KEY] != NULL) { deconst->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1);
memcpy (obj->trash_stack[UCL_TRASH_KEY], obj->key, obj->keylen); if (deconst->trash_stack[UCL_TRASH_KEY] != NULL) {
obj->trash_stack[UCL_TRASH_KEY][obj->keylen] = '\0'; memcpy (deconst->trash_stack[UCL_TRASH_KEY], obj->key, obj->keylen);
deconst->trash_stack[UCL_TRASH_KEY][obj->keylen] = '\0';
} }
obj->key = obj->trash_stack[UCL_TRASH_KEY]; deconst->key = obj->trash_stack[UCL_TRASH_KEY];
obj->flags |= UCL_OBJECT_ALLOCATED_KEY; deconst->flags |= UCL_OBJECT_ALLOCATED_KEY;
} }
return obj->trash_stack[UCL_TRASH_KEY]; return obj->trash_stack[UCL_TRASH_KEY];
} }
UCL_EXTERN char * char *
ucl_copy_value_trash (ucl_object_t *obj) ucl_copy_value_trash (const ucl_object_t *obj)
{ {
ucl_object_t *deconst;
if (obj == NULL) { if (obj == NULL) {
return NULL; return NULL;
} }
if (obj->trash_stack[UCL_TRASH_VALUE] == NULL) { if (obj->trash_stack[UCL_TRASH_VALUE] == NULL) {
deconst = __DECONST (ucl_object_t *, obj);
if (obj->type == UCL_STRING) { if (obj->type == UCL_STRING) {
/* Special case for strings */ /* Special case for strings */
obj->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1); deconst->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1);
if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) { if (deconst->trash_stack[UCL_TRASH_VALUE] != NULL) {
memcpy (obj->trash_stack[UCL_TRASH_VALUE], obj->value.sv, obj->len); memcpy (deconst->trash_stack[UCL_TRASH_VALUE], obj->value.sv, obj->len);
obj->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0'; deconst->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0';
obj->value.sv = obj->trash_stack[UCL_TRASH_VALUE]; deconst->value.sv = obj->trash_stack[UCL_TRASH_VALUE];
} }
} }
else { else {
/* Just emit value in json notation */ /* Just emit value in json notation */
obj->trash_stack[UCL_TRASH_VALUE] = ucl_object_emit_single_json (obj); deconst->trash_stack[UCL_TRASH_VALUE] = ucl_object_emit_single_json (obj);
obj->len = strlen (obj->trash_stack[UCL_TRASH_VALUE]); deconst->len = strlen (obj->trash_stack[UCL_TRASH_VALUE]);
} }
obj->flags |= UCL_OBJECT_ALLOCATED_VALUE; deconst->flags |= UCL_OBJECT_ALLOCATED_VALUE;
} }
return obj->trash_stack[UCL_TRASH_VALUE]; return obj->trash_stack[UCL_TRASH_VALUE];
} }
@ -1084,21 +1132,22 @@ ucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags
return obj; return obj;
} }
static ucl_object_t * static bool
ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt, ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt,
const char *key, size_t keylen, bool copy_key, bool merge, bool replace) const char *key, size_t keylen, bool copy_key, bool merge, bool replace)
{ {
ucl_object_t *found, *cur; ucl_object_t *found, *tmp;
const ucl_object_t *cur;
ucl_object_iter_t it = NULL; ucl_object_iter_t it = NULL;
const char *p; const char *p;
int ret = true;
if (elt == NULL || key == NULL) { if (elt == NULL || key == NULL) {
return NULL; return false;
} }
if (top == NULL) { if (top == NULL) {
top = ucl_object_new (); return false;
top->type = UCL_OBJECT;
} }
if (top->type != UCL_OBJECT) { if (top->type != UCL_OBJECT) {
@ -1108,7 +1157,7 @@ ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt,
} }
else { else {
/* Refuse converting of other object types */ /* Refuse converting of other object types */
return top; return false;
} }
} }
@ -1134,12 +1183,15 @@ ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt,
ucl_copy_key_trash (elt); ucl_copy_key_trash (elt);
} }
found = ucl_hash_search_obj (top->value.ov, elt); found = __DECONST (ucl_object_t *, ucl_hash_search_obj (top->value.ov, elt));
if (!found) { if (!found) {
top->value.ov = ucl_hash_insert_object (top->value.ov, elt); top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
DL_APPEND (found, elt); DL_APPEND (found, elt);
top->len ++; top->len ++;
if (replace) {
ret = false;
}
} }
else { else {
if (replace) { if (replace) {
@ -1152,19 +1204,22 @@ ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt,
else if (merge) { else if (merge) {
if (found->type != UCL_OBJECT && elt->type == UCL_OBJECT) { if (found->type != UCL_OBJECT && elt->type == UCL_OBJECT) {
/* Insert old elt to new one */ /* Insert old elt to new one */
elt = ucl_object_insert_key_common (elt, found, found->key, found->keylen, copy_key, false, false); ucl_object_insert_key_common (elt, found, found->key,
found->keylen, copy_key, false, false);
ucl_hash_delete (top->value.ov, found); ucl_hash_delete (top->value.ov, found);
top->value.ov = ucl_hash_insert_object (top->value.ov, elt); top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
} }
else if (found->type == UCL_OBJECT && elt->type != UCL_OBJECT) { else if (found->type == UCL_OBJECT && elt->type != UCL_OBJECT) {
/* Insert new to old */ /* Insert new to old */
found = ucl_object_insert_key_common (found, elt, elt->key, elt->keylen, copy_key, false, false); ucl_object_insert_key_common (found, elt, elt->key,
elt->keylen, copy_key, false, false);
} }
else if (found->type == UCL_OBJECT && elt->type == UCL_OBJECT) { else if (found->type == UCL_OBJECT && elt->type == UCL_OBJECT) {
/* Mix two hashes */ /* Mix two hashes */
while ((cur = ucl_iterate_object (elt, &it, true)) != NULL) { while ((cur = ucl_iterate_object (elt, &it, true)) != NULL) {
ucl_object_ref (cur); tmp = ucl_object_ref (cur);
found = ucl_object_insert_key_common (found, cur, cur->key, cur->keylen, copy_key, false, false); ucl_object_insert_key_common (found, tmp, cur->key,
cur->keylen, copy_key, false, false);
} }
ucl_object_unref (elt); ucl_object_unref (elt);
} }
@ -1178,11 +1233,11 @@ ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt,
} }
} }
return top; return ret;
} }
bool bool
ucl_object_delete_keyl(ucl_object_t *top, const char *key, size_t keylen) ucl_object_delete_keyl (ucl_object_t *top, const char *key, size_t keylen)
{ {
ucl_object_t *found; ucl_object_t *found;
@ -1190,13 +1245,13 @@ ucl_object_delete_keyl(ucl_object_t *top, const char *key, size_t keylen)
return false; return false;
} }
found = ucl_object_find_keyl(top, key, keylen); found = __DECONST (ucl_object_t *, ucl_object_find_keyl (top, key, keylen));
if (found == NULL) { if (found == NULL) {
return false; return false;
} }
ucl_hash_delete(top->value.ov, found); ucl_hash_delete (top->value.ov, found);
ucl_object_unref (found); ucl_object_unref (found);
top->len --; top->len --;
@ -1204,61 +1259,62 @@ ucl_object_delete_keyl(ucl_object_t *top, const char *key, size_t keylen)
} }
bool bool
ucl_object_delete_key(ucl_object_t *top, const char *key) ucl_object_delete_key (ucl_object_t *top, const char *key)
{ {
return ucl_object_delete_keyl(top, key, 0); return ucl_object_delete_keyl (top, key, strlen(key));
} }
ucl_object_t* ucl_object_t*
ucl_object_pop_keyl (ucl_object_t *top, const char *key, size_t keylen) ucl_object_pop_keyl (ucl_object_t *top, const char *key, size_t keylen)
{ {
ucl_object_t *found; const ucl_object_t *found;
if (top == NULL || key == NULL) { if (top == NULL || key == NULL) {
return false; return false;
} }
found = ucl_object_find_keyl(top, key, keylen); found = ucl_object_find_keyl (top, key, keylen);
if (found == NULL) { if (found == NULL) {
return NULL; return NULL;
} }
ucl_hash_delete(top->value.ov, found); ucl_hash_delete (top->value.ov, found);
top->len --; top->len --;
return found; return __DECONST (ucl_object_t *, found);
} }
ucl_object_t* ucl_object_t*
ucl_object_pop_key (ucl_object_t *top, const char *key) ucl_object_pop_key (ucl_object_t *top, const char *key)
{ {
return ucl_object_pop_keyl (top, key, 0); return ucl_object_pop_keyl (top, key, strlen(key));
} }
ucl_object_t * bool
ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt,
const char *key, size_t keylen, bool copy_key) const char *key, size_t keylen, bool copy_key)
{ {
return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, false); return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, false);
} }
ucl_object_t * bool
ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt, ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt,
const char *key, size_t keylen, bool copy_key) const char *key, size_t keylen, bool copy_key)
{ {
return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, true, false); return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, true, false);
} }
ucl_object_t * bool
ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt, ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt,
const char *key, size_t keylen, bool copy_key) const char *key, size_t keylen, bool copy_key)
{ {
return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, true); return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, true);
} }
ucl_object_t * const ucl_object_t *
ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen) ucl_object_find_keyl (const ucl_object_t *obj, const char *key, size_t klen)
{ {
ucl_object_t *ret, srch; const ucl_object_t *ret;
ucl_object_t srch;
if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) { if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) {
return NULL; return NULL;
@ -1271,11 +1327,12 @@ ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen)
return ret; return ret;
} }
ucl_object_t * const ucl_object_t *
ucl_object_find_key (ucl_object_t *obj, const char *key) ucl_object_find_key (const ucl_object_t *obj, const char *key)
{ {
size_t klen; size_t klen;
ucl_object_t *ret, srch; const ucl_object_t *ret;
ucl_object_t srch;
if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) { if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) {
return NULL; return NULL;
@ -1289,10 +1346,10 @@ ucl_object_find_key (ucl_object_t *obj, const char *key)
return ret; return ret;
} }
ucl_object_t* const ucl_object_t*
ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values) ucl_iterate_object (const ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values)
{ {
ucl_object_t *elt; const ucl_object_t *elt;
if (obj == NULL || iter == NULL) { if (obj == NULL || iter == NULL) {
return NULL; return NULL;
@ -1301,7 +1358,7 @@ ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_valu
if (expand_values) { if (expand_values) {
switch (obj->type) { switch (obj->type) {
case UCL_OBJECT: case UCL_OBJECT:
return (ucl_object_t*)ucl_hash_iterate (obj->value.ov, iter); return (const ucl_object_t*)ucl_hash_iterate (obj->value.ov, iter);
break; break;
case UCL_ARRAY: case UCL_ARRAY:
elt = *iter; elt = *iter;
@ -1332,7 +1389,7 @@ ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_valu
else if (elt == obj) { else if (elt == obj) {
return NULL; return NULL;
} }
*iter = elt->next ? elt->next : obj; *iter = __DECONST (void *, elt->next ? elt->next : obj);
return elt; return elt;
/* Not reached */ /* Not reached */
@ -1420,72 +1477,55 @@ ucl_object_frombool (bool bv)
return obj; return obj;
} }
ucl_object_t * bool
ucl_array_append (ucl_object_t *top, ucl_object_t *elt) ucl_array_append (ucl_object_t *top, ucl_object_t *elt)
{ {
ucl_object_t *head; ucl_object_t *head;
if (elt == NULL) { if (elt == NULL || top == NULL) {
return NULL; return false;
} }
if (top == NULL) { head = top->value.av;
top = ucl_object_typed_new (UCL_ARRAY); if (head == NULL) {
top->value.av = elt; top->value.av = elt;
elt->next = NULL;
elt->prev = elt; elt->prev = elt;
top->len = 1;
} }
else { else {
head = top->value.av; elt->prev = head->prev;
if (head == NULL) { head->prev->next = elt;
top->value.av = elt; head->prev = elt;
elt->prev = elt;
}
else {
elt->prev = head->prev;
head->prev->next = elt;
head->prev = elt;
}
elt->next = NULL;
top->len ++;
} }
elt->next = NULL;
top->len ++;
return top; return true;
} }
ucl_object_t * bool
ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt) ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt)
{ {
ucl_object_t *head; ucl_object_t *head;
if (elt == NULL) { if (elt == NULL || top == NULL) {
return NULL; return false;
} }
if (top == NULL) {
top = ucl_object_typed_new (UCL_ARRAY); head = top->value.av;
if (head == NULL) {
top->value.av = elt; top->value.av = elt;
elt->next = NULL;
elt->prev = elt; elt->prev = elt;
top->len = 1;
} }
else { else {
head = top->value.av; elt->prev = head->prev;
if (head == NULL) { head->prev = elt;
top->value.av = elt;
elt->prev = elt;
}
else {
elt->prev = head->prev;
head->prev = elt;
}
elt->next = head;
top->value.av = elt;
top->len ++;
} }
elt->next = head;
top->value.av = elt;
top->len ++;
return top; return true;
} }
ucl_object_t * ucl_object_t *
@ -1521,8 +1561,8 @@ ucl_array_delete (ucl_object_t *top, ucl_object_t *elt)
return elt; return elt;
} }
ucl_object_t * const ucl_object_t *
ucl_array_head (ucl_object_t *top) ucl_array_head (const ucl_object_t *top)
{ {
if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) { if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
return NULL; return NULL;
@ -1530,8 +1570,8 @@ ucl_array_head (ucl_object_t *top)
return top->value.av; return top->value.av;
} }
ucl_object_t * const ucl_object_t *
ucl_array_tail (ucl_object_t *top) ucl_array_tail (const ucl_object_t *top)
{ {
if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) { if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
return NULL; return NULL;
@ -1542,13 +1582,13 @@ ucl_array_tail (ucl_object_t *top)
ucl_object_t * ucl_object_t *
ucl_array_pop_last (ucl_object_t *top) ucl_array_pop_last (ucl_object_t *top)
{ {
return ucl_array_delete (top, ucl_array_tail (top)); return ucl_array_delete (top, __DECONST(ucl_object_t *, ucl_array_tail (top)));
} }
ucl_object_t * ucl_object_t *
ucl_array_pop_first (ucl_object_t *top) ucl_array_pop_first (ucl_object_t *top)
{ {
return ucl_array_delete (top, ucl_array_head (top)); return ucl_array_delete (top, __DECONST(ucl_object_t *, ucl_array_head (top)));
} }
ucl_object_t * ucl_object_t *
@ -1571,7 +1611,7 @@ ucl_elt_append (ucl_object_t *head, ucl_object_t *elt)
} }
bool bool
ucl_object_todouble_safe (ucl_object_t *obj, double *target) ucl_object_todouble_safe (const ucl_object_t *obj, double *target)
{ {
if (obj == NULL || target == NULL) { if (obj == NULL || target == NULL) {
return false; return false;
@ -1592,7 +1632,7 @@ ucl_object_todouble_safe (ucl_object_t *obj, double *target)
} }
double double
ucl_object_todouble (ucl_object_t *obj) ucl_object_todouble (const ucl_object_t *obj)
{ {
double result = 0.; double result = 0.;
@ -1601,7 +1641,7 @@ ucl_object_todouble (ucl_object_t *obj)
} }
bool bool
ucl_object_toint_safe (ucl_object_t *obj, int64_t *target) ucl_object_toint_safe (const ucl_object_t *obj, int64_t *target)
{ {
if (obj == NULL || target == NULL) { if (obj == NULL || target == NULL) {
return false; return false;
@ -1622,7 +1662,7 @@ ucl_object_toint_safe (ucl_object_t *obj, int64_t *target)
} }
int64_t int64_t
ucl_object_toint (ucl_object_t *obj) ucl_object_toint (const ucl_object_t *obj)
{ {
int64_t result = 0; int64_t result = 0;
@ -1631,7 +1671,7 @@ ucl_object_toint (ucl_object_t *obj)
} }
bool bool
ucl_object_toboolean_safe (ucl_object_t *obj, bool *target) ucl_object_toboolean_safe (const ucl_object_t *obj, bool *target)
{ {
if (obj == NULL || target == NULL) { if (obj == NULL || target == NULL) {
return false; return false;
@ -1648,7 +1688,7 @@ ucl_object_toboolean_safe (ucl_object_t *obj, bool *target)
} }
bool bool
ucl_object_toboolean (ucl_object_t *obj) ucl_object_toboolean (const ucl_object_t *obj)
{ {
bool result = false; bool result = false;
@ -1657,7 +1697,7 @@ ucl_object_toboolean (ucl_object_t *obj)
} }
bool bool
ucl_object_tostring_safe (ucl_object_t *obj, const char **target) ucl_object_tostring_safe (const ucl_object_t *obj, const char **target)
{ {
if (obj == NULL || target == NULL) { if (obj == NULL || target == NULL) {
return false; return false;
@ -1675,7 +1715,7 @@ ucl_object_tostring_safe (ucl_object_t *obj, const char **target)
} }
const char * const char *
ucl_object_tostring (ucl_object_t *obj) ucl_object_tostring (const ucl_object_t *obj)
{ {
const char *result = NULL; const char *result = NULL;
@ -1684,13 +1724,13 @@ ucl_object_tostring (ucl_object_t *obj)
} }
const char * const char *
ucl_object_tostring_forced (ucl_object_t *obj) ucl_object_tostring_forced (const ucl_object_t *obj)
{ {
return ucl_copy_value_trash (obj); return ucl_copy_value_trash (obj);
} }
bool bool
ucl_object_tolstring_safe (ucl_object_t *obj, const char **target, size_t *tlen) ucl_object_tolstring_safe (const ucl_object_t *obj, const char **target, size_t *tlen)
{ {
if (obj == NULL || target == NULL) { if (obj == NULL || target == NULL) {
return false; return false;
@ -1710,7 +1750,7 @@ ucl_object_tolstring_safe (ucl_object_t *obj, const char **target, size_t *tlen)
} }
const char * const char *
ucl_object_tolstring (ucl_object_t *obj, size_t *tlen) ucl_object_tolstring (const ucl_object_t *obj, size_t *tlen)
{ {
const char *result = NULL; const char *result = NULL;
@ -1719,13 +1759,13 @@ ucl_object_tolstring (ucl_object_t *obj, size_t *tlen)
} }
const char * const char *
ucl_object_key (ucl_object_t *obj) ucl_object_key (const ucl_object_t *obj)
{ {
return ucl_copy_key_trash (obj); return ucl_copy_key_trash (obj);
} }
const char * const char *
ucl_object_keyl (ucl_object_t *obj, size_t *len) ucl_object_keyl (const ucl_object_t *obj, size_t *len)
{ {
if (len == NULL || obj == NULL) { if (len == NULL || obj == NULL) {
return NULL; return NULL;
@ -1735,26 +1775,40 @@ ucl_object_keyl (ucl_object_t *obj, size_t *len)
} }
ucl_object_t * ucl_object_t *
ucl_object_ref (ucl_object_t *obj) ucl_object_ref (const ucl_object_t *obj)
{ {
ucl_object_t *res = NULL;
if (obj != NULL) { if (obj != NULL) {
obj->ref ++; res = __DECONST (ucl_object_t *, obj);
#ifdef HAVE_ATOMIC_BUILTINS
(void)__sync_add_and_fetch (&res->ref, 1);
#else
res->ref ++;
#endif
} }
return obj; return res;
} }
void void
ucl_object_unref (ucl_object_t *obj) ucl_object_unref (ucl_object_t *obj)
{ {
if (obj != NULL && --obj->ref <= 0) { if (obj != NULL) {
ucl_object_free (obj); #ifdef HAVE_ATOMIC_BUILTINS
unsigned int rc = __sync_sub_and_fetch (&obj->ref, 1);
if (rc == 0) {
#else
if (--obj->ref == 0) {
#endif
ucl_object_free_internal (obj, true, ucl_object_dtor_unref);
}
} }
} }
int int
ucl_object_compare (ucl_object_t *o1, ucl_object_t *o2) ucl_object_compare (const ucl_object_t *o1, const ucl_object_t *o2)
{ {
ucl_object_t *it1, *it2; const ucl_object_t *it1, *it2;
ucl_object_iter_t iter = NULL; ucl_object_iter_t iter = NULL;
int ret = 0; int ret = 0;
@ -1825,7 +1879,7 @@ ucl_object_compare (ucl_object_t *o1, ucl_object_t *o2)
void void
ucl_object_array_sort (ucl_object_t *ar, ucl_object_array_sort (ucl_object_t *ar,
int (*cmp)(ucl_object_t *o1, ucl_object_t *o2)) int (*cmp)(const ucl_object_t *o1, const ucl_object_t *o2))
{ {
if (cmp == NULL || ar == NULL || ar->type != UCL_ARRAY) { if (cmp == NULL || ar == NULL || ar->type != UCL_ARRAY) {
return; return;

View File

@ -78,7 +78,9 @@ main (int argc, char **argv)
while (!feof (in)) { while (!feof (in)) {
memset (inbuf, 0, sizeof (inbuf)); memset (inbuf, 0, sizeof (inbuf));
(void)fread (inbuf, sizeof (inbuf) - 1, 1, in); if (fread (inbuf, 1, sizeof (inbuf) - 1, in) == 0) {
break;
}
inlen = strlen (inbuf); inlen = strlen (inbuf);
test_in = malloc (inlen); test_in = malloc (inlen);
memcpy (test_in, inbuf, inlen); memcpy (test_in, inbuf, inlen);

View File

@ -29,7 +29,7 @@
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
ucl_object_t *obj, *cur, *ar; ucl_object_t *obj, *cur, *ar, *ref;
FILE *out; FILE *out;
unsigned char *emitted; unsigned char *emitted;
const char *fname_out = NULL; const char *fname_out = NULL;
@ -55,62 +55,64 @@ main (int argc, char **argv)
obj = ucl_object_typed_new (UCL_OBJECT); obj = ucl_object_typed_new (UCL_OBJECT);
/* Create some strings */ /* Create some strings */
cur = ucl_object_fromstring_common (" test string ", 0, UCL_STRING_TRIM); cur = ucl_object_fromstring_common (" test string ", 0, UCL_STRING_TRIM);
obj = ucl_object_insert_key (obj, cur, "key1", 0, false); ucl_object_insert_key (obj, cur, "key1", 0, false);
cur = ucl_object_fromstring_common (" test \nstring\n ", 0, UCL_STRING_TRIM | UCL_STRING_ESCAPE); cur = ucl_object_fromstring_common (" test \nstring\n ", 0, UCL_STRING_TRIM | UCL_STRING_ESCAPE);
obj = ucl_object_insert_key (obj, cur, "key2", 0, false); ucl_object_insert_key (obj, cur, "key2", 0, false);
cur = ucl_object_fromstring_common (" test string \n", 0, 0); cur = ucl_object_fromstring_common (" test string \n", 0, 0);
obj = ucl_object_insert_key (obj, cur, "key3", 0, false); ucl_object_insert_key (obj, cur, "key3", 0, false);
/* Array of numbers */ /* Array of numbers */
ar = ucl_object_typed_new (UCL_ARRAY);
cur = ucl_object_fromint (10); cur = ucl_object_fromint (10);
ar = ucl_array_append (NULL, cur); ucl_array_append (ar, cur);
cur = ucl_object_fromdouble (10.1); cur = ucl_object_fromdouble (10.1);
ar = ucl_array_append (ar, cur); ucl_array_append (ar, cur);
cur = ucl_object_fromdouble (9.999); cur = ucl_object_fromdouble (9.999);
ar = ucl_array_prepend (ar, cur); ucl_array_prepend (ar, cur);
/* Removing from an array */ /* Removing from an array */
cur = ucl_object_fromdouble (1.0); cur = ucl_object_fromdouble (1.0);
ar = ucl_array_append (ar, cur); ucl_array_append (ar, cur);
cur = ucl_array_delete (ar, cur); cur = ucl_array_delete (ar, cur);
assert (ucl_object_todouble (cur) == 1.0); assert (ucl_object_todouble (cur) == 1.0);
ucl_object_unref (cur); ucl_object_unref (cur);
cur = ucl_object_fromdouble (2.0); cur = ucl_object_fromdouble (2.0);
ar = ucl_array_append (ar, cur); ucl_array_append (ar, cur);
cur = ucl_array_pop_last (ar); cur = ucl_array_pop_last (ar);
assert (ucl_object_todouble (cur) == 2.0); assert (ucl_object_todouble (cur) == 2.0);
ucl_object_unref (cur); ucl_object_unref (cur);
cur = ucl_object_fromdouble (3.0); cur = ucl_object_fromdouble (3.0);
ar = ucl_array_prepend (ar, cur); ucl_array_prepend (ar, cur);
cur = ucl_array_pop_first (ar); cur = ucl_array_pop_first (ar);
assert (ucl_object_todouble (cur) == 3.0); assert (ucl_object_todouble (cur) == 3.0);
ucl_object_unref (cur); ucl_object_unref (cur);
obj = ucl_object_insert_key (obj, ar, "key4", 0, false); ucl_object_insert_key (obj, ar, "key4", 0, false);
cur = ucl_object_frombool (true); cur = ucl_object_frombool (true);
obj = ucl_object_insert_key (obj, cur, "key4", 0, false); /* Ref object to test refcounts */
ref = ucl_object_ref (cur);
ucl_object_insert_key (obj, cur, "key4", 0, false);
/* Empty strings */ /* Empty strings */
cur = ucl_object_fromstring_common (" ", 0, UCL_STRING_TRIM); cur = ucl_object_fromstring_common (" ", 0, UCL_STRING_TRIM);
obj = ucl_object_insert_key (obj, cur, "key5", 0, false); ucl_object_insert_key (obj, cur, "key5", 0, false);
cur = ucl_object_fromstring_common ("", 0, UCL_STRING_ESCAPE); cur = ucl_object_fromstring_common ("", 0, UCL_STRING_ESCAPE);
obj = ucl_object_insert_key (obj, cur, "key6", 0, false); ucl_object_insert_key (obj, cur, "key6", 0, false);
cur = ucl_object_fromstring_common (" \n", 0, UCL_STRING_ESCAPE); cur = ucl_object_fromstring_common (" \n", 0, UCL_STRING_ESCAPE);
obj = ucl_object_insert_key (obj, cur, "key7", 0, false); ucl_object_insert_key (obj, cur, "key7", 0, false);
/* Numbers and booleans */ /* Numbers and booleans */
cur = ucl_object_fromstring_common ("1mb", 0, UCL_STRING_ESCAPE | UCL_STRING_PARSE); cur = ucl_object_fromstring_common ("1mb", 0, UCL_STRING_ESCAPE | UCL_STRING_PARSE);
obj = ucl_object_insert_key (obj, cur, "key8", 0, false); ucl_object_insert_key (obj, cur, "key8", 0, false);
cur = ucl_object_fromstring_common ("3.14", 0, UCL_STRING_PARSE); cur = ucl_object_fromstring_common ("3.14", 0, UCL_STRING_PARSE);
obj = ucl_object_insert_key (obj, cur, "key9", 0, false); ucl_object_insert_key (obj, cur, "key9", 0, false);
cur = ucl_object_fromstring_common ("true", 0, UCL_STRING_PARSE); cur = ucl_object_fromstring_common ("true", 0, UCL_STRING_PARSE);
obj = ucl_object_insert_key (obj, cur, "key10", 0, false); ucl_object_insert_key (obj, cur, "key10", 0, false);
cur = ucl_object_fromstring_common (" off ", 0, UCL_STRING_PARSE | UCL_STRING_TRIM); cur = ucl_object_fromstring_common (" off ", 0, UCL_STRING_PARSE | UCL_STRING_TRIM);
obj = ucl_object_insert_key (obj, cur, "key11", 0, false); ucl_object_insert_key (obj, cur, "key11", 0, false);
cur = ucl_object_fromstring_common ("gslin@gslin.org", 0, UCL_STRING_PARSE_INT); cur = ucl_object_fromstring_common ("gslin@gslin.org", 0, UCL_STRING_PARSE_INT);
obj = ucl_object_insert_key (obj, cur, "key12", 0, false); ucl_object_insert_key (obj, cur, "key12", 0, false);
cur = ucl_object_fromstring_common ("#test", 0, UCL_STRING_PARSE_INT); cur = ucl_object_fromstring_common ("#test", 0, UCL_STRING_PARSE_INT);
obj = ucl_object_insert_key (obj, cur, "key13", 0, false); ucl_object_insert_key (obj, cur, "key13", 0, false);
cur = ucl_object_frombool (true); cur = ucl_object_frombool (true);
obj = ucl_object_insert_key (obj, cur, "k=3", 0, false); ucl_object_insert_key (obj, cur, "k=3", 0, false);
emitted = ucl_object_emit (obj, UCL_EMIT_CONFIG); emitted = ucl_object_emit (obj, UCL_EMIT_CONFIG);
@ -122,5 +124,9 @@ main (int argc, char **argv)
} }
fclose (out); fclose (out);
/* Ref should still be accessible */
ref->value.iv = 100500;
ucl_object_unref (ref);
return ret; return ret;
} }

View File

@ -58,10 +58,10 @@ read_stdin (char **buf)
} }
static bool static bool
perform_test (ucl_object_t *schema, ucl_object_t *obj, perform_test (const ucl_object_t *schema, const ucl_object_t *obj,
struct ucl_schema_error *err) struct ucl_schema_error *err)
{ {
ucl_object_t *valid, *data, *description; const const ucl_object_t *valid, *data, *description;
bool match; bool match;
data = ucl_object_find_key (obj, "data"); data = ucl_object_find_key (obj, "data");
@ -86,11 +86,11 @@ perform_test (ucl_object_t *schema, ucl_object_t *obj,
} }
static int static int
perform_tests (ucl_object_t *obj) perform_tests (const ucl_object_t *obj)
{ {
struct ucl_schema_error err; struct ucl_schema_error err;
ucl_object_iter_t iter = NULL; ucl_object_iter_t iter = NULL;
ucl_object_t *schema, *tests, *description, *test; const ucl_object_t *schema, *tests, *description, *test;
if (obj->type != UCL_OBJECT) { if (obj->type != UCL_OBJECT) {
fprintf (stdout, "Bad test case\n"); fprintf (stdout, "Bad test case\n");
@ -124,7 +124,8 @@ main (int argc, char **argv)
{ {
char *buf = NULL; char *buf = NULL;
struct ucl_parser *parser; struct ucl_parser *parser;
ucl_object_t *obj = NULL, *elt; ucl_object_t *obj = NULL;
const ucl_object_t *elt;
ucl_object_iter_t iter = NULL; ucl_object_iter_t iter = NULL;
int ret = 0; int ret = 0;

View File

@ -28,11 +28,11 @@
#include "ucl.h" #include "ucl.h"
void void
ucl_obj_dump(ucl_object_t *obj, unsigned int shift) ucl_obj_dump (const ucl_object_t *obj, unsigned int shift)
{ {
int num = shift * 4 + 5; int num = shift * 4 + 5;
char *pre = (char *) malloc (num * sizeof(char)); char *pre = (char *) malloc (num * sizeof(char));
ucl_object_t *cur, *tmp; const ucl_object_t *cur, *tmp;
ucl_object_iter_t it = NULL, it_obj = NULL; ucl_object_iter_t it = NULL, it_obj = NULL;
pre[--num] = 0x00; pre[--num] = 0x00;
@ -64,7 +64,7 @@ ucl_obj_dump(ucl_object_t *obj, unsigned int shift)
} }
else if (obj->type == UCL_INT) { else if (obj->type == UCL_INT) {
printf ("%stype: UCL_INT\n", pre); printf ("%stype: UCL_INT\n", pre);
printf ("%svalue: %ld\n", pre, ucl_object_toint (obj)); printf ("%svalue: %jd\n", pre, (intmax_t)ucl_object_toint (obj));
} }
else if (obj->type == UCL_FLOAT) { else if (obj->type == UCL_FLOAT) {
printf ("%stype: UCL_FLOAT\n", pre); printf ("%stype: UCL_FLOAT\n", pre);
@ -99,7 +99,7 @@ main(int argc, char **argv)
struct ucl_parser *parser; struct ucl_parser *parser;
int k, ret = 0, r = 0; int k, ret = 0, r = 0;
ucl_object_t *obj = NULL; ucl_object_t *obj = NULL;
ucl_object_t *par; const ucl_object_t *par;
FILE *in; FILE *in;
if (argc > 1) { if (argc > 1) {
@ -129,7 +129,7 @@ main(int argc, char **argv)
} }
obj = ucl_parser_get_object (parser); obj = ucl_parser_get_object (parser);
if (ucl_parser_get_error(parser)) { if (ucl_parser_get_error (parser)) {
printf ("Error occured: %s\n", ucl_parser_get_error(parser)); printf ("Error occured: %s\n", ucl_parser_get_error(parser));
ret = 1; ret = 1;
goto end; goto end;

View File

@ -517,10 +517,10 @@ boolstr_to_bool(const char *str)
} }
static void static void
config_parse(ucl_object_t *obj, pkg_conf_file_t conftype) config_parse(const ucl_object_t *obj, pkg_conf_file_t conftype)
{ {
struct sbuf *buf = sbuf_new_auto(); struct sbuf *buf = sbuf_new_auto();
ucl_object_t *cur, *seq; const ucl_object_t *cur, *seq;
ucl_object_iter_t it = NULL, itseq = NULL; ucl_object_iter_t it = NULL, itseq = NULL;
struct config_entry *temp_config; struct config_entry *temp_config;
struct config_value *cv; struct config_value *cv;
@ -638,7 +638,7 @@ static void
parse_repo_file(ucl_object_t *obj) parse_repo_file(ucl_object_t *obj)
{ {
ucl_object_iter_t it = NULL; ucl_object_iter_t it = NULL;
ucl_object_t *cur; const ucl_object_t *cur;
const char *key; const char *key;
while ((cur = ucl_iterate_object(obj, &it, true))) { while ((cur = ucl_iterate_object(obj, &it, true))) {
@ -683,7 +683,7 @@ read_conf_file(const char *confpath, pkg_conf_file_t conftype)
parse_repo_file(obj); parse_repo_file(obj);
} }
ucl_object_free(obj); ucl_object_unref(obj);
ucl_parser_free(p); ucl_parser_free(p);
return (0); return (0);

View File

@ -270,7 +270,7 @@ fetch_to_fd(const char *url, char *path)
static struct fingerprint * static struct fingerprint *
parse_fingerprint(ucl_object_t *obj) parse_fingerprint(ucl_object_t *obj)
{ {
ucl_object_t *cur; const ucl_object_t *cur;
ucl_object_iter_t it = NULL; ucl_object_iter_t it = NULL;
const char *function, *fp, *key; const char *function, *fp, *key;
struct fingerprint *f; struct fingerprint *f;
@ -349,7 +349,7 @@ load_fingerprint(const char *dir, const char *filename)
if (f != NULL) if (f != NULL)
f->name = strdup(filename); f->name = strdup(filename);
ucl_object_free(obj); ucl_object_unref(obj);
ucl_parser_free(p); ucl_parser_free(p);
return (f); return (f);