From owner-svn-src-vendor@freebsd.org Sat Oct 1 00:11:12 2016 Return-Path: Delivered-To: svn-src-vendor@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 4B145C049DF; Sat, 1 Oct 2016 00:11:12 +0000 (UTC) (envelope-from bapt@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id D959CA40; Sat, 1 Oct 2016 00:11:11 +0000 (UTC) (envelope-from bapt@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u910BBW1007683; Sat, 1 Oct 2016 00:11:11 GMT (envelope-from bapt@FreeBSD.org) Received: (from bapt@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u910BAjp007670; Sat, 1 Oct 2016 00:11:10 GMT (envelope-from bapt@FreeBSD.org) Message-Id: <201610010011.u910BAjp007670@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: bapt set sender to bapt@FreeBSD.org using -f From: Baptiste Daroussin Date: Sat, 1 Oct 2016 00:11:10 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org Subject: svn commit: r306542 - in vendor/libucl/dist: . haskell include m4 python python/src python/tests src tests/schema X-SVN-Group: vendor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-vendor@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the vendor work area tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 01 Oct 2016 00:11:12 -0000 Author: bapt Date: Sat Oct 1 00:11:09 2016 New Revision: 306542 URL: https://svnweb.freebsd.org/changeset/base/306542 Log: Update libucl to snapshot 20160812 Added: vendor/libucl/dist/haskell/ vendor/libucl/dist/haskell/hucl.hs vendor/libucl/dist/m4/gcov.m4 vendor/libucl/dist/python/tests/ vendor/libucl/dist/python/tests/__init__.py (contents, props changed) vendor/libucl/dist/python/tests/compat.py (contents, props changed) vendor/libucl/dist/python/tests/test_dump.py (contents, props changed) vendor/libucl/dist/python/tests/test_load.py (contents, props changed) vendor/libucl/dist/python/tests/test_validation.py (contents, props changed) Deleted: vendor/libucl/dist/python/test.sh vendor/libucl/dist/python/test_uclmodule.py Modified: vendor/libucl/dist/CMakeLists.txt vendor/libucl/dist/Makefile.unix vendor/libucl/dist/Makefile.w32 vendor/libucl/dist/README.md vendor/libucl/dist/include/ucl++.h vendor/libucl/dist/include/ucl.h vendor/libucl/dist/python/setup.py vendor/libucl/dist/python/src/uclmodule.c vendor/libucl/dist/src/mum.h vendor/libucl/dist/src/ucl_parser.c vendor/libucl/dist/src/ucl_schema.c vendor/libucl/dist/src/ucl_util.c vendor/libucl/dist/tests/schema/patternProperties.json vendor/libucl/dist/tests/schema/refRemote.json Modified: vendor/libucl/dist/CMakeLists.txt ============================================================================== --- vendor/libucl/dist/CMakeLists.txt Fri Sep 30 23:38:26 2016 (r306541) +++ vendor/libucl/dist/CMakeLists.txt Sat Oct 1 00:11:09 2016 (r306542) @@ -205,8 +205,7 @@ SET(UCLSRC src/ucl_util.c src/ucl_hash.c src/ucl_schema.c src/ucl_msgpack.c - src/ucl_sexp.c - src/xxhash.c) + src/ucl_sexp.c) SET (LIB_TYPE STATIC) Modified: vendor/libucl/dist/Makefile.unix ============================================================================== --- vendor/libucl/dist/Makefile.unix Fri Sep 30 23:38:26 2016 (r306541) +++ vendor/libucl/dist/Makefile.unix Sat Oct 1 00:11:09 2016 (r306542) @@ -1,7 +1,7 @@ CC ?= gcc DESTDIR ?= /usr/local LD ?= gcc -C_COMMON_FLAGS ?= -fPIC -Wall -W -Wno-unused-parameter -Wno-pointer-sign -I./include -I./uthash -I./src +C_COMMON_FLAGS ?= -fPIC -Wall -W -Wno-unused-parameter -Wno-pointer-sign -I./include -I./uthash -I./src -I./klib MAJOR_VERSION = 0 MINOR_VERSION = 2 PATCH_VERSION = 9 @@ -25,13 +25,12 @@ HDEPS = $(SRCDIR)/ucl_hash.h \ $(SRCDIR)/ucl_chartable.h \ $(SRCDIR)/ucl_internal.h \ $(INCLUDEDIR)/ucl.h \ - $(SRCDIR)/xxhash.h + $(SRCDIR)/mum.h OBJECTS = $(OBJDIR)/ucl_hash.o \ $(OBJDIR)/ucl_util.o \ $(OBJDIR)/ucl_parser.o \ $(OBJDIR)/ucl_emitter.o \ - $(OBJDIR)/ucl_schema.o \ - $(OBJDIR)/xxhash.o + $(OBJDIR)/ucl_schema.o all: $(OBJDIR) $(OBJDIR)/$(SONAME) @@ -55,8 +54,6 @@ $(OBJDIR)/ucl_hash.o: $(SRCDIR)/ucl_hash $(CC) -o $(OBJDIR)/ucl_hash.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_hash.c $(OBJDIR)/ucl_schema.o: $(SRCDIR)/ucl_schema.c $(HDEPS) $(CC) -o $(OBJDIR)/ucl_schema.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_schema.c -$(OBJDIR)/xxhash.o: $(SRCDIR)/xxhash.c $(HDEPS) - $(CC) -o $(OBJDIR)/xxhash.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/xxhash.c clean: $(RM) $(OBJDIR)/*.o $(OBJDIR)/$(SONAME_FULL) $(OBJDIR)/$(SONAME) $(OBJDIR)/chargen $(OBJDIR)/test_basic $(OBJDIR)/test_speed $(OBJDIR)/objdump $(OBJDIR)/test_generate $(OBJDIR)/test_schema || true Modified: vendor/libucl/dist/Makefile.w32 ============================================================================== --- vendor/libucl/dist/Makefile.w32 Fri Sep 30 23:38:26 2016 (r306541) +++ vendor/libucl/dist/Makefile.w32 Sat Oct 1 00:11:09 2016 (r306542) @@ -28,14 +28,13 @@ HDEPS = $(SRCDIR)/ucl_hash.h \ $(SRCDIR)/ucl_chartable.h \ $(SRCDIR)/ucl_internal.h \ $(INCLUDEDIR)/ucl.h \ - $(SRCDIR)/xxhash.h + $(SRCDIR)/mum.h OBJECTS = $(OBJDIR)/ucl_hash.o \ $(OBJDIR)/ucl_util.o \ $(OBJDIR)/ucl_parser.o \ $(OBJDIR)/ucl_emitter.o \ $(OBJDIR)/ucl_emitter_utils.o \ - $(OBJDIR)/ucl_schema.o \ - $(OBJDIR)/xxhash.o + $(OBJDIR)/ucl_schema.o all: $(OBJDIR) $(OBJDIR)/$(SONAME) Modified: vendor/libucl/dist/README.md ============================================================================== --- vendor/libucl/dist/README.md Fri Sep 30 23:38:26 2016 (r306541) +++ vendor/libucl/dist/README.md Sat Oct 1 00:11:09 2016 (r306542) @@ -12,7 +12,7 @@ - [Named keys hierarchy](#named-keys-hierarchy) - [Convenient numbers and booleans](#convenient-numbers-and-booleans) - [General improvements](#general-improvements) - - [Commments](#commments) + - [Comments](#comments) - [Macros support](#macros-support) - [Variables support](#variables-support) - [Multiline strings](#multiline-strings) @@ -21,7 +21,7 @@ - [Performance](#performance) - [Conclusion](#conclusion) -## Introduction +## Introduction This document describes the main features and principles of the configuration language called `UCL` - universal configuration language. @@ -47,7 +47,7 @@ section { string = "something"; subsection { host = { - host = "hostname"; + host = "hostname"; port = 900; } host = { @@ -163,9 +163,9 @@ section { } } ``` - + Plain definitions may be more complex and contain more than a single level of nested objects: - + ```nginx section "blah" "foo" { key = value; @@ -174,7 +174,7 @@ section "blah" "foo" { is presented as: -```nginx +```nginx section { blah { foo { @@ -196,17 +196,17 @@ section { ## General improvements -### Commments +### Comments UCL supports different style of comments: -* single line: `#` +* single line: `#` * multiline: `/* ... */` Multiline comments may be nested: ```c # Sample single line comment -/* +/* some comment /* nested comment */ end of comment @@ -263,7 +263,7 @@ all files that matches the specified pat for your operating system). This option is meaningless for URL includes. * `url` (default: **true**) - allow URL includes. * `path` (default: empty) - A UCL_ARRAY of directories to search for the include file. -Search ends after the first patch, unless `glob` is true, then all matches are included. +Search ends after the first match, unless `glob` is true, then all matches are included. * `prefix` (default false) - Put included contents inside an object, instead of loading them into the root. If no `key` is provided, one is automatically generated based on each files basename() * `key` (default: ) - Key to load contents of include into. If @@ -273,7 +273,7 @@ object or an array. * `priority` (default: 0) - specify priority for the include (see below). * `duplicate` (default: 'append') - specify policy of duplicates resolving: - `append` - default strategy, if we have new object of higher priority then it replaces old one, if we have new object with less priority it is ignored completely, and if we have two duplicate objects with the same priority then we have a multi-value key (implicit array) - - `merge` - if we have object or array, then new keys are merged inside, if we have a plain object then an implicit array is formed (regardeless of priorities) + - `merge` - if we have object or array, then new keys are merged inside, if we have a plain object then an implicit array is formed (regardless of priorities) - `error` - create error on duplicate keys and stop parsing - `rewrite` - always rewrite an old value with new one (ignoring priorities) @@ -320,7 +320,7 @@ Here are some rules for this syntax: * Multiline terminator must start just after `<<` symbols and it must consist of capital letters only (e.g. `< ParserHandle +foreign import ccall "ucl_parser_add_string" ucl_parser_add_string :: ParserHandle -> CString -> CUInt -> IO Bool +foreign import ccall "ucl_parser_add_file" ucl_parser_add_file :: ParserHandle -> CString -> IO Bool +foreign import ccall "ucl_parser_get_object" ucl_parser_get_object :: ParserHandle -> UCLObjectHandle +foreign import ccall "ucl_parser_get_error" ucl_parser_get_error :: ParserHandle -> CString + +foreign import ccall "ucl_object_iterate_new" ucl_object_iterate_new :: UCLObjectHandle -> UCLIterHandle +foreign import ccall "ucl_object_iterate_safe" ucl_object_iterate_safe :: UCLIterHandle -> Bool -> UCLObjectHandle +foreign import ccall "ucl_object_type" ucl_object_type :: UCLObjectHandle -> CUInt +foreign import ccall "ucl_object_key" ucl_object_key :: UCLObjectHandle -> CString +foreign import ccall "ucl_object_toint" ucl_object_toint :: UCLObjectHandle -> CInt +foreign import ccall "ucl_object_todouble" ucl_object_todouble :: UCLObjectHandle -> CDouble +foreign import ccall "ucl_object_tostring" ucl_object_tostring :: UCLObjectHandle -> CString +foreign import ccall "ucl_object_toboolean" ucl_object_toboolean :: UCLObjectHandle -> Bool + +foreign import ccall "ucl_object_emit" ucl_object_emit :: UCLObjectHandle -> UCLEmitterType -> CString +foreign import ccall "ucl_object_emit_len" ucl_object_emit_len :: UCLObjectHandle -> UCLEmitterType -> Ptr CSize -> IO CString + +type UCL_TYPE = CUInt +ucl_OBJECT :: UCL_TYPE +ucl_OBJECT = 0 +ucl_ARRAY :: UCL_TYPE +ucl_ARRAY = 1 +ucl_INT :: UCL_TYPE +ucl_INT = 2 +ucl_FLOAT :: UCL_TYPE +ucl_FLOAT = 3 +ucl_STRING :: UCL_TYPE +ucl_STRING = 4 +ucl_BOOLEAN :: UCL_TYPE +ucl_BOOLEAN = 5 +ucl_TIME :: UCL_TYPE +ucl_TIME = 6 +ucl_USERDATA :: UCL_TYPE +ucl_USERDATA = 7 +ucl_NULL :: UCL_TYPE +ucl_NULL = 8 + +ucl_emit_json :: UCLEmitterType +ucl_emit_json = 0 +ucl_emit_json_compact :: UCLEmitterType +ucl_emit_json_compact = 1 :: UCLEmitterType +ucl_emit_msgpack :: UCLEmitterType +ucl_emit_msgpack = 4 :: UCLEmitterType + +ucl_parser_parse_string_pure :: String -> Either UCLObjectHandle ErrorString +ucl_parser_parse_string_pure s = unsafePerformIO $ do + cs <- newCString s + let p = ucl_parser_new 0x4 + didParse <- ucl_parser_add_string p cs (toEnum $ length s) + if didParse + then return $ Left $ ucl_parser_get_object p + else Right <$> peekCString ( ucl_parser_get_error p) + +ucl_parser_add_file_pure :: String -> Either UCLObjectHandle ErrorString +ucl_parser_add_file_pure s = unsafePerformIO $ do + cs <- newCString s + let p = ucl_parser_new 0x4 + didParse <- ucl_parser_add_file p cs + if didParse + then return $ Left $ ucl_parser_get_object p + else Right <$> peekCString ( ucl_parser_get_error p) + +unpack :: MSG.MessagePack a => String -> Either a ErrorString +unpack s = case ucl_parser_parse_string_pure s of + (Right err) -> Right err + (Left obj) -> case MSG.fromObject (ucl_to_msgpack_object obj) of + Nothing -> Right "MessagePack fromObject Error" + (Just a) -> Left a + +ucl_to_msgpack_object :: UCLObjectHandle -> MSG.Object +ucl_to_msgpack_object o = toMsgPackObj (ucl_object_type o) o + where + toMsgPackObj n obj + |n==ucl_OBJECT = MSG.ObjectMap $ uclObjectToVector obj + |n==ucl_ARRAY = MSG.ObjectArray undefined + |n==ucl_INT = MSG.ObjectInt $ fromEnum $ ucl_object_toint obj + |n==ucl_FLOAT = MSG.ObjectDouble $ realToFrac $ ucl_object_todouble obj + |n==ucl_STRING = MSG.ObjectStr $ T.pack $ unsafePerformIO $ peekCString $ ucl_object_tostring obj + |n==ucl_BOOLEAN = MSG.ObjectBool $ ucl_object_toboolean obj + |n==ucl_TIME = error "time undefined" + |n==ucl_USERDATA = error "userdata undefined" + |n==ucl_NULL = error "null undefined" + |otherwise = error "\"Unknown Type\" Error" + +uclObjectToVector :: UCLObjectHandle -> V.Vector (MSG.Object,MSG.Object) +uclObjectToVector o = iterateObject (ucl_object_iterate_safe iter True ) iter V.empty + where + iter = ucl_object_iterate_new o + iterateObject obj it vec = if ucl_object_type obj == ucl_NULL + then vec + else iterateObject (ucl_object_iterate_safe it True) it (V.snoc vec ( getUclKey obj , ucl_to_msgpack_object obj)) + getUclKey obj = MSG.ObjectStr $ T.pack $ unsafePerformIO $ peekCString $ ucl_object_key obj + +uclArrayToVector :: UCLObjectHandle -> V.Vector MSG.Object +uclArrayToVector o = iterateArray (ucl_object_iterate_safe iter True ) iter V.empty + where + iter = ucl_object_iterate_new o + iterateArray obj it vec = if ucl_object_type obj == ucl_NULL + then vec + else iterateArray (ucl_object_iterate_safe it True) it (V.snoc vec (ucl_to_msgpack_object obj)) + Modified: vendor/libucl/dist/include/ucl++.h ============================================================================== --- vendor/libucl/dist/include/ucl++.h Fri Sep 30 23:38:26 2016 (r306541) +++ vendor/libucl/dist/include/ucl++.h Sat Oct 1 00:11:09 2016 (r306542) @@ -24,6 +24,9 @@ #pragma once #include +#include +#include +#include #include #include @@ -100,6 +103,68 @@ private: return func; }; + static bool ucl_variable_getter(const unsigned char *data, size_t len, + unsigned char ** /*replace*/, size_t * /*replace_len*/, bool *need_free, void* ud) + { + *need_free = false; + + auto vars = reinterpret_cast *>(ud); + if (vars && data && len != 0) { + vars->emplace (data, data + len); + } + return false; + } + + static bool ucl_variable_replacer (const unsigned char *data, size_t len, + unsigned char **replace, size_t *replace_len, bool *need_free, void* ud) + { + *need_free = false; + + auto replacer = reinterpret_cast(ud); + if (!replacer) { + return false; + } + + std::string var_name (data, data + len); + if (!replacer->is_variable (var_name)) { + return false; + } + + std::string var_value = replacer->replace (var_name); + if (var_value.empty ()) { + return false; + } + + *replace = (unsigned char *)UCL_ALLOC (var_value.size ()); + memcpy (*replace, var_value.data (), var_value.size ()); + + *replace_len = var_value.size (); + *need_free = true; + + return true; + } + + template + static Ucl parse_with_strategy_function (C config_func, P parse_func, std::string &err) + { + auto parser = ucl_parser_new (UCL_PARSER_DEFAULT); + + config_func (parser); + + if (!parse_func (parser)) { + err.assign (ucl_parser_get_error (parser)); + ucl_parser_free (parser); + + return nullptr; + } + + auto obj = ucl_parser_get_object (parser); + ucl_parser_free (parser); + + // Obj will handle ownership + return Ucl (obj); + } + std::unique_ptr obj; public: @@ -117,9 +182,9 @@ public: const_iterator(const Ucl &obj) { it = std::shared_ptr(ucl_object_iterate_new (obj.obj.get()), - ucl_iter_deleter()); + ucl_iter_deleter()); cur.reset (new Ucl(ucl_object_iterate_safe (it.get(), true))); - if (!*cur) { + if (cur->type() == UCL_NULL) { it.reset (); cur.reset (); } @@ -153,7 +218,7 @@ public: cur.reset (new Ucl(ucl_object_iterate_safe (it.get(), true))); } - if (!*cur) { + if (cur && cur->type() == UCL_NULL) { it.reset (); cur.reset (); } @@ -171,6 +236,17 @@ public: } }; + struct variable_replacer { + virtual ~variable_replacer() {} + + virtual bool is_variable (const std::string &str) const + { + return !str.empty (); + } + + virtual std::string replace (const std::string &var) const = 0; + }; + // We grab ownership if get non-const ucl_object_t Ucl(ucl_object_t *other) { obj.reset (other); @@ -211,20 +287,20 @@ public: obj.reset (ucl_object_fromstring_common (value.data (), value.size (), UCL_STRING_RAW)); } - Ucl(const char * value) { + Ucl(const char *value) { obj.reset (ucl_object_fromstring_common (value, 0, UCL_STRING_RAW)); } // Implicit constructor: anything with a to_json() function. template - Ucl(const T & t) : Ucl(t.to_ucl()) {} + Ucl(const T &t) : Ucl(t.to_ucl()) {} // Implicit constructor: map-like objects (std::map, std::unordered_map, etc) template ::value && std::is_constructible::value, int>::type = 0> - Ucl(const M & m) { + Ucl(const M &m) { obj.reset (ucl_object_typed_new (UCL_OBJECT)); auto cobj = obj.get (); @@ -238,7 +314,7 @@ public: template ::value, int>::type = 0> - Ucl(const V & v) { + Ucl(const V &v) { obj.reset (ucl_object_typed_new (UCL_ARRAY)); auto cobj = obj.get (); @@ -356,46 +432,138 @@ public: return out; } - static Ucl parse (const std::string & in, std::string & err) + static Ucl parse (const std::string &in, std::string &err) { - auto parser = ucl_parser_new (UCL_PARSER_DEFAULT); + return parse (in, std::map(), err); + } - if (!ucl_parser_add_chunk (parser, (const unsigned char *)in.data (), - in.size ())) { - err.assign (ucl_parser_get_error (parser)); - ucl_parser_free (parser); + static Ucl parse (const std::string &in, const std::map &vars, std::string &err) + { + auto config_func = [&vars] (ucl_parser *parser) { + for (const auto & item : vars) { + ucl_parser_register_variable (parser, item.first.c_str (), item.second.c_str ()); + } + }; + + auto parse_func = [&in] (ucl_parser *parser) { + return ucl_parser_add_chunk (parser, (unsigned char *)in.data (), in.size ()); + }; + + return parse_with_strategy_function (config_func, parse_func, err); + } + static Ucl parse (const std::string &in, const variable_replacer &replacer, std::string &err) + { + auto config_func = [&replacer] (ucl_parser *parser) { + ucl_parser_set_variables_handler (parser, ucl_variable_replacer, + &const_cast(replacer)); + }; + + auto parse_func = [&in] (ucl_parser *parser) { + return ucl_parser_add_chunk (parser, (unsigned char *) in.data (), in.size ()); + }; + + return parse_with_strategy_function (config_func, parse_func, err); + } + + static Ucl parse (const char *in, std::string &err) + { + return parse (in, std::map(), err); + } + + static Ucl parse (const char *in, const std::map &vars, std::string &err) + { + if (!in) { + err = "null input"; return nullptr; } + return parse (std::string (in), vars, err); + } - auto obj = ucl_parser_get_object (parser); + static Ucl parse (const char *in, const variable_replacer &replacer, std::string &err) + { + if (!in) { + err = "null input"; + return nullptr; + } + return parse (std::string(in), replacer, err); + } + + static Ucl parse_from_file (const std::string &filename, std::string &err) + { + return parse_from_file (filename, std::map(), err); + } + + static Ucl parse_from_file (const std::string &filename, const std::map &vars, std::string &err) + { + auto config_func = [&vars] (ucl_parser *parser) { + for (const auto & item : vars) { + ucl_parser_register_variable (parser, item.first.c_str (), item.second.c_str ()); + } + }; + + auto parse_func = [&filename] (ucl_parser *parser) { + return ucl_parser_add_file (parser, filename.c_str ()); + }; + + return parse_with_strategy_function (config_func, parse_func, err); + } + + static Ucl parse_from_file (const std::string &filename, const variable_replacer &replacer, std::string &err) + { + auto config_func = [&replacer] (ucl_parser *parser) { + ucl_parser_set_variables_handler (parser, ucl_variable_replacer, + &const_cast(replacer)); + }; + + auto parse_func = [&filename] (ucl_parser *parser) { + return ucl_parser_add_file (parser, filename.c_str ()); + }; + + return parse_with_strategy_function (config_func, parse_func, err); + } + + static std::vector find_variable (const std::string &in) + { + auto parser = ucl_parser_new (UCL_PARSER_DEFAULT); + + std::set vars; + ucl_parser_set_variables_handler (parser, ucl_variable_getter, &vars); + ucl_parser_add_chunk (parser, (const unsigned char *)in.data (), in.size ()); ucl_parser_free (parser); - // Obj will handle ownership - return Ucl (obj); + std::vector result; + std::move (vars.begin (), vars.end (), std::back_inserter (result)); + return result; } - static Ucl parse (const char * in, std::string & err) + static std::vector find_variable (const char *in) { - if (in) { - return parse (std::string(in), err); - } else { - err = "null input"; - return nullptr; + if (!in) { + return std::vector(); } + return find_variable (std::string (in)); } - static Ucl parse (std::istream &ifs, std::string &err) + static std::vector find_variable_from_file (const std::string &filename) { - return Ucl::parse (std::string(std::istreambuf_iterator(ifs), - std::istreambuf_iterator()), err); + auto parser = ucl_parser_new (UCL_PARSER_DEFAULT); + + std::set vars; + ucl_parser_set_variables_handler (parser, ucl_variable_getter, &vars); + ucl_parser_add_file (parser, filename.c_str ()); + ucl_parser_free (parser); + + std::vector result; + std::move (vars.begin (), vars.end (), std::back_inserter (result)); + return std::move (result); } - Ucl& operator= (Ucl rhs) - { - obj.swap (rhs.obj); - return *this; - } + Ucl& operator= (Ucl rhs) + { + obj.swap (rhs.obj); + return *this; + } bool operator== (const Ucl &rhs) const { Modified: vendor/libucl/dist/include/ucl.h ============================================================================== --- vendor/libucl/dist/include/ucl.h Fri Sep 30 23:38:26 2016 (r306541) +++ vendor/libucl/dist/include/ucl.h Sat Oct 1 00:11:09 2016 (r306542) @@ -1016,7 +1016,6 @@ UCL_EXTERN bool ucl_parser_add_string_pr * Load and add data from a file * @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_file (struct ucl_parser *parser, @@ -1026,7 +1025,6 @@ UCL_EXTERN bool ucl_parser_add_file (str * Load and add data from a file * @param parser parser structure * @param filename the name of file - * @param err if *err is NULL it is set to parser error * @param priority the desired priority of a chunk (only 4 least significant bits * are considered for this parameter) * @return true if chunk has been added and false in case of error @@ -1035,6 +1033,20 @@ UCL_EXTERN bool ucl_parser_add_file_prio const char *filename, unsigned priority); /** + * Load and add data from a file + * @param parser parser structure + * @param filename the name of file + * @param priority the desired priority of a chunk (only 4 least significant bits + * are considered for this parameter) + * @param strat Merge strategy to use while parsing this file + * @param parse_type Parser type to use while parsing this file + * @return true if chunk has been added and false in case of error + */ +UCL_EXTERN bool ucl_parser_add_file_full (struct ucl_parser *parser, const char *filename, + unsigned priority, enum ucl_duplicate_strategy strat, + enum ucl_parse_type parse_type); + +/** * Load and add data from a file descriptor * @param parser parser structure * @param filename the name of file Added: vendor/libucl/dist/m4/gcov.m4 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ vendor/libucl/dist/m4/gcov.m4 Sat Oct 1 00:11:09 2016 (r306542) @@ -0,0 +1,89 @@ +# SYNOPSIS +# +# Add code coverage support with gcov/lcov. +# +# AX_CODE_COVERAGE() +# +# DESCRIPTION +# +# Provides a --enable-coverage option which checks for available +# gcov/lcov binaries and provides ENABLE_CODE_COVERAGE conditional. +# +# LAST MODIFICATION +# +# $Id: coverage.m4 40881 2013-08-20 17:54:39Z damon $ +# +# COPYLEFT +# +# Copyright (c) 2012 Roy H. Stogner +# Copyright (c) 2010 Karl W. Schulz +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. + +AC_DEFUN([AX_CODE_COVERAGE], +[ + +AC_ARG_ENABLE(coverage, AC_HELP_STRING([--enable-coverage],[configure code coverage analysis tools])) + +HAVE_GCOV_TOOLS=0 + +GCOV_FLAGS="" + +if test "x$enable_coverage" = "xyes"; then + + # ---------------------------- + # Check for gcov/lcov binaries + # ---------------------------- + + AC_ARG_VAR([GCOV], [Coverage testing command]) + if test "x$GCOV" = "x"; then + AC_PATH_PROG(GCOV, gcov, no) + else + AC_PATH_PROG(GCOV, $GCOV, no) + fi + + AC_PATH_PROG(LCOV, lcov, no) + AC_PATH_PROG(GENHTML, genhtml) + + # ---------------------------------- + # include coverage compiler options + # ---------------------------------- + AC_MSG_CHECKING([for clang]) + + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([], [[ + #ifndef __clang__ + not clang + #endif + ]])], + [CLANG=yes], [CLANG=no]) + + AC_MSG_RESULT([$CLANG]) + HAVE_GCOV_TOOLS=1 + COVERAGE_CFLAGS="-fprofile-arcs -ftest-coverage" + COVERAGE_LDFLAGS="--coverage -fprofile-arcs -ftest-coverage" + COVERAGE_OPTFLAGS="-O0" + + # Test for C... + CFLAGS="${GCOV_FLAGS} ${CFLAGS}" + CXXFLAGS="${GCOV_FLAGS} ${CXXFLAGS}" + if test "x$GCC" = "xyes" -a "x$CLANG" = "xno"; then + COVERAGE_LIBS="-lgcov" + else + COVERAGE_LIBS="" + fi +fi + +AC_SUBST([GCOV]) +AC_SUBST([LCOV]) +AC_SUBST([GENHTML]) +AC_SUBST([GENHTML_OPTIONS]) +AC_SUBST([COVERAGE_CFLAGS]) +AC_SUBST([COVERAGE_OPTFLAGS]) +AC_SUBST([COVERAGE_LDFLAGS]) +AC_SUBST([COVERAGE_LIBS]) +AM_CONDITIONAL(CODE_COVERAGE_ENABLED,test x$HAVE_GCOV_TOOLS = x1) + +]) Modified: vendor/libucl/dist/python/setup.py ============================================================================== --- vendor/libucl/dist/python/setup.py Fri Sep 30 23:38:26 2016 (r306541) +++ vendor/libucl/dist/python/setup.py Sat Oct 1 00:11:09 2016 (r306542) @@ -1,37 +1,43 @@ -import distutils.ccompiler -import distutils.sysconfig -from distutils.core import setup, Extension +try: + from setuptools import setup, Extension +except ImportError: + from distutils.core import setup, Extension + import os +import sys +tests_require = [] -compiler = distutils.ccompiler.new_compiler() -search_paths=[os.path.expanduser('~/{}'), '/opt/local/{}', '/usr/local/{}', '/usr/{}'] -lib_paths = [ a.format("lib") for a in search_paths] -inc_paths = [ a.format("include") for a in search_paths] +if sys.version < '2.7': + tests_require.append('unittest2') -uclmodule = Extension('ucl', - include_dirs = inc_paths, - library_dirs = lib_paths, - libraries = ['ucl'], - sources = ['src/uclmodule.c'], - runtime_library_dirs = lib_paths, - language='c') +uclmodule = Extension( + 'ucl', + libraries = ['ucl'], + sources = ['src/uclmodule.c'], + language = 'c' +) -setup(name='ucl', - version='1.0', - description='ucl parser and emmitter', +setup( + name = 'ucl', + version = '0.8', + description = 'ucl parser and emmitter', ext_modules = [uclmodule], - author="Eitan Adler", - author_email="lists@eitanadler.com", - url="https://github.com/vstakhov/libucl/", - license="MIT", - classifiers=["Development Status :: 3 - Alpha", + test_suite = 'tests', + tests_require = tests_require, + author = "Eitan Adler, Denis Volpato Martins", + author_email = "lists@eitanadler.com", + url = "https://github.com/vstakhov/libucl/", + license = "MIT", + classifiers = [ + "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: DFSG approved", "License :: OSI Approved :: MIT License", "Programming Language :: C", + "Programming Language :: Python :: 2", "Programming Language :: Python :: 3", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Software Development :: Libraries", - ] - ) + ] +) Modified: vendor/libucl/dist/python/src/uclmodule.c ============================================================================== --- vendor/libucl/dist/python/src/uclmodule.c Fri Sep 30 23:38:26 2016 (r306541) +++ vendor/libucl/dist/python/src/uclmodule.c Sat Oct 1 00:11:09 2016 (r306542) @@ -2,6 +2,8 @@ #include #include +static PyObject *SchemaError; + static PyObject * _basic_ucl_type (ucl_object_t const *obj) { @@ -13,9 +15,11 @@ _basic_ucl_type (ucl_object_t const *obj case UCL_STRING: return Py_BuildValue ("s", ucl_object_tostring (obj)); case UCL_BOOLEAN: - return ucl_object_toboolean (obj) ? Py_True : Py_False; + return PyBool_FromLong (ucl_object_toboolean (obj)); case UCL_TIME: return Py_BuildValue ("d", ucl_object_todouble (obj)); + case UCL_NULL: + Py_RETURN_NONE; } return NULL; } @@ -124,26 +128,60 @@ _iterate_python (PyObject *obj) { if (obj == Py_None) { return ucl_object_new(); - } else if (PyBool_Check (obj)) { + } + else if (PyBool_Check (obj)) { return ucl_object_frombool (obj == Py_True); - } else if (PyInt_Check (obj)) { + } +#if PY_MAJOR_VERSION < 3 + else if (PyInt_Check (obj)) { return ucl_object_fromint (PyInt_AsLong (obj)); - } else if (PyFloat_Check (obj)) { + } +#endif + else if (PyLong_Check (obj)) { + return ucl_object_fromint (PyLong_AsLong (obj)); + } + else if (PyFloat_Check (obj)) { return ucl_object_fromdouble (PyFloat_AsDouble (obj)); - } else if (PyString_Check (obj)) { + } + else if (PyUnicode_Check (obj)) { + ucl_object_t *ucl_str; + PyObject *str = PyUnicode_AsASCIIString(obj); + ucl_str = ucl_object_fromstring (PyBytes_AsString (str)); + Py_DECREF(str); + return ucl_str; + } +#if PY_MAJOR_VERSION < 3 + else if (PyString_Check (obj)) { return ucl_object_fromstring (PyString_AsString (obj)); - // } else if (PyDateTime_Check (obj)) { } +#endif else if (PyDict_Check(obj)) { PyObject *key, *value; Py_ssize_t pos = 0; ucl_object_t *top, *elm; + char *keystr = NULL; top = ucl_object_typed_new (UCL_OBJECT); while (PyDict_Next(obj, &pos, &key, &value)) { elm = _iterate_python(value); - ucl_object_insert_key (top, elm, PyString_AsString(key), 0, true); + + if (PyUnicode_Check(key)) { + PyObject *keyascii = PyUnicode_AsASCIIString(key); + keystr = PyBytes_AsString(keyascii); + Py_DECREF(keyascii); + } +#if PY_MAJOR_VERSION < 3 + else if (PyString_Check(key)) { + keystr = PyString_AsString(key); + } +#endif + else { + PyErr_SetString(PyExc_TypeError, "Unknown key type"); + return NULL; + } + + ucl_object_insert_key (top, elm, keystr, 0, true); } return top; @@ -195,11 +233,6 @@ ucl_dump (PyObject *self, PyObject *args Py_RETURN_NONE; } - if (!PyDict_Check(obj)) { - PyErr_SetString(PyExc_TypeError, "Argument must be dict"); - return NULL; - } - root = _iterate_python(obj); if (root) { PyObject *ret; @@ -207,7 +240,11 @@ ucl_dump (PyObject *self, PyObject *args buf = (char *) ucl_object_emit (root, emitter); ucl_object_unref (root); +#if PY_MAJOR_VERSION < 3 ret = PyString_FromString (buf); +#else + ret = PyUnicode_FromString (buf); +#endif free(buf); return ret; @@ -219,17 +256,35 @@ ucl_dump (PyObject *self, PyObject *args static PyObject * ucl_validate (PyObject *self, PyObject *args) { - char *uclstr, *schema; + PyObject *dataobj, *schemaobj; + ucl_object_t *data, *schema; + bool r; + struct ucl_schema_error err; - if (PyArg_ParseTuple(args, "zz", &uclstr, &schema)) { - if (!uclstr || !schema) { - Py_RETURN_NONE; - } + if (!PyArg_ParseTuple (args, "OO", &schemaobj, &dataobj)) { + PyErr_SetString (PyExc_TypeError, "Unhandled object type"); + return NULL; + } - PyErr_SetString(PyExc_NotImplementedError, "schema validation is not yet supported"); + schema = _iterate_python(schemaobj); + if (!schema) + return NULL; + + data = _iterate_python(dataobj); + if (!data) + return NULL; + + // validation + r = ucl_object_validate (schema, data, &err); + ucl_object_unref (schema); + ucl_object_unref (data); + + if (!r) { + PyErr_SetString (SchemaError, err.msg); + return NULL; } - return NULL; + Py_RETURN_TRUE; } static PyMethodDef uclMethods[] = { @@ -247,6 +302,10 @@ init_macros(PyObject *mod) PyModule_AddIntMacro(mod, UCL_EMIT_CONFIG); PyModule_AddIntMacro(mod, UCL_EMIT_YAML); PyModule_AddIntMacro(mod, UCL_EMIT_MSGPACK); + + SchemaError = PyErr_NewException("ucl.SchemaError", NULL, NULL); + Py_INCREF(SchemaError); + PyModule_AddObject(mod, "SchemaError", SchemaError); } #if PY_MAJOR_VERSION >= 3 Added: vendor/libucl/dist/python/tests/__init__.py ============================================================================== Added: vendor/libucl/dist/python/tests/compat.py ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ vendor/libucl/dist/python/tests/compat.py Sat Oct 1 00:11:09 2016 (r306542) @@ -0,0 +1,8 @@ +try: + import unittest2 as unittest +except ImportError: *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***