Commit 94f2b741 authored by Baptiste Daroussin's avatar Baptiste Daroussin
Browse files

Import libucl 0.8.0

parent 4e2fa78e
......@@ -37,3 +37,31 @@
- Fixed a bug with macroes that come after an empty object
- Fixed a bug in include processing when an incorrect variable has been destroyed (use-after-free)
### Libucl 0.8.0
- Allow to save comments and macros when parsing UCL documents
- C++ API
- Python bindings (by Eitan Adler)
- Add msgpack support for parser and emitter
- Add Canonical S-expressions parser for libucl
- CLI interface for parsing and validation (by Maxim Ignatenko)
- Implement include with priority
- Add 'nested' functionality to .include macro (by Allan Jude)
- Allow searching an array of paths for includes (by Allan Jude)
- Add new .load macro (by Allan Jude)
- Implement .inherit macro (#100)
- Add merge strategies
- Add schema validation to lua API
- Add support for external references to schema validation
- Add coveralls integration to libucl
- Implement tests for 80% of libucl code lines
- Fix tonns of minor and major bugs
- Improve documentation
- Rework function names to the common conventions (old names are preserved for backwards compatibility)
- Add Coverity scan integration
- Add fuzz tests
**Incompatible changes**:
- `ucl_object_emit_full` now accepts additional argument `comments` that could be used to emit comments with UCL output
\ No newline at end of file
......@@ -8,4 +8,74 @@ if LUA_SUB
LUA_SUBDIR = lua
endif
SUBDIRS = src tests utils doc $(LUA_SUBDIR)
\ No newline at end of file
COVERAGE_INFO_FILE = $(top_builddir)/coverage.info
COVERAGE_REPORT_DIR = $(top_builddir)/coverage
.PHONY = coverage-requirement-check clean-coverage-report
coverage-requirement-check:
@if test ! -e $(GCOV); then \
echo "Cannot find $(GCOV). Please install gcov."; \
exit 1; \
fi
coverage: coverage-requirement-check clean-coverage coverage-build coverage-check coverage-report
@echo "Please execute 'make clean' before 'make' or 'make check' to remove instrumented object files(compiled with -O0 etc.). Note that 'make clean' also remove coverage data."
coverage-build: coverage-requirement-check
@if test `find $(top_builddir) -name "*.gcno" | wc -l` -eq 0; then \
echo "Start to remove old non-instrumented object files..."; \
$(MAKE) $(AM_MAKEFLAGS) clean; \
echo "Successfully removed old non-instrumented object files."; \
fi
@echo "Start to build libraries with coverage options..."
$(MAKE) $(AM_MAKEFLAGS) \
CFLAGS="$(CFLAGS) $(COVERAGE_CFLAGS) $(COVERAGE_OPTFLAGS)" \
CXXFLAGS="$(CXXFLAGS) $(COVERAGE_CXXFLAGS) $(COVERAGE_OPTFLAGS)" \
LDFLAGS="$(LDFLAGS) $(COVERAGE_LDFLAGS)" \
LIBS="$(LIBS) $(COVERAGE_LIBS)"
@echo "Successfully built libraries with coverage options."
coverage-check: coverage-requirement-check
@echo "Start to run tests with instrumented libraries..."
$(MAKE) $(AM_MAKEFLAGS) check \
CFLAGS="$(CFLAGS) $(COVERAGE_CFLAGS) $(COVERAGE_OPTFLAGS)" \
CXXFLAGS="$(CXXFLAGS) $(COVERAGE_CXXFLAGS) $(COVERAGE_OPTFLAGS)" \
LDFLAGS="$(LDFLAGS) $(COVERAGE_LDFLAGS)" \
LIBS="$(LIBS) $(COVERAGE_LIBS)"
@echo "Successfully run tests with instrumented libraries."
coverage-lcov: coverage-check coverage-requirement-check
$(LCOV) --capture \
--directory "$(top_builddir)/" \
--output-file $(COVERAGE_INFO_FILE) \
--gcov-tool $(GCOV) \
--compat-libtool --checksum
$(LCOV) --extract $(COVERAGE_INFO_FILE) `pwd`/src/ucl_\* \
--output-file $(COVERAGE_INFO_FILE)
coverage-report: coverage-lcov
@echo "Start to create coverage reports..."
$(GENHTML) --prefix "$(top_srcdir)" \
--output-directory $(COVERAGE_REPORT_DIR) \
--title $(PACKAGE_NAME) \
--legend --show-details \
$(GENHTML_OPTIONS) \
$(COVERAGE_INFO_FILE)
@echo "Successfully created coverage reports into $(COVERAGE_REPORT_DIR) directory."
clean-coverage-report:
-rm -rf $(COVERAGE_INFO_FILE)
-rm -rf $(COVERAGE_REPORT_DIR)
clean-coverage: clean-coverage-report
-$(LCOV) --gcov-tool $(GCOV) --zerocounters --directory $(top_builddir)
@if xargs --version 2>/dev/null; then \
find $(top_builddir) -name "*.gcno" | xargs --no-run-if-empty rm; \
else \
find $(top_builddir) -name "*.gcno" | xargs rm; \
fi
clean-local: clean-coverage
SUBDIRS = src tests utils doc $(LUA_SUBDIR)
# LIBUCL
[![Build Status](https://travis-ci.org/vstakhov/libucl.svg?branch=master)](https://travis-ci.org/vstakhov/libucl)[![Coverity](https://scan.coverity.com/projects/4138/badge.svg)](https://scan.coverity.com/projects/4138)
[![Build Status](https://travis-ci.org/vstakhov/libucl.svg?branch=master)](https://travis-ci.org/vstakhov/libucl)[![Coverity](https://scan.coverity.com/projects/4138/badge.svg)](https://scan.coverity.com/projects/4138)[![Coverage Status](https://coveralls.io/repos/github/vstakhov/libucl/badge.svg?branch=master)](https://coveralls.io/github/vstakhov/libucl?branch=master)
**Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)*
......
m4_define([maj_ver], [0])
m4_define([med_ver], [7])
m4_define([min_ver], [3])
m4_define([so_version], [5:0:2])
m4_define([med_ver], [8])
m4_define([min_ver], [0])
m4_define([so_version], [6:0:0])
m4_define([ucl_version], [maj_ver.med_ver.min_ver])
AC_INIT([libucl],[ucl_version],[https://github.com/vstakhov/libucl],[libucl])
......@@ -173,6 +173,8 @@ AC_LINK_IFELSE([
AC_MSG_WARN([Libucl references could be thread-unsafe because atomic builtins are missing])
])
AX_CODE_COVERAGE
AC_CONFIG_FILES(Makefile \
src/Makefile \
lua/Makefile
......
......@@ -26,7 +26,6 @@
#include <string>
#include <memory>
#include <iostream>
#include <strstream>
#include "ucl.h"
......@@ -120,18 +119,19 @@ class Ucl final {
it = std::shared_ptr<void>(ucl_object_iterate_new (obj.obj.get()),
ucl_iter_deleter());
cur.reset (new Ucl(ucl_object_iterate_safe (it.get(), true)));
if (!*cur) {
it.reset ();
cur.reset ();
}
}
const_iterator() {}
const_iterator(const const_iterator &other) {
it = other.it;
}
const_iterator(const const_iterator &other) = delete;
const_iterator(const_iterator &&other) = default;
~const_iterator() {}
const_iterator& operator=(const const_iterator &other) {
it = other.it;
return *this;
}
const_iterator& operator=(const const_iterator &other) = delete;
const_iterator& operator=(const_iterator &&other) = default;
bool operator==(const const_iterator &other) const
{
......@@ -264,45 +264,51 @@ class Ucl final {
return res;
}
double number_value () const
double number_value (const double default_val = 0.0) const
{
if (obj) {
return ucl_object_todouble (obj.get());
double res;
if (ucl_object_todouble_safe(obj.get(), &res)) {
return res;
}
return 0.0;
return default_val;
}
int64_t int_value () const
int64_t int_value (const int64_t default_val = 0) const
{
if (obj) {
return ucl_object_toint (obj.get());
int64_t res;
if (ucl_object_toint_safe(obj.get(), &res)) {
return res;
}
return 0;
return default_val;
}
bool bool_value () const
bool bool_value (const bool default_val = false) const
{
if (obj) {
return ucl_object_toboolean (obj.get());
bool res;
if (ucl_object_toboolean_safe(obj.get(), &res)) {
return res;
}
return false;
return default_val;
}
const std::string string_value () const
const std::string string_value (const std::string& default_val = "") const
{
std::string res;
const char* res = nullptr;
if (obj) {
res.assign (ucl_object_tostring (obj.get()));
if (ucl_object_tostring_safe(obj.get(), &res)) {
return res;
}
return res;
return default_val;
}
const Ucl operator[] (size_t i) const
const Ucl at (size_t i) const
{
if (type () == UCL_ARRAY) {
return Ucl (ucl_array_find_index (obj.get(), i));
......@@ -311,15 +317,25 @@ class Ucl final {
return Ucl (nullptr);
}
const Ucl operator[](const std::string &key) const
const Ucl lookup (const std::string &key) const
{
if (type () == UCL_OBJECT) {
return Ucl (ucl_object_find_keyl (obj.get(),
return Ucl (ucl_object_lookup_len (obj.get(),
key.data (), key.size ()));
}
return Ucl (nullptr);
}
inline const Ucl operator[] (size_t i) const
{
return at(i);
}
inline const Ucl operator[](const std::string &key) const
{
return lookup(key);
}
// Serialize.
void dump (std::string &out, ucl_emitter_t type = UCL_EMIT_JSON) const
{
......@@ -328,7 +344,7 @@ class Ucl final {
cbdata = Ucl::default_emit_funcs();
cbdata.ud = reinterpret_cast<void *>(&out);
ucl_object_emit_full (obj.get(), type, &cbdata);
ucl_object_emit_full (obj.get(), type, &cbdata, nullptr);
}
std::string dump (ucl_emitter_t type = UCL_EMIT_JSON) const
......@@ -375,6 +391,12 @@ class Ucl final {
std::istreambuf_iterator<char>()), err);
}
Ucl& operator= (Ucl rhs)
{
obj.swap (rhs.obj);
return *this;
}
bool operator== (const Ucl &rhs) const
{
return ucl_object_compare (obj.get(), rhs.obj.get ()) == 0;
......@@ -388,7 +410,7 @@ class Ucl final {
bool operator> (const Ucl &rhs) const { return (rhs < *this); }
bool operator>= (const Ucl &rhs) const { return !(*this < rhs); }
operator bool () const
explicit operator bool () const
{
if (!obj || type() == UCL_NULL) {
return false;
......
......@@ -107,7 +107,8 @@ typedef enum ucl_error {
UCL_ENESTED, /**< Input has too many recursion levels */
UCL_EMACRO, /**< Error processing a macro */
UCL_EINTERNAL, /**< Internal unclassified error */
UCL_ESSL /**< SSL error */
UCL_ESSL, /**< SSL error */
UCL_EMERGE /**< A merge error occured */
} ucl_error_t;
/**
......@@ -147,11 +148,13 @@ typedef enum ucl_emitter {
* UCL still has to perform copying implicitly.
*/
typedef enum ucl_parser_flags {
UCL_PARSER_DEFAULT = 0x0, /**< No special flags */
UCL_PARSER_KEY_LOWERCASE = 0x1, /**< Convert all keys to lower case */
UCL_PARSER_ZEROCOPY = 0x2, /**< Parse input in zero-copy mode if possible */
UCL_PARSER_NO_TIME = 0x4, /**< Do not parse time and treat time values as strings */
UCL_PARSER_NO_IMPLICIT_ARRAYS = 0x8 /** Create explicit arrays instead of implicit ones */
UCL_PARSER_DEFAULT = 0, /**< No special flags */
UCL_PARSER_KEY_LOWERCASE = (1 << 0), /**< Convert all keys to lower case */
UCL_PARSER_ZEROCOPY = (1 << 1), /**< Parse input in zero-copy mode if possible */
UCL_PARSER_NO_TIME = (1 << 2), /**< Do not parse time and treat time values as strings */
UCL_PARSER_NO_IMPLICIT_ARRAYS = (1 << 3), /** Create explicit arrays instead of implicit ones */
UCL_PARSER_SAVE_COMMENTS = (1 << 4), /** Save comments in the parser context */
UCL_PARSER_DISABLE_MACRO = (1 << 5) /** Treat macros as comments */
} ucl_parser_flags_t;
/**
......@@ -159,17 +162,17 @@ typedef enum ucl_parser_flags {
*/
typedef enum ucl_string_flags {
UCL_STRING_RAW = 0x0, /**< Treat string as is */
UCL_STRING_ESCAPE = 0x1, /**< Perform JSON escape */
UCL_STRING_TRIM = 0x2, /**< Trim leading and trailing whitespaces */
UCL_STRING_PARSE_BOOLEAN = 0x4, /**< Parse passed string and detect boolean */
UCL_STRING_PARSE_INT = 0x8, /**< Parse passed string and detect integer number */
UCL_STRING_PARSE_DOUBLE = 0x10, /**< Parse passed string and detect integer or float number */
UCL_STRING_PARSE_TIME = 0x20, /**< Parse time strings */
UCL_STRING_ESCAPE = (1 << 0), /**< Perform JSON escape */
UCL_STRING_TRIM = (1 << 1), /**< Trim leading and trailing whitespaces */
UCL_STRING_PARSE_BOOLEAN = (1 << 2), /**< Parse passed string and detect boolean */
UCL_STRING_PARSE_INT = (1 << 3), /**< Parse passed string and detect integer number */
UCL_STRING_PARSE_DOUBLE = (1 << 4), /**< Parse passed string and detect integer or float number */
UCL_STRING_PARSE_TIME = (1 << 5), /**< Parse time strings */
UCL_STRING_PARSE_NUMBER = UCL_STRING_PARSE_INT|UCL_STRING_PARSE_DOUBLE|UCL_STRING_PARSE_TIME, /**<
Parse passed string and detect number */
UCL_STRING_PARSE = UCL_STRING_PARSE_BOOLEAN|UCL_STRING_PARSE_NUMBER, /**<
Parse passed string (and detect booleans and numbers) */
UCL_STRING_PARSE_BYTES = 0x40 /**< Treat numbers as bytes */
UCL_STRING_PARSE_BYTES = (1 << 6) /**< Treat numbers as bytes */
} ucl_string_flags_t;
/**
......@@ -286,10 +289,12 @@ UCL_EXTERN ucl_object_t* ucl_object_new_full (ucl_type_t type, unsigned priority
/**
* Create new object with userdata dtor
* @param dtor destructor function
* @param emitter emitter for userdata
* @param ptr opaque pointer
* @return new object
*/
UCL_EXTERN ucl_object_t* ucl_object_new_userdata (ucl_userdata_dtor dtor,
ucl_userdata_emitter emitter) UCL_WARN_UNUSED_RESULT;
ucl_userdata_emitter emitter, void *ptr) UCL_WARN_UNUSED_RESULT;
/**
* Perform deep copy of an object copying everything
......@@ -305,6 +310,21 @@ UCL_EXTERN ucl_object_t * ucl_object_copy (const ucl_object_t *other)
*/
UCL_EXTERN ucl_type_t ucl_object_type (const ucl_object_t *obj);
/**
* Converts ucl object type to its string representation
* @param type type of object
* @return constant string describing type
*/
UCL_EXTERN const char * ucl_object_type_to_string (ucl_type_t type);
/**
* Converts string that represents ucl type to real ucl type enum
* @param input C string with name of type
* @param res resulting target
* @return true if `input` is a name of type stored in `res`
*/
UCL_EXTERN bool ucl_object_string_to_type (const char *input, ucl_type_t *res);
/**
* Convert any string to an ucl object making the specified transformations
* @param str fixed size or NULL terminated string
......@@ -642,8 +662,9 @@ UCL_EXTERN const char* ucl_object_tolstring (const ucl_object_t *obj, size_t *tl
* @param key key to search
* @return object matching the specified key or NULL if key was not found
*/
UCL_EXTERN const ucl_object_t* ucl_object_find_key (const ucl_object_t *obj,
UCL_EXTERN const ucl_object_t* ucl_object_lookup (const ucl_object_t *obj,
const char *key);
#define ucl_object_find_key ucl_object_lookup
/**
* Return object identified by a key in the specified object, if the first key is
......@@ -655,8 +676,9 @@ UCL_EXTERN const ucl_object_t* ucl_object_find_key (const ucl_object_t *obj,
* @param ... list of alternative keys to search (NULL terminated)
* @return object matching the specified key or NULL if key was not found
*/
UCL_EXTERN const ucl_object_t* ucl_object_find_any_key (const ucl_object_t *obj,
UCL_EXTERN const ucl_object_t* ucl_object_lookup_any (const ucl_object_t *obj,
const char *key, ...);
#define ucl_object_find_any_key ucl_object_lookup_any
/**
* Return object identified by a fixed size key in the specified object
......@@ -665,8 +687,9 @@ UCL_EXTERN const ucl_object_t* ucl_object_find_any_key (const ucl_object_t *obj,
* @param klen length of a key
* @return object matching the specified key or NULL if key was not found
*/
UCL_EXTERN const ucl_object_t* ucl_object_find_keyl (const ucl_object_t *obj,
UCL_EXTERN const ucl_object_t* ucl_object_lookup_len (const ucl_object_t *obj,
const char *key, size_t klen);
#define ucl_object_find_keyl ucl_object_lookup_len
/**
* Return object identified by dot notation string
......@@ -674,8 +697,9 @@ UCL_EXTERN const ucl_object_t* ucl_object_find_keyl (const ucl_object_t *obj,
* @param path dot.notation.path to the path to lookup. May use numeric .index on arrays
* @return object matched the specified path or NULL if path is not found
*/
UCL_EXTERN const ucl_object_t *ucl_lookup_path (const ucl_object_t *obj,
UCL_EXTERN const ucl_object_t *ucl_object_lookup_path (const ucl_object_t *obj,
const char *path);
#define ucl_lookup_path ucl_object_lookup_path
/**
* Return object identified by object notation string using arbitrary delimiter
......@@ -684,8 +708,9 @@ UCL_EXTERN const ucl_object_t *ucl_lookup_path (const ucl_object_t *obj,
* @param sep the sepatorator to use in place of . (incase keys have . in them)
* @return object matched the specified path or NULL if path is not found
*/
UCL_EXTERN const ucl_object_t *ucl_lookup_path_char (const ucl_object_t *obj,
UCL_EXTERN const ucl_object_t *ucl_object_lookup_path_char (const ucl_object_t *obj,
const char *path, char sep);
#define ucl_lookup_path_char ucl_object_lookup_path_char
/**
* Returns a key of an object as a NULL terminated string
......@@ -734,6 +759,19 @@ UCL_EXTERN void ucl_object_unref (ucl_object_t *obj);
UCL_EXTERN int ucl_object_compare (const ucl_object_t *o1,
const ucl_object_t *o2);
/**
* Compare objects `o1` and `o2` useful for sorting
* @param o1 the first object
* @param o2 the second object
* @return values >0, 0 and <0 if `o1` is more than, equal and less than `o2`.
* The order of comparison:
* 1) Type of objects
* 2) Size of objects
* 3) Content of objects
*/
UCL_EXTERN int ucl_object_compare_qsort (const ucl_object_t **o1,
const ucl_object_t **o2);
/**
* Sort UCL array using `cmp` compare function
* @param ar
......@@ -770,8 +808,9 @@ typedef void* ucl_object_iter_t;
* while ((cur = ucl_iterate_object (obj, &it)) != NULL) ...
* @return the next object or NULL
*/
UCL_EXTERN const ucl_object_t* ucl_iterate_object (const ucl_object_t *obj,
UCL_EXTERN const ucl_object_t* ucl_object_iterate (const ucl_object_t *obj,
ucl_object_iter_t *iter, bool expand_values);
#define ucl_iterate_object ucl_object_iterate
/**
* Create new safe iterator for the specified object
......@@ -1040,34 +1079,34 @@ UCL_EXTERN ucl_object_t* ucl_parser_get_object (struct ucl_parser *parser);
* @param parser parser object
* @return error description
*/
UCL_EXTERN const char *ucl_parser_get_error(struct ucl_parser *parser);
UCL_EXTERN const char *ucl_parser_get_error (struct ucl_parser *parser);
/**
* Get the code of the last error
* @param parser parser object
* @return error code
*/
UCL_EXTERN int ucl_parser_get_error_code(struct ucl_parser *parser);
UCL_EXTERN int ucl_parser_get_error_code (struct ucl_parser *parser);
/**
* Get the current column number within parser
* @param parser parser object
* @return current column number
*/
UCL_EXTERN unsigned ucl_parser_get_column(struct ucl_parser *parser);
UCL_EXTERN unsigned ucl_parser_get_column (struct ucl_parser *parser);
/**
* Get the current line number within parser
* @param parser parser object
* @return current line number
*/
UCL_EXTERN unsigned ucl_parser_get_linenum(struct ucl_parser *parser);
UCL_EXTERN unsigned ucl_parser_get_linenum (struct ucl_parser *parser);
/**
* Clear the error in the parser
* @param parser parser object
*/
UCL_EXTERN void ucl_parser_clear_error(struct ucl_parser *parser);
UCL_EXTERN void ucl_parser_clear_error (struct ucl_parser *parser);
/**
* Free ucl parser object
......@@ -1075,6 +1114,42 @@ UCL_EXTERN void ucl_parser_clear_error(struct ucl_parser *parser);
*/
UCL_EXTERN void ucl_parser_free (struct ucl_parser *parser);
/**
* Get constant opaque pointer to comments structure for this parser. Increase
* refcount to prevent this object to be destroyed on parser's destruction
* @param parser parser structure
* @return ucl comments pointer or NULL
*/
UCL_EXTERN const ucl_object_t * ucl_parser_get_comments (struct ucl_parser *parser);
/**
* Utility function to find a comment object for the specified object in the input
* @param comments comments object
* @param srch search object
* @return string comment enclosed in ucl_object_t
*/
UCL_EXTERN const ucl_object_t * ucl_comments_find (const ucl_object_t *comments,
const ucl_object_t *srch);
/**
* Move comment from `from` object to `to` object
* @param comments comments object
* @param what source object
* @param whith destination object
* @return `true` if `from` has comment and it has been moved to `to`
*/
UCL_EXTERN bool ucl_comments_move (ucl_object_t *comments,
const ucl_object_t *from, const ucl_object_t *to);
/**
* Adds a new comment for an object
* @param comments comments object
* @param obj object to add comment to
* @param comment string representation of a comment
*/
UCL_EXTERN void ucl_comments_add (ucl_object_t *comments,
const ucl_object_t *obj, const char *comment);
/**
* Add new public key to parser for signatures check
* @param parser parser object
......@@ -1083,7 +1158,8 @@ UCL_EXTERN void ucl_parser_free (struct ucl_parser *parser);
* @param err if *err is NULL it is set to parser error
* @return true if a key has been successfully added
*/
UCL_EXTERN bool ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len);
UCL_EXTERN bool ucl_parser_pubkey_add (struct ucl_parser *parser,
const unsigned char *key, size_t len);
/**
* Set FILENAME and CURDIR variables in parser
......@@ -1156,8 +1232,8 @@ struct ucl_emitter_context {
unsigned int indent;
/** Top level object */
const ucl_object_t *top;
/** The rest of context */
unsigned char data[1];
/** Optional comments */
const ucl_object_t *comments;
};
/**
......@@ -1187,11 +1263,13 @@ UCL_EXTERN unsigned char *ucl_object_emit_len (const ucl_object_t *obj,
* @param emit_type if type is #UCL_EMIT_JSON then emit json, if type is
* #UCL_EMIT_CONFIG then emit config like object
* @param emitter a set of emitter functions
* @param comments optional comments for the parser
* @return dump of an object (must be freed after using) or NULL in case of error
*/
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,
const ucl_object_t *comments);
/**
* Start streamlined UCL object emitter
......@@ -1280,6 +1358,9 @@ enum ucl_schema_error_code {
UCL_SCHEMA_MISSING_PROPERTY,/**< one or more missing properties */
UCL_SCHEMA_CONSTRAINT, /**< constraint found */
UCL_SCHEMA_MISSING_DEPENDENCY, /**< missing dependency */
UCL_SCHEMA_EXTERNAL_REF_MISSING, /**< cannot fetch external ref */
UCL_SCHEMA_EXTERNAL_REF_INVALID, /**< invalid external ref */
UCL_SCHEMA_INTERNAL_ERROR, /**< something bad happened */
UCL_SCHEMA_UNKNOWN /**< generic error */
};
......@@ -1303,6 +1384,37 @@ struct ucl_schema_error {
UCL_EXTERN bool ucl_object_validate (const ucl_object_t *schema,
const ucl_object_t *obj, struct ucl_schema_error *err);
/**
* Validate object `obj` using schema object `schema` and root schema at `root`.
* @param schema schema object
* @param obj object to validate
* @param root root schema object
* @param err error pointer, if this parameter is not NULL and error has been
* occured, then `err` is filled with the exact error definition.
* @return true if `obj` is valid using `schema`
*/
UCL_EXTERN bool ucl_object_validate_root (const ucl_object_t *schema,
const ucl_object_t *obj,
const ucl_object_t *root,
struct ucl_schema_error *err);
/**
* Validate object `obj` using schema object `schema` and root schema at `root`
* using some external references provided.
* @param schema schema object
* @param obj object to validate
* @param root root schema object
* @param ext_refs external references (might be modified during validation)
* @param err error pointer, if this parameter is not NULL and error has been
* occured, then `err` is filled with the exact error definition.
* @return true if `obj` is valid using `schema`
*/
UCL_EXTERN bool ucl_object_validate_root_ext (const ucl_object_t *schema,
const ucl_object_t *obj,
const ucl_object_t *root,
ucl_object_t *ext_refs,
struct ucl_schema_error *err);