aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBaptiste Daroussin <bapt@FreeBSD.org>2014-04-22 21:56:27 +0000
committerBaptiste Daroussin <bapt@FreeBSD.org>2014-04-22 21:56:27 +0000
commitd4fc17b1e5ff64ea70cfb02594ae87f599f81c29 (patch)
treec1169bd0239a10ab249485e498817c451e608aea
parentbfc6d68337150c52c8ce2dc6a7d19a9d1bd92795 (diff)
downloadsrc-d4fc17b1e5ff64ea70cfb02594ae87f599f81c29.tar.gz
src-d4fc17b1e5ff64ea70cfb02594ae87f599f81c29.zip
Import libucl 0.4.0vendor/libucl/0.4.0
Notes
Notes: svn path=/vendor/libucl/dist/; revision=264787 svn path=/vendor/libucl/0.4.0/; revision=264788; tag=vendor/libucl/0.4.0
-rw-r--r--README.md2
-rw-r--r--configure.ac61
-rw-r--r--doc/api.md12
-rw-r--r--doc/libucl.3155
-rw-r--r--include/ucl.h151
-rw-r--r--src/Makefile.am2
-rw-r--r--src/ucl_emitter.c59
-rw-r--r--src/ucl_hash.c15
-rw-r--r--src/ucl_hash.h12
-rw-r--r--src/ucl_internal.h18
-rw-r--r--src/ucl_parser.c34
-rw-r--r--src/ucl_schema.c102
-rw-r--r--src/ucl_util.c320
-rw-r--r--tests/test_basic.c4
-rw-r--r--tests/test_generate.c52
-rw-r--r--tests/test_schema.c11
-rw-r--r--utils/objdump.c10
17 files changed, 574 insertions, 446 deletions
diff --git a/README.md b/README.md
index 70f646efd753..b6353d10ae27 100644
--- a/README.md
+++ b/README.md
@@ -287,7 +287,7 @@ Each UCL object can be serialized to one of the three supported formats:
## 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
diff --git a/configure.ac b/configure.ac
index c936829c753b..1f6e87d41ef0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
m4_define([maj_ver], [0])
-m4_define([med_ver], [3])
+m4_define([med_ver], [4])
m4_define([min_ver], [0])
m4_define([so_version], [maj_ver:med_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])
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],
- [Enable signatures check (requires openssl)]))
+ [Enable signatures check (requires openssl) @<:@default=no@:>@]), [],
+ [enable_signatures=no])
AC_ARG_ENABLE([utils],
- [--enable-utils Build and install utils],
+ AS_HELP_STRING([--enable-utils], [Build and install utils @<:@default=no@:>@]),
[case "${enableval}" in
yes) utils=true ;;
no) utils=false ;;
@@ -63,11 +69,11 @@ AM_CONDITIONAL([UTILS], [test x$utils = xtrue])
AS_IF([test "x$enable_signatures" = "xyes"], [
AC_SEARCH_LIBS([EVP_MD_CTX_create], [crypto], [
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"
], [AC_MSG_ERROR([unable to find the EVP_MD_CTX_create() function])])
])
-
+AC_SUBST(LIBCRYPTO_LIB)
AC_PATH_PROG(PANDOC, pandoc, [/non/existent])
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_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])],
- [#include <sys/types.h>])
+AS_IF([test "x$enable_regex" = "xyes"], [
+ AC_CHECK_HEADER([regex.h], [
+ AC_DEFINE(HAVE_REGEX_H, 1, [Define to 1 if you have the <regex.h> header file.])
+ AC_SEARCH_LIBS([regexec], [regex], [
+ 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"], [
AC_CHECK_HEADER([fetch.h], [
@@ -114,6 +130,29 @@ AS_IF([test "x$enable_urls" = "xyes"], [
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 \
src/Makefile \
tests/Makefile \
diff --git a/doc/api.md b/doc/api.md
index 3b031d2305c9..41e660a428ea 100644
--- a/doc/api.md
+++ b/doc/api.md
@@ -282,7 +282,7 @@ Libucl provides the following functions for emitting UCL objects:
### ucl_object_emit
~~~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.
@@ -290,7 +290,7 @@ Allocate a string that is suitable to fit the underlying UCL object `obj` and fi
### ucl_object_emit_full
~~~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);
~~~
@@ -381,7 +381,7 @@ Iteration are used to iterate over UCL compound types: arrays and objects. Moreo
## ucl_iterate_object
~~~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);
~~~
@@ -389,7 +389,7 @@ This function accept opaque iterator pointer `iter`. In the first call this iter
~~~C
ucl_object_iter_t it = NULL, it_obj = NULL;
-ucl_object_t *cur, *tmp;
+const ucl_object_t *cur, *tmp;
/* Iterate over the object */
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
~~~C
-bool ucl_object_validate (ucl_object_t *schema,
- ucl_object_t *obj, struct ucl_schema_error *err);
+bool ucl_object_validate (const ucl_object_t *schema,
+ 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:
diff --git a/doc/libucl.3 b/doc/libucl.3
index 0d4fb607a510..a185d1a56675 100644
--- a/doc/libucl.3
+++ b/doc/libucl.3
@@ -6,11 +6,11 @@
\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_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
.SH LIBRARY
.PP
-UCL library (libucl, -lucl)
+UCL library (libucl, \-lucl)
.SH SYNOPSIS
.PP
\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.
Currently, libucl supports the following exports:
.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)
.IP \[bu] 2
-\f[C]Config\f[] - human-readable configuration format (losseless)
+\f[C]Config\f[] \- human\-readable configuration format (losseless)
.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)
.SS Conversion functions
.PP
@@ -57,7 +57,7 @@ as implicit array or implicit consolidation).
.SS Validation functions
.PP
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.
.SS Utility functions
.PP
@@ -76,13 +76,13 @@ struct\ ucl_parser*\ ucl_parser_new\ (int\ flags);
.PP
Creates new parser with the specified flags:
.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
-\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
-so it should exist till any object parsed is used)
+\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 so it should exist till any object parsed is used)
.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
.SS ucl_parser_register_macro
.IP
@@ -161,7 +161,7 @@ bool\ ucl_parser_add_string\ (struct\ ucl_parser\ *parser,\
.PP
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
-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.
.SS ucl_parser_add_file
.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
\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
-\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
working.
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
\f[C]filename\f[] specified:
.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
-\f[C]$CURDIR\f[] - a current directory of the input
+\f[C]$CURDIR\f[] \- a current directory of the input
.PP
-For example, if a \f[C]filename\f[] param is \f[C]../something.conf\f[]
-then the variables will have the following values:
+For example, if a \f[C]filename\f[] param is
+\f[C]\&../something.conf\f[] then the variables will have the following
+values:
.IP \[bu] 2
-\f[C]$FILENAME\f[] - "../something.conf"
+\f[C]$FILENAME\f[] \- "../something.conf"
.IP \[bu] 2
-\f[C]$CURDIR\f[] - ".."
+\f[C]$CURDIR\f[] \- ".."
.PP
if \f[C]need_expand\f[] parameter is \f[C]true\f[] then all relative
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
-have these values:
+In this example if \f[C]\&..\f[] is \f[C]/etc/dir\f[] then variables
+will have these values:
.IP \[bu] 2
-\f[C]$FILENAME\f[] - "/etc/something.conf"
+\f[C]$FILENAME\f[] \- "/etc/something.conf"
.IP \[bu] 2
-\f[C]$CURDIR\f[] - "/etc"
+\f[C]$CURDIR\f[] \- "/etc"
.SS Parser usage example
.PP
The following example loads, parses and extracts \f[C]ucl\f[] object
@@ -283,7 +284,7 @@ FILE\ *in;
in\ =\ stdin;
parser\ =\ ucl_parser_new\ (0);
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);
fclose\ (in);
@@ -309,20 +310,20 @@ return\ ret;
.PP
Libucl can transform UCL objects to a number of tectual formats:
.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
duplicate keys
.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
.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
.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
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:
.IP
.nf
@@ -344,17 +345,17 @@ struct\ ucl_emitter_functions\ {
.PP
This structure defines the following callbacks:
.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[]
.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[]
.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
.IP \[bu] 2
-\f[C]ucl_emitter_append_double\f[] - this function is intended to output
-floating point variable
+\f[C]ucl_emitter_append_double\f[] \- this function is intended to
+output floating point variable
.PP
The set of these functions could be used to output text formats of
\f[C]UCL\f[] objects to different structures or streams.
@@ -364,7 +365,7 @@ Libucl provides the following functions for emitting UCL objects:
.IP
.nf
\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[]
.fi
.PP
@@ -376,7 +377,7 @@ The caller should free the returned string after using.
.IP
.nf
\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);
\f[]
.fi
@@ -400,26 +401,26 @@ cannot be converted then some reasonable default is returned (NULL for
strings and 0 for numbers)
.PP
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.
For compound and numeric types this function performs emitting to a
compact json format actually.
.PP
Here is a list of all conversion functions:
.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
-\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
-\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
-\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)
.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)
.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
.PP
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[]
.fi
.PP
-Create an object of a specified type: - \f[C]UCL_OBJECT\f[] - UCL object
-- key/value pairs - \f[C]UCL_ARRAY\f[] - UCL array - \f[C]UCL_INT\f[] -
-integer number - \f[C]UCL_FLOAT\f[] - floating point number -
-\f[C]UCL_STRING\f[] - NULL terminated string - \f[C]UCL_BOOLEAN\f[] -
-boolean value - \f[C]UCL_TIME\f[] - time value (floating point number of
-seconds) - \f[C]UCL_USERDATA\f[] - opaque userdata pointer (may be used
-in macros) - \f[C]UCL_NULL\f[] - null value
+Create an object of a specified type: \- \f[C]UCL_OBJECT\f[] \- UCL
+object \- key/value pairs \- \f[C]UCL_ARRAY\f[] \- UCL array \-
+\f[C]UCL_INT\f[] \- integer number \- \f[C]UCL_FLOAT\f[] \- floating
+point number \- \f[C]UCL_STRING\f[] \- NULL terminated string \-
+\f[C]UCL_BOOLEAN\f[] \- boolean value \- \f[C]UCL_TIME\f[] \- time value
+(floating point number of seconds) \- \f[C]UCL_USERDATA\f[] \- opaque
+userdata pointer (may be used in macros) \- \f[C]UCL_NULL\f[] \- null
+value
.PP
This object should be released by caller.
.SS Primitive objects generation
.PP
Libucl provides the functions similar to inverse conversion functions
-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]double\f[] to UCL object -
-\f[C]ucl_object_fromboolean\f[] - converts \f[C]bool\f[] to UCL object -
-\f[C]ucl_object_fromstring\f[] - converts \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]size_t\f[] len to UCL object (string can be not NULL terminated)
+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]double\f[] to UCL object
+\- \f[C]ucl_object_fromboolean\f[] \- converts \f[C]bool\f[] to UCL
+object \- \f[C]ucl_object_fromstring\f[] \- converts
+\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]size_t\f[] len to UCL object (string can be not NULL
+terminated)
.PP
Also there is a function to generate UCL object from a string performing
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
\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
-NULL-terminated.
+NULL\-terminated.
This function supports the following flags (a set of flags can be
specified using logical \f[C]OR\f[] operation):
.IP \[bu] 2
-\f[C]UCL_STRING_ESCAPE\f[] - perform JSON escape
+\f[C]UCL_STRING_ESCAPE\f[] \- perform JSON escape
.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
-\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
.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
.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
.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
.IP \[bu] 2
-\f[C]UCL_STRING_PARSE_NUMBER\f[] - parse passed string and detect number
-(both float, integer and time types)
+\f[C]UCL_STRING_PARSE_NUMBER\f[] \- parse passed string and detect
+number (both float, integer and time types)
.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)
.IP \[bu] 2
-\f[C]UCL_STRING_PARSE_BYTES\f[] - assume that numeric multipliers are in
-bytes notation, for example \f[C]10k\f[] means \f[C]10*1024\f[] and not
-\f[C]10*1000\f[] as assumed without this flag
+\f[C]UCL_STRING_PARSE_BYTES\f[] \- assume that numeric multipliers are
+in bytes notation, for example \f[C]10k\f[] means \f[C]10*1024\f[] and
+not \f[C]10*1000\f[] as assumed without this flag
.PP
If parsing operations fail then the resulting UCL object will be a
\f[C]UCL_STRING\f[].
@@ -530,7 +533,7 @@ is a function \f[C]ucl_iterate_object\f[].
.IP
.nf
\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);
\f[]
.fi
@@ -561,7 +564,7 @@ Here is an example of iteration over the objects using libucl API
.nf
\f[C]
ucl_object_iter_t\ it\ =\ NULL,\ it_obj\ =\ NULL;
-ucl_object_t\ *cur,\ *tmp;
+const\ ucl_object_t\ *cur,\ *tmp;
/*\ Iterate\ over\ the\ object\ */
while\ ((obj\ =\ ucl_iterate_object\ (top,\ &it,\ true)))\ {
@@ -584,13 +587,13 @@ This function is defined as following:
.IP
.nf
\f[C]
-bool\ ucl_object_validate\ (ucl_object_t\ *schema,
-\ \ \ \ ucl_object_t\ *obj,\ struct\ ucl_schema_error\ *err);
+bool\ ucl_object_validate\ (const\ ucl_object_t\ *schema,
+\ \ \ \ const\ ucl_object_t\ *obj,\ struct\ ucl_schema_error\ *err);
\f[]
.fi
.PP
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[].
If this function returns \f[C]true\f[] then validation procedure has
been succeed.
diff --git a/include/ucl.h b/include/ucl.h
index 6cd7faf4c991..08039b29001e 100644
--- a/include/ucl.h
+++ b/include/ucl.h
@@ -81,6 +81,14 @@ extern "C" {
#define UCL_WARN_UNUSED_RESULT
#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
* 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
* @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
* @param obj CL object
* @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
@@ -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
* @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
@@ -253,28 +261,29 @@ UCL_EXTERN ucl_object_t *ucl_object_fromstring (const char *str);
* @param len length of a string
* @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
* @param iv number
* @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
* @param dv number
* @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
* @param bv bool value
* @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'
@@ -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 keylen length of the key (or 0 for NULL terminated keys)
* @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,
- const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT;
+UCL_EXTERN bool ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt,
+ 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,
@@ -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 keylen length of the key (or 0 for NULL terminated keys)
* @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,
- const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT;
+UCL_EXTERN bool ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt,
+ const char *key, size_t keylen, bool copy_key);
/**
* 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 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,
* @param top object
* @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 keylen length of the key (or 0 for NULL terminated keys)
* @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,
- const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT;
+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);
/**
* Append an element to the front of array object
* @param top destination object (will be created automatically if top is 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_object_t *elt) UCL_WARN_UNUSED_RESULT;
+UCL_EXTERN bool ucl_array_append (ucl_object_t *top,
+ ucl_object_t *elt);
/**
* Append an element to the start of array object
* @param top destination object (will be created automatically if top is 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_object_t *elt) UCL_WARN_UNUSED_RESULT;
+UCL_EXTERN bool ucl_array_prepend (ucl_object_t *top,
+ ucl_object_t *elt);
/**
* 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
* @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`
* @param top array ucl object
* @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`
* @param top array ucl object
* @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
@@ -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
* @param head head to append (may be NULL)
* @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_object_t *elt) UCL_WARN_UNUSED_RESULT;
+UCL_EXTERN ucl_object_t * ucl_elt_append (ucl_object_t *head,
+ ucl_object_t *elt);
/**
* 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
* @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
* @param obj CL object
* @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
@@ -438,14 +450,14 @@ UCL_EXTERN double ucl_object_todouble (ucl_object_t *obj);
* @param target target integer variable
* @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
* @param obj CL object
* @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
@@ -453,14 +465,14 @@ UCL_EXTERN int64_t ucl_object_toint (ucl_object_t *obj);
* @param target target boolean variable
* @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
* @param obj CL object
* @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
@@ -468,21 +480,21 @@ UCL_EXTERN bool ucl_object_toboolean (ucl_object_t *obj);
* @param target target string variable, no need to free value
* @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
* @param obj CL object
* @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
* @param obj CL object
* @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
@@ -492,7 +504,7 @@ UCL_EXTERN const char* ucl_object_tostring_forced (ucl_object_t *obj);
* @param tlen target length
* @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);
/**
@@ -500,7 +512,7 @@ UCL_EXTERN bool ucl_object_tolstring_safe (ucl_object_t *obj,
* @param obj CL object
* @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
@@ -508,7 +520,8 @@ UCL_EXTERN const char* ucl_object_tolstring (ucl_object_t *obj, size_t *tlen);
* @param key key to search
* @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
@@ -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
* @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
* @param obj CL object
* @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)
@@ -532,19 +546,19 @@ UCL_EXTERN const char* ucl_object_key (ucl_object_t *obj);
* @param len target key length
* @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
+ * Increase reference count for an object
+ * @param obj object to ref
*/
-UCL_EXTERN void ucl_object_free (ucl_object_t *obj);
+UCL_EXTERN ucl_object_t* ucl_object_ref (const ucl_object_t *obj);
/**
- * Increase reference count for an object
- * @param obj object to ref
+ * Free ucl object
+ * @param obj ucl object to free
*/
-UCL_EXTERN ucl_object_t* ucl_object_ref (ucl_object_t *obj);
+UCL_DEPRECATED(UCL_EXTERN void ucl_object_free (ucl_object_t *obj));
/**
* Decrease reference count for an object
@@ -562,7 +576,8 @@ UCL_EXTERN void ucl_object_unref (ucl_object_t *obj);
* 2) Size 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
@@ -570,7 +585,7 @@ UCL_EXTERN int ucl_object_compare (ucl_object_t *o1, ucl_object_t *o2);
* @param cmp
*/
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
@@ -585,7 +600,8 @@ typedef void* ucl_object_iter_t;
* while ((cur = ucl_iterate_object (obj, &it)) != 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
* @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);
+
+/**
+ * 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
+ * Get a top object for a parser (refcount is increased)
* @param parser parser structure
* @param err if *err is NULL it is set to parser error
* @return top parser object or NULL
@@ -736,7 +763,8 @@ struct ucl_emitter_functions {
* #UCL_EMIT_CONFIG then emit config like object
* @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
@@ -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
* @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);
/** @} */
@@ -775,7 +804,7 @@ enum ucl_schema_error_code {
struct ucl_schema_error {
enum ucl_schema_error_code code; /**< error code */
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.
* @return true if `obj` is valid using `schema`
*/
-UCL_EXTERN bool ucl_object_validate (ucl_object_t *schema,
- ucl_object_t *obj, struct ucl_schema_error *err);
+UCL_EXTERN bool ucl_object_validate (const ucl_object_t *schema,
+ const ucl_object_t *obj, struct ucl_schema_error *err);
/** @} */
diff --git a/src/Makefile.am b/src/Makefile.am
index 499d640508a2..76391cd044f0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,6 +13,8 @@ libucl_la_CFLAGS= $(libucl_common_cflags) \
@CURL_CFLAGS@
libucl_la_LDFLAGS = -version-info @SO_VERSION@
libucl_la_LIBADD= @LIBFETCH_LIBS@ \
+ @LIBCRYPTO_LIB@ \
+ @LIBREGEX_LIB@ \
@CURL_LIBS@
include_HEADERS= $(top_srcdir)/include/ucl.h
diff --git a/src/ucl_emitter.c b/src/ucl_emitter.c
index eb314ac21cd7..04c3d4b13232 100644
--- a/src/ucl_emitter.c
+++ b/src/ucl_emitter.c
@@ -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,
unsigned int tabs,
bool start_tabs,
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,
unsigned int tabs,
bool start_tabs,
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,
unsigned int tabs,
bool start_tabs,
bool is_top,
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,
unsigned int tabs,
bool start_tabs,
bool compact,
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,
unsigned int tabs,
bool start_tabs,
@@ -144,10 +144,10 @@ ucl_elt_string_write_json (const char *str, size_t size,
* @param buf target buffer
*/
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)
{
- ucl_object_t *cur;
+ const ucl_object_t *cur;
ucl_hash_iter_t it = NULL;
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
*/
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)
{
- ucl_object_t *cur = obj;
+ const ucl_object_t *cur = obj;
if (start_tabs) {
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
*/
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)
{
bool flag;
@@ -295,10 +295,10 @@ ucl_elt_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func,
* @param buf target buffer
*/
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)
{
- ucl_object_t *cur;
+ const ucl_object_t *cur;
bool is_array = (obj->next != NULL);
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)
*/
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);
}
@@ -350,10 +351,10 @@ ucl_object_emit_json (ucl_object_t *obj, bool compact, struct ucl_emitter_functi
* @param buf target buffer
*/
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)
{
- ucl_object_t *cur, *cur_obj;
+ const ucl_object_t *cur, *cur_obj;
ucl_hash_iter_t it = NULL;
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
*/
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)
{
- ucl_object_t *cur = obj;
+ const ucl_object_t *cur = obj;
if (start_tabs) {
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
*/
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)
{
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)
*/
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);
}
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)
{
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
*/
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)
{
- ucl_object_t *cur;
+ const ucl_object_t *cur;
ucl_hash_iter_t it = NULL;
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
*/
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)
{
- ucl_object_t *cur = obj;
+ const ucl_object_t *cur = obj;
if (start_tabs) {
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
*/
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)
{
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)
*/
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);
}
@@ -723,7 +724,7 @@ ucl_utstring_append_double (double val, void *ud)
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;
unsigned char *res = NULL;
@@ -763,7 +764,7 @@ ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type)
}
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)
{
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 *
-ucl_object_emit_single_json (ucl_object_t *obj)
+ucl_object_emit_single_json (const ucl_object_t *obj)
{
UT_string *buf = NULL;
unsigned char *res = NULL;
diff --git a/src/ucl_hash.c b/src/ucl_hash.c
index 0ab962a42009..c2e80cb4b252 100644
--- a/src/ucl_hash.c
+++ b/src/ucl_hash.c
@@ -40,11 +40,15 @@ ucl_hash_create (void)
void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func *func)
{
ucl_hash_node_t *elt, *tmp;
+ const ucl_object_t *cur, *otmp;
HASH_ITER (hh, hashlin->buckets, elt, tmp) {
HASH_DELETE (hh, hashlin->buckets, elt);
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);
}
@@ -52,7 +56,8 @@ void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func *func)
}
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;
@@ -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);
}
-void*
+const void*
ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *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_node_t *found;
@@ -109,7 +114,7 @@ ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen)
}
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;
diff --git a/src/ucl_hash.h b/src/ucl_hash.h
index 5c9b851b9f29..cbbf005240bd 100644
--- a/src/ucl_hash.h
+++ b/src/ucl_hash.h
@@ -31,7 +31,7 @@
typedef struct ucl_hash_node_s
{
- ucl_object_t *data;
+ const ucl_object_t *data;
UT_hash_handle hh;
} 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.
*/
-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.
*/
-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.
*/
-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)
* @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
diff --git a/src/ucl_internal.h b/src/ucl_internal.h
index a55d747dbfcc..9a35dcec40be 100644
--- a/src/ucl_internal.h
+++ b/src/ucl_internal.h
@@ -45,7 +45,9 @@
#define HAVE_STDBOOL_H
#define HAVE_STDINT_H
#define HAVE_STDARG_H
-#define HAVE_REGEX_H
+#ifndef _WIN32
+# define HAVE_REGEX_H
+#endif
#endif
#ifdef HAVE_SYS_TYPES_H
@@ -97,6 +99,10 @@
#include <openssl/evp.h>
#endif
+#ifndef __DECONST
+#define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
+#endif
+
/**
* @file rcl_internal.h
* 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);
-static inline ucl_object_t *
+static inline const ucl_object_t *
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 *
-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 *
-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) {
hashlin = ucl_hash_create ();
@@ -339,6 +345,6 @@ ucl_hash_insert_object (ucl_hash_t *hashlin, ucl_object_t *obj)
* @param obj
* @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_ */
diff --git a/src/ucl_parser.c b/src/ucl_parser.c
index a067286df40c..d5a085ebf829 100644
--- a/src/ucl_parser.c
+++ b/src/ucl_parser.c
@@ -55,34 +55,6 @@ struct ucl_parser_saved_state {
(chunk)->remain --; \
} 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
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],
&key, end - c, need_unescape, parser->flags & UCL_PARSER_KEY_LOWERCASE, false);
if (keylen == -1) {
- ucl_object_free(nobj);
+ ucl_object_unref (nobj);
return false;
}
else if (keylen == 0) {
ucl_set_err (chunk, UCL_ESYNTAX, "empty keys are not allowed", &parser->err);
- ucl_object_free(nobj);
+ ucl_object_unref (nobj);
return false;
}
container = parser->stack->obj->value.ov;
nobj->key = key;
nobj->keylen = keylen;
- tobj = ucl_hash_search_obj (container, nobj);
+ tobj = __DECONST (ucl_object_t *, ucl_hash_search_obj (container, nobj));
if (tobj == NULL) {
container = ucl_hash_insert_object (container, nobj);
nobj->prev = nobj;
diff --git a/src/ucl_schema.c b/src/ucl_schema.c
index a74ed0f527a1..faffe8613ce7 100644
--- a/src/ucl_schema.c
+++ b/src/ucl_schema.c
@@ -40,10 +40,10 @@
#include <math.h>
#endif
-static bool ucl_schema_validate (ucl_object_t *schema,
- ucl_object_t *obj, bool try_array,
+static bool ucl_schema_validate (const ucl_object_t *schema,
+ const ucl_object_t *obj, bool try_array,
struct ucl_schema_error *err,
- ucl_object_t *root);
+ const ucl_object_t *root);
static bool
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
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, ...)
{
va_list va;
@@ -132,11 +132,13 @@ ucl_schema_create_error (struct ucl_schema_error *err,
/*
* Check whether we have a pattern specified
*/
-static ucl_object_t *
-ucl_schema_test_pattern (ucl_object_t *obj, const char *pattern)
+static const ucl_object_t *
+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;
- ucl_object_t *res = NULL, *elt;
+ const ucl_object_t *elt;
ucl_object_iter_t iter = NULL;
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);
}
-
+#endif
return res;
}
@@ -156,11 +158,11 @@ ucl_schema_test_pattern (ucl_object_t *obj, const char *pattern)
* Check dependencies for an object
*/
static bool
-ucl_schema_validate_dependencies (ucl_object_t *deps,
- ucl_object_t *obj, struct ucl_schema_error *err,
- ucl_object_t *root)
+ucl_schema_validate_dependencies (const ucl_object_t *deps,
+ const ucl_object_t *obj, struct ucl_schema_error *err,
+ 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;
bool ret = true;
@@ -193,11 +195,11 @@ ucl_schema_validate_dependencies (ucl_object_t *deps,
* Validate object
*/
static bool
-ucl_schema_validate_object (ucl_object_t *schema,
- ucl_object_t *obj, struct ucl_schema_error *err,
- ucl_object_t *root)
+ucl_schema_validate_object (const ucl_object_t *schema,
+ const ucl_object_t *obj, struct ucl_schema_error *err,
+ 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;
ucl_object_iter_t iter = NULL, piter = NULL;
bool ret = true, allow_additional = true;
@@ -334,10 +336,10 @@ ucl_schema_validate_object (ucl_object_t *schema,
}
static bool
-ucl_schema_validate_number (ucl_object_t *schema,
- ucl_object_t *obj, struct ucl_schema_error *err)
+ucl_schema_validate_number (const ucl_object_t *schema,
+ 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;
bool ret = true, exclusive = false;
double constraint, val;
@@ -400,14 +402,16 @@ ucl_schema_validate_number (ucl_object_t *schema,
}
static bool
-ucl_schema_validate_string (ucl_object_t *schema,
- ucl_object_t *obj, struct ucl_schema_error *err)
+ucl_schema_validate_string (const ucl_object_t *schema,
+ 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;
bool ret = true;
int64_t constraint;
+#ifdef HAVE_REGEX_H
regex_t re;
+#endif
while (ret && (elt = ucl_iterate_object (schema, &iter, true)) != NULL) {
if (elt->type == UCL_INT &&
@@ -432,6 +436,7 @@ ucl_schema_validate_string (ucl_object_t *schema,
break;
}
}
+#ifdef HAVE_REGEX_H
else if (elt->type == UCL_STRING &&
strcmp (ucl_object_key (elt), "pattern") == 0) {
if (regcomp (&re, ucl_object_tostring (elt),
@@ -449,13 +454,14 @@ ucl_schema_validate_string (ucl_object_t *schema,
}
regfree (&re);
}
+#endif
}
return ret;
}
struct ucl_compare_node {
- ucl_object_t *obj;
+ const ucl_object_t *obj;
TREE_ENTRY(ucl_compare_node) link;
struct ucl_compare_node *next;
};
@@ -467,17 +473,17 @@ TREE_DEFINE(ucl_compare_node, link)
static int
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);
}
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_object_iter_t iter = NULL;
- ucl_object_t *elt;
+ const ucl_object_t *elt;
struct ucl_compare_node *node, test, *nodes = NULL, *tmp;
bool ret = true;
@@ -510,11 +516,11 @@ ucl_schema_array_is_unique (ucl_object_t *obj, struct ucl_schema_error *err)
}
static bool
-ucl_schema_validate_array (ucl_object_t *schema,
- ucl_object_t *obj, struct ucl_schema_error *err,
- ucl_object_t *root)
+ucl_schema_validate_array (const ucl_object_t *schema,
+ const ucl_object_t *obj, struct ucl_schema_error *err,
+ 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;
ucl_object_iter_t iter = NULL, piter = NULL;
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
*/
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)
{
ucl_object_iter_t iter = NULL;
- ucl_object_t *elt;
+ const ucl_object_t *elt;
const char *type_str;
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
*/
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)
{
ucl_object_iter_t iter = NULL;
- ucl_object_t *elt;
+ const ucl_object_t *elt;
bool ret = false;
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
*/
-static ucl_object_t *
-ucl_schema_resolve_ref_component (ucl_object_t *cur,
+static const ucl_object_t *
+ucl_schema_resolve_ref_component (const ucl_object_t *cur,
const char *refc, int len,
struct ucl_schema_error *err)
{
- ucl_object_t *res = NULL;
+ const ucl_object_t *res = NULL;
char *err_str;
int num, i;
@@ -762,12 +768,12 @@ ucl_schema_resolve_ref_component (ucl_object_t *cur,
/*
* Find reference schema
*/
-static ucl_object_t *
-ucl_schema_resolve_ref (ucl_object_t *root, const char *ref,
+static const ucl_object_t *
+ucl_schema_resolve_ref (const ucl_object_t *root, const char *ref,
struct ucl_schema_error *err)
{
const char *p, *c;
- ucl_object_t *res = NULL;
+ const ucl_object_t *res = NULL;
if (ref[0] != '#') {
@@ -822,10 +828,10 @@ ucl_schema_resolve_ref (ucl_object_t *root, const char *ref,
}
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)
{
- ucl_object_t *elt, *cur;
+ const ucl_object_t *elt, *cur;
int64_t constraint, i;
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
-ucl_schema_validate (ucl_object_t *schema,
- ucl_object_t *obj, bool try_array,
+ucl_schema_validate (const ucl_object_t *schema,
+ const ucl_object_t *obj, bool try_array,
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;
bool ret;
@@ -1001,8 +1007,8 @@ ucl_schema_validate (ucl_object_t *schema,
}
bool
-ucl_object_validate (ucl_object_t *schema,
- ucl_object_t *obj, struct ucl_schema_error *err)
+ucl_object_validate (const ucl_object_t *schema,
+ const ucl_object_t *obj, struct ucl_schema_error *err)
{
return ucl_schema_validate (schema, obj, true, err, schema);
}
diff --git a/src/ucl_util.c b/src/ucl_util.c
index f96c23cd6129..9178795d9446 100644
--- a/src/ucl_util.c
+++ b/src/ucl_util.c
@@ -134,35 +134,76 @@ static char* ucl_realpath(const char *path, char *resolved_path) {
* 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
-ucl_object_free_internal (ucl_object_t *obj, bool allow_rec)
+ucl_object_dtor_free (ucl_object_t *obj)
{
- ucl_object_t *sub, *tmp;
+ 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);
+}
- 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]);
+/*
+ * 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;
+ while (obj != NULL) {
if (obj->type == UCL_ARRAY) {
sub = obj->value.av;
while (sub != NULL) {
tmp = sub->next;
- ucl_object_free_internal (sub, false);
+ dtor (sub);
sub = tmp;
}
}
else if (obj->type == UCL_OBJECT) {
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;
- UCL_FREE (sizeof (ucl_object_t), obj);
+ dtor (obj);
obj = tmp;
if (!allow_rec) {
@@ -174,7 +215,7 @@ ucl_object_free_internal (ucl_object_t *obj, bool allow_rec)
void
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
@@ -282,47 +323,54 @@ ucl_unescape_json_string (char *str, size_t len)
return (t - str);
}
-UCL_EXTERN char *
-ucl_copy_key_trash (ucl_object_t *obj)
+char *
+ucl_copy_key_trash (const ucl_object_t *obj)
{
+ ucl_object_t *deconst;
+
if (obj == NULL) {
return NULL;
}
if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->key != NULL) {
- obj->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1);
- if (obj->trash_stack[UCL_TRASH_KEY] != NULL) {
- memcpy (obj->trash_stack[UCL_TRASH_KEY], obj->key, obj->keylen);
- obj->trash_stack[UCL_TRASH_KEY][obj->keylen] = '\0';
+ deconst = __DECONST (ucl_object_t *, obj);
+ deconst->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1);
+ if (deconst->trash_stack[UCL_TRASH_KEY] != NULL) {
+ 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];
- obj->flags |= UCL_OBJECT_ALLOCATED_KEY;
+ deconst->key = obj->trash_stack[UCL_TRASH_KEY];
+ deconst->flags |= UCL_OBJECT_ALLOCATED_KEY;
}
return obj->trash_stack[UCL_TRASH_KEY];
}
-UCL_EXTERN char *
-ucl_copy_value_trash (ucl_object_t *obj)
+char *
+ucl_copy_value_trash (const ucl_object_t *obj)
{
+ ucl_object_t *deconst;
+
if (obj == NULL) {
return NULL;
}
if (obj->trash_stack[UCL_TRASH_VALUE] == NULL) {
+ deconst = __DECONST (ucl_object_t *, obj);
if (obj->type == UCL_STRING) {
+
/* Special case for strings */
- obj->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1);
- if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
- memcpy (obj->trash_stack[UCL_TRASH_VALUE], obj->value.sv, obj->len);
- obj->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0';
- obj->value.sv = obj->trash_stack[UCL_TRASH_VALUE];
+ deconst->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1);
+ if (deconst->trash_stack[UCL_TRASH_VALUE] != NULL) {
+ memcpy (deconst->trash_stack[UCL_TRASH_VALUE], obj->value.sv, obj->len);
+ deconst->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0';
+ deconst->value.sv = obj->trash_stack[UCL_TRASH_VALUE];
}
}
else {
/* Just emit value in json notation */
- obj->trash_stack[UCL_TRASH_VALUE] = ucl_object_emit_single_json (obj);
- obj->len = strlen (obj->trash_stack[UCL_TRASH_VALUE]);
+ deconst->trash_stack[UCL_TRASH_VALUE] = ucl_object_emit_single_json (obj);
+ 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];
}
@@ -1084,21 +1132,22 @@ ucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags
return obj;
}
-static ucl_object_t *
+static bool
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)
{
- ucl_object_t *found, *cur;
+ ucl_object_t *found, *tmp;
+ const ucl_object_t *cur;
ucl_object_iter_t it = NULL;
const char *p;
+ int ret = true;
if (elt == NULL || key == NULL) {
- return NULL;
+ return false;
}
if (top == NULL) {
- top = ucl_object_new ();
- top->type = UCL_OBJECT;
+ return false;
}
if (top->type != UCL_OBJECT) {
@@ -1108,7 +1157,7 @@ ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt,
}
else {
/* 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);
}
- found = ucl_hash_search_obj (top->value.ov, elt);
+ found = __DECONST (ucl_object_t *, ucl_hash_search_obj (top->value.ov, elt));
if (!found) {
top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
DL_APPEND (found, elt);
top->len ++;
+ if (replace) {
+ ret = false;
+ }
}
else {
if (replace) {
@@ -1152,19 +1204,22 @@ ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt,
else if (merge) {
if (found->type != UCL_OBJECT && elt->type == UCL_OBJECT) {
/* 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);
top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
}
else if (found->type == UCL_OBJECT && elt->type != UCL_OBJECT) {
/* 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) {
/* Mix two hashes */
while ((cur = ucl_iterate_object (elt, &it, true)) != NULL) {
- ucl_object_ref (cur);
- found = ucl_object_insert_key_common (found, cur, cur->key, cur->keylen, copy_key, false, false);
+ tmp = ucl_object_ref (cur);
+ ucl_object_insert_key_common (found, tmp, cur->key,
+ cur->keylen, copy_key, false, false);
}
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
-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;
@@ -1190,13 +1245,13 @@ ucl_object_delete_keyl(ucl_object_t *top, const char *key, size_t keylen)
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) {
return false;
}
- ucl_hash_delete(top->value.ov, found);
+ ucl_hash_delete (top->value.ov, found);
ucl_object_unref (found);
top->len --;
@@ -1204,61 +1259,62 @@ ucl_object_delete_keyl(ucl_object_t *top, const char *key, size_t keylen)
}
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_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) {
return false;
}
- found = ucl_object_find_keyl(top, key, keylen);
+ found = ucl_object_find_keyl (top, key, keylen);
if (found == NULL) {
return NULL;
}
- ucl_hash_delete(top->value.ov, found);
+ ucl_hash_delete (top->value.ov, found);
top->len --;
- return found;
+ return __DECONST (ucl_object_t *, found);
}
ucl_object_t*
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,
const char *key, size_t keylen, bool copy_key)
{
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,
const char *key, size_t keylen, bool copy_key)
{
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,
const char *key, size_t keylen, bool copy_key)
{
return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, true);
}
-ucl_object_t *
-ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen)
+const ucl_object_t *
+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) {
return NULL;
@@ -1271,11 +1327,12 @@ ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen)
return ret;
}
-ucl_object_t *
-ucl_object_find_key (ucl_object_t *obj, const char *key)
+const ucl_object_t *
+ucl_object_find_key (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) {
return NULL;
@@ -1289,10 +1346,10 @@ ucl_object_find_key (ucl_object_t *obj, const char *key)
return ret;
}
-ucl_object_t*
-ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values)
+const ucl_object_t*
+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) {
return NULL;
@@ -1301,7 +1358,7 @@ ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_valu
if (expand_values) {
switch (obj->type) {
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;
case UCL_ARRAY:
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) {
return NULL;
}
- *iter = elt->next ? elt->next : obj;
+ *iter = __DECONST (void *, elt->next ? elt->next : obj);
return elt;
/* Not reached */
@@ -1420,72 +1477,55 @@ ucl_object_frombool (bool bv)
return obj;
}
-ucl_object_t *
+bool
ucl_array_append (ucl_object_t *top, ucl_object_t *elt)
{
ucl_object_t *head;
- if (elt == NULL) {
- return NULL;
+ if (elt == NULL || top == NULL) {
+ return false;
}
- if (top == NULL) {
- top = ucl_object_typed_new (UCL_ARRAY);
+ head = top->value.av;
+ if (head == NULL) {
top->value.av = elt;
- elt->next = NULL;
elt->prev = elt;
- top->len = 1;
}
else {
- head = top->value.av;
- if (head == NULL) {
- top->value.av = elt;
- elt->prev = elt;
- }
- else {
- elt->prev = head->prev;
- head->prev->next = elt;
- head->prev = elt;
- }
- elt->next = NULL;
- top->len ++;
+ elt->prev = head->prev;
+ head->prev->next = elt;
+ head->prev = elt;
}
+ 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_object_t *head;
- if (elt == NULL) {
- return NULL;
+ if (elt == NULL || top == NULL) {
+ return false;
}
- if (top == NULL) {
- top = ucl_object_typed_new (UCL_ARRAY);
+
+ head = top->value.av;
+ if (head == NULL) {
top->value.av = elt;
- elt->next = NULL;
elt->prev = elt;
- top->len = 1;
}
else {
- head = top->value.av;
- if (head == NULL) {
- 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->prev = head->prev;
+ head->prev = elt;
}
+ elt->next = head;
+ top->value.av = elt;
+ top->len ++;
- return top;
+ return true;
}
ucl_object_t *
@@ -1521,8 +1561,8 @@ ucl_array_delete (ucl_object_t *top, ucl_object_t *elt)
return elt;
}
-ucl_object_t *
-ucl_array_head (ucl_object_t *top)
+const ucl_object_t *
+ucl_array_head (const ucl_object_t *top)
{
if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
return NULL;
@@ -1530,8 +1570,8 @@ ucl_array_head (ucl_object_t *top)
return top->value.av;
}
-ucl_object_t *
-ucl_array_tail (ucl_object_t *top)
+const ucl_object_t *
+ucl_array_tail (const ucl_object_t *top)
{
if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
return NULL;
@@ -1542,13 +1582,13 @@ ucl_array_tail (ucl_object_t *top)
ucl_object_t *
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_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 *
@@ -1571,7 +1611,7 @@ ucl_elt_append (ucl_object_t *head, ucl_object_t *elt)
}
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) {
return false;
@@ -1592,7 +1632,7 @@ ucl_object_todouble_safe (ucl_object_t *obj, double *target)
}
double
-ucl_object_todouble (ucl_object_t *obj)
+ucl_object_todouble (const ucl_object_t *obj)
{
double result = 0.;
@@ -1601,7 +1641,7 @@ ucl_object_todouble (ucl_object_t *obj)
}
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) {
return false;
@@ -1622,7 +1662,7 @@ ucl_object_toint_safe (ucl_object_t *obj, int64_t *target)
}
int64_t
-ucl_object_toint (ucl_object_t *obj)
+ucl_object_toint (const ucl_object_t *obj)
{
int64_t result = 0;
@@ -1631,7 +1671,7 @@ ucl_object_toint (ucl_object_t *obj)
}
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) {
return false;
@@ -1648,7 +1688,7 @@ ucl_object_toboolean_safe (ucl_object_t *obj, bool *target)
}
bool
-ucl_object_toboolean (ucl_object_t *obj)
+ucl_object_toboolean (const ucl_object_t *obj)
{
bool result = false;
@@ -1657,7 +1697,7 @@ ucl_object_toboolean (ucl_object_t *obj)
}
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) {
return false;
@@ -1675,7 +1715,7 @@ ucl_object_tostring_safe (ucl_object_t *obj, const char **target)
}
const char *
-ucl_object_tostring (ucl_object_t *obj)
+ucl_object_tostring (const ucl_object_t *obj)
{
const char *result = NULL;
@@ -1684,13 +1724,13 @@ ucl_object_tostring (ucl_object_t *obj)
}
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);
}
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) {
return false;
@@ -1710,7 +1750,7 @@ ucl_object_tolstring_safe (ucl_object_t *obj, const char **target, size_t *tlen)
}
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;
@@ -1719,13 +1759,13 @@ ucl_object_tolstring (ucl_object_t *obj, size_t *tlen)
}
const char *
-ucl_object_key (ucl_object_t *obj)
+ucl_object_key (const ucl_object_t *obj)
{
return ucl_copy_key_trash (obj);
}
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) {
return NULL;
@@ -1735,26 +1775,40 @@ ucl_object_keyl (ucl_object_t *obj, size_t *len)
}
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) {
- 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
ucl_object_unref (ucl_object_t *obj)
{
- if (obj != NULL && --obj->ref <= 0) {
- ucl_object_free (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, true, ucl_object_dtor_unref);
+ }
}
}
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;
int ret = 0;
@@ -1825,7 +1879,7 @@ ucl_object_compare (ucl_object_t *o1, ucl_object_t *o2)
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))
{
if (cmp == NULL || ar == NULL || ar->type != UCL_ARRAY) {
return;
diff --git a/tests/test_basic.c b/tests/test_basic.c
index 0834728bb926..5a977aa7191a 100644
--- a/tests/test_basic.c
+++ b/tests/test_basic.c
@@ -78,7 +78,9 @@ main (int argc, char **argv)
while (!feof (in)) {
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);
test_in = malloc (inlen);
memcpy (test_in, inbuf, inlen);
diff --git a/tests/test_generate.c b/tests/test_generate.c
index b2081ba512f1..2b1bf8d73a3f 100644
--- a/tests/test_generate.c
+++ b/tests/test_generate.c
@@ -29,7 +29,7 @@
int
main (int argc, char **argv)
{
- ucl_object_t *obj, *cur, *ar;
+ ucl_object_t *obj, *cur, *ar, *ref;
FILE *out;
unsigned char *emitted;
const char *fname_out = NULL;
@@ -55,62 +55,64 @@ main (int argc, char **argv)
obj = ucl_object_typed_new (UCL_OBJECT);
/* Create some strings */
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);
- 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);
- obj = ucl_object_insert_key (obj, cur, "key3", 0, false);
+ ucl_object_insert_key (obj, cur, "key3", 0, false);
/* Array of numbers */
+ ar = ucl_object_typed_new (UCL_ARRAY);
cur = ucl_object_fromint (10);
- ar = ucl_array_append (NULL, cur);
+ ucl_array_append (ar, cur);
cur = ucl_object_fromdouble (10.1);
- ar = ucl_array_append (ar, cur);
+ ucl_array_append (ar, cur);
cur = ucl_object_fromdouble (9.999);
- ar = ucl_array_prepend (ar, cur);
+ ucl_array_prepend (ar, cur);
/* Removing from an array */
cur = ucl_object_fromdouble (1.0);
- ar = ucl_array_append (ar, cur);
+ ucl_array_append (ar, cur);
cur = ucl_array_delete (ar, cur);
assert (ucl_object_todouble (cur) == 1.0);
ucl_object_unref (cur);
cur = ucl_object_fromdouble (2.0);
- ar = ucl_array_append (ar, cur);
+ ucl_array_append (ar, cur);
cur = ucl_array_pop_last (ar);
assert (ucl_object_todouble (cur) == 2.0);
ucl_object_unref (cur);
cur = ucl_object_fromdouble (3.0);
- ar = ucl_array_prepend (ar, cur);
+ ucl_array_prepend (ar, cur);
cur = ucl_array_pop_first (ar);
assert (ucl_object_todouble (cur) == 3.0);
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);
- 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 */
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);
- 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);
- obj = ucl_object_insert_key (obj, cur, "key7", 0, false);
+ ucl_object_insert_key (obj, cur, "key7", 0, false);
/* Numbers and booleans */
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);
- 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);
- 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);
- 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);
- 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);
- obj = ucl_object_insert_key (obj, cur, "key13", 0, false);
+ ucl_object_insert_key (obj, cur, "key13", 0, false);
cur = ucl_object_frombool (true);
- obj = ucl_object_insert_key (obj, cur, "k=3", 0, false);
-
+ ucl_object_insert_key (obj, cur, "k=3", 0, false);
emitted = ucl_object_emit (obj, UCL_EMIT_CONFIG);
@@ -122,5 +124,9 @@ main (int argc, char **argv)
}
fclose (out);
+ /* Ref should still be accessible */
+ ref->value.iv = 100500;
+ ucl_object_unref (ref);
+
return ret;
}
diff --git a/tests/test_schema.c b/tests/test_schema.c
index 9436d71b4113..afce17816d50 100644
--- a/tests/test_schema.c
+++ b/tests/test_schema.c
@@ -58,10 +58,10 @@ read_stdin (char **buf)
}
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)
{
- ucl_object_t *valid, *data, *description;
+ const const ucl_object_t *valid, *data, *description;
bool match;
data = ucl_object_find_key (obj, "data");
@@ -86,11 +86,11 @@ perform_test (ucl_object_t *schema, ucl_object_t *obj,
}
static int
-perform_tests (ucl_object_t *obj)
+perform_tests (const ucl_object_t *obj)
{
struct ucl_schema_error err;
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) {
fprintf (stdout, "Bad test case\n");
@@ -124,7 +124,8 @@ main (int argc, char **argv)
{
char *buf = NULL;
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;
int ret = 0;
diff --git a/utils/objdump.c b/utils/objdump.c
index 8bf6e28edd53..2e00d0abc2f3 100644
--- a/utils/objdump.c
+++ b/utils/objdump.c
@@ -28,11 +28,11 @@
#include "ucl.h"
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;
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;
pre[--num] = 0x00;
@@ -64,7 +64,7 @@ ucl_obj_dump(ucl_object_t *obj, unsigned int shift)
}
else if (obj->type == UCL_INT) {
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) {
printf ("%stype: UCL_FLOAT\n", pre);
@@ -99,7 +99,7 @@ main(int argc, char **argv)
struct ucl_parser *parser;
int k, ret = 0, r = 0;
ucl_object_t *obj = NULL;
- ucl_object_t *par;
+ const ucl_object_t *par;
FILE *in;
if (argc > 1) {
@@ -129,7 +129,7 @@ main(int argc, char **argv)
}
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));
ret = 1;
goto end;