Import libucl 0.9.3

This commit is contained in:
Muhammad Moinur Rahman 2026-01-07 19:19:44 +01:00
parent 1e2f270469
commit 1dd83cf7e5
40 changed files with 4977 additions and 4770 deletions

67
.clang-format Normal file
View file

@ -0,0 +1,67 @@
# Generated from CLion C/C++ Code Style settings
BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: None
AlignOperands: Align
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: Always
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterReturnType: None
AlwaysBreakTemplateDeclarations: Yes
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterUnion: false
BeforeCatch: false
BeforeElse: true
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
ColumnLimit: 0
CompactNamespaces: false
ContinuationIndentWidth: 4
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 4
KeepEmptyLinesAtTheStartOfBlocks: true
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PointerAlignment: Right
ReflowComments: false
SortIncludes: Never
SpaceAfterCStyleCast: true
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 0
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
TabWidth: 4
UseTab: ForContinuationAndIndentation

View file

@ -72,4 +72,4 @@ jobs:
working-directory: ${{ steps.strings.outputs.build-output-dir }}
# Execute tests defined by the CMake configuration. Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator).
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest --build-config ${{ matrix.build_type }}
run: ctest --progress --output-on-failure --build-config ${{ matrix.build_type }}

View file

@ -1,9 +1,9 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.1.0 FATAL_ERROR)
CMAKE_MINIMUM_REQUIRED(VERSION 3.5.0 FATAL_ERROR)
PROJECT(libucl C)
SET(LIBUCL_VERSION_MAJOR 0)
SET(LIBUCL_VERSION_MINOR 9)
SET(LIBUCL_VERSION_PATCH 2)
SET(LIBUCL_VERSION_PATCH 3)
SET(LIBUCL_VERSION
"${LIBUCL_VERSION_MAJOR}.${LIBUCL_VERSION_MINOR}.${LIBUCL_VERSION_PATCH}")
@ -19,6 +19,9 @@ OPTION(BUILD_SHARED_LIBS "Build Shared Libraries [default: OFF]" OFF)
OPTION(ENABLE_LUA "Enable lua support [default: OFF]" OFF)
OPTION(ENABLE_LUAJIT "Enable luajit support [default: OFF]" OFF)
OPTION(ENABLE_UTILS "Enable building utility binaries [default: OFF]" OFF)
OPTION(ENABLE_SANITIZERS "Enable sanitizers (address, undefined, etc.) [default: OFF]" OFF)
SET(SANITIZE_TYPE "address" CACHE STRING "Type of sanitizer to use (address, thread, undefined, memory, leak)")
SET_PROPERTY(CACHE SANITIZE_TYPE PROPERTY STRINGS address thread undefined memory leak)
# Find lua installation
MACRO(FindLua)
@ -195,6 +198,23 @@ ENDIF(SUPPORT_WUNUSED_PARAMETER)
SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_WARN_FLAGS}" )
IF(ENABLE_SANITIZERS MATCHES "ON")
SET(SANITIZE_FLAGS "-fsanitize=${SANITIZE_TYPE} -fno-omit-frame-pointer -fno-optimize-sibling-calls")
SET(CMAKE_REQUIRED_FLAGS "${SANITIZE_FLAGS}")
SET(CMAKE_REQUIRED_LIBRARIES "${SANITIZE_FLAGS}")
CHECK_C_SOURCE_COMPILES("int main() { return 0; }" COMPILER_SUPPORTS_SANITIZE)
UNSET(CMAKE_REQUIRED_FLAGS)
UNSET(CMAKE_REQUIRED_LIBRARIES)
IF(COMPILER_SUPPORTS_SANITIZE)
MESSAGE(STATUS "Enabling sanitizer: ${SANITIZE_TYPE}")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZE_FLAGS}")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SANITIZE_FLAGS}")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${SANITIZE_FLAGS}")
ELSE()
MESSAGE(WARNING "Compiler does not support -fsanitize=${SANITIZE_TYPE}")
ENDIF()
ENDIF()
IF(ENABLE_URL_SIGN MATCHES "ON")
IF(OPENSSL_FOUND)
SET(HAVE_OPENSSL 1)
@ -258,10 +278,12 @@ IF(ENABLE_LUA MATCHES "ON")
INCLUDE_DIRECTORIES("${LUA_INCLUDE_DIR}")
ENDIF(NOT LUA_FOUND)
ELSE(ENABLE_LUAJIT MATCHES "ON")
FindLua(VERSION_MAJOR "5" VERSION_MINOR "2" ROOT "${LUA_ROOT}")
IF(NOT LUA_FOUND)
FindLua(VERSION_MAJOR "5" VERSION_MINOR "1" ROOT "${LUA_ROOT}")
ENDIF(NOT LUA_FOUND)
FOREACH(LUA_MINOR RANGE 4 1 -1)
FindLua(VERSION_MAJOR "5" VERSION_MINOR ${LUA_MINOR} ROOT "${LUA_ROOT}")
IF(LUA_FOUND)
BREAK()
ENDIF(LUA_FOUND)
ENDFOREACH(LUA_MINOR RANGE 4 1 -1)
IF(NOT LUA_FOUND)
MESSAGE(FATAL_ERROR "Lua not found, lua support is required")
ELSE(NOT LUA_FOUND)
@ -309,6 +331,9 @@ SET_TARGET_PROPERTIES(ucl PROPERTIES
INSTALL(TARGETS ucl EXPORT uclConfig DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
ENABLE_TESTING()
ADD_SUBDIRECTORY(tests)
IF(ENABLE_UTILS MATCHES "ON")
ADD_SUBDIRECTORY(utils)
ENDIF()

View file

@ -1,5 +1,15 @@
# Version history
## Libucl 0.9.3
- Fix invalid JSON emission when merging objects (Fixes #312)
- Fix heap-buffer-overflow in ucl_maybe_parse_number (Fixes #344, #328)
- Fix Use-After-Free in ucl_hash_insert by ignoring duplicates in different containers (Fixes #347)
- Fix heap-buffer-overflow in ucl_parse_multiline_string
- Add support of sanitizers to cmake
- Fix allocator mismatches in libucl
- Various other fixes and improvements
## Libucl 0.9.0
* 803b588 Breaking: Try to fix streamline embedding

View file

@ -1,12 +1,14 @@
m4_define([maj_ver], [0])
m4_define([med_ver], [9])
m4_define([min_ver], [2])
m4_define([so_version], [9:0:2])
m4_define([min_ver], [3])
m4_define([so_version], [9:0:3])
m4_define([ucl_version], [maj_ver.med_ver.min_ver])
AC_PREREQ([2.70])
AC_INIT([libucl],[ucl_version],[https://github.com/vstakhov/libucl],[libucl])
AC_CONFIG_SRCDIR([configure.ac])
AM_INIT_AUTOMAKE([1.11 foreign -Wall -Wportability no-dist-gzip dist-xz])
AM_INIT_AUTOMAKE([foreign -Wall -Wportability no-dist-gzip dist-xz 1.14])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
UCL_VERSION=ucl_version
@ -15,8 +17,7 @@ SO_VERSION=so_version
AC_SUBST(UCL_VERSION)
AC_SUBST(SO_VERSION)
AC_PROG_CC_C99
AM_PROG_CC_C_O
AC_PROG_CC
AM_PROG_AR
LT_INIT
AC_CONFIG_MACRO_DIR([m4])

View file

@ -44,7 +44,7 @@ struct ucl_lua_funcdata {
/**
* Initialize lua UCL API
*/
UCL_EXTERN int luaopen_ucl (lua_State *L);
UCL_EXTERN int luaopen_ucl(lua_State *L);
/**
* Import UCL object from lua state
@ -52,7 +52,7 @@ UCL_EXTERN int luaopen_ucl (lua_State *L);
* @param idx index of object at the lua stack to convert to UCL
* @return new UCL object or NULL, the caller should unref object after using
*/
UCL_EXTERN ucl_object_t* ucl_object_lua_import (lua_State *L, int idx);
UCL_EXTERN ucl_object_t *ucl_object_lua_import(lua_State *L, int idx);
/**
* Import UCL object from lua state, escaping JSON strings
@ -60,7 +60,7 @@ UCL_EXTERN ucl_object_t* ucl_object_lua_import (lua_State *L, int idx);
* @param idx index of object at the lua stack to convert to UCL
* @return new UCL object or NULL, the caller should unref object after using
*/
UCL_EXTERN ucl_object_t* ucl_object_lua_import_escape (lua_State *L, int idx);
UCL_EXTERN ucl_object_t *ucl_object_lua_import_escape(lua_State *L, int idx);
/**
* Push an object to lua
@ -68,18 +68,18 @@ UCL_EXTERN ucl_object_t* ucl_object_lua_import_escape (lua_State *L, int idx);
* @param obj object to push
* @param allow_array traverse over implicit arrays
*/
UCL_EXTERN int ucl_object_push_lua (lua_State *L,
const ucl_object_t *obj, bool allow_array);
UCL_EXTERN int ucl_object_push_lua(lua_State *L,
const ucl_object_t *obj, bool allow_array);
/**
* Push an object to lua replacing all ucl.null with `false`
* @param L lua state
* @param obj object to push
* @param allow_array traverse over implicit arrays
*/
UCL_EXTERN int ucl_object_push_lua_filter_nil (lua_State *L,
const ucl_object_t *obj,
bool allow_array);
UCL_EXTERN int ucl_object_push_lua_filter_nil(lua_State *L,
const ucl_object_t *obj,
bool allow_array);
UCL_EXTERN struct ucl_lua_funcdata* ucl_object_toclosure (const ucl_object_t *obj);
UCL_EXTERN struct ucl_lua_funcdata *ucl_object_toclosure(const ucl_object_t *obj);
#endif /* LUA_UCL_H_ */

View file

@ -37,57 +37,57 @@
namespace ucl {
struct ucl_map_construct_t { };
struct ucl_map_construct_t {};
constexpr ucl_map_construct_t ucl_map_construct = ucl_map_construct_t();
struct ucl_array_construct_t { };
struct ucl_array_construct_t {};
constexpr ucl_array_construct_t ucl_array_construct = ucl_array_construct_t();
class Ucl final {
private:
struct ucl_deleter {
void operator() (ucl_object_t *obj) {
ucl_object_unref (obj);
void operator()(ucl_object_t *obj)
{
ucl_object_unref(obj);
}
};
static int
append_char (unsigned char c, size_t nchars, void *ud)
append_char(unsigned char c, size_t nchars, void *ud)
{
std::string *out = reinterpret_cast<std::string *>(ud);
out->append (nchars, (char)c);
out->append(nchars, (char) c);
return nchars;
}
static int
append_len (unsigned const char *str, size_t len, void *ud)
append_len(unsigned const char *str, size_t len, void *ud)
{
std::string *out = reinterpret_cast<std::string *>(ud);
out->append ((const char *)str, len);
out->append((const char *) str, len);
return len;
}
static int
append_int (int64_t elt, void *ud)
append_int(int64_t elt, void *ud)
{
std::string *out = reinterpret_cast<std::string *>(ud);
auto nstr = std::to_string (elt);
auto nstr = std::to_string(elt);
out->append (nstr);
out->append(nstr);
return nstr.size ();
return nstr.size();
}
static int
append_double (double elt, void *ud)
append_double(double elt, void *ud)
{
std::string *out = reinterpret_cast<std::string *>(ud);
auto nstr = std::to_string (elt);
auto nstr = std::to_string(elt);
out->append (nstr);
out->append(nstr);
return nstr.size ();
return nstr.size();
}
static struct ucl_emitter_functions default_emit_funcs()
@ -98,26 +98,25 @@ private:
Ucl::append_int,
Ucl::append_double,
nullptr,
nullptr
};
nullptr};
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)
unsigned char ** /*replace*/, size_t * /*replace_len*/, bool *need_free, void *ud)
{
*need_free = false;
auto vars = reinterpret_cast<std::set<std::string> *>(ud);
if (vars && data && len != 0) {
vars->emplace (data, data + len);
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)
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;
@ -126,89 +125,96 @@ private:
return false;
}
std::string var_name (data, data + len);
if (!replacer->is_variable (var_name)) {
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 ()) {
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 = (unsigned char *) UCL_ALLOC(var_value.size());
memcpy(*replace, var_value.data(), var_value.size());
*replace_len = var_value.size ();
*replace_len = var_value.size();
*need_free = true;
return true;
}
template <typename C, typename P>
static Ucl parse_with_strategy_function (C config_func, P parse_func, std::string &err)
template<typename C, typename P>
static Ucl parse_with_strategy_function(C config_func, P parse_func, std::string &err)
{
auto parser = ucl_parser_new (UCL_PARSER_DEFAULT);
auto parser = ucl_parser_new(UCL_PARSER_DEFAULT);
config_func (parser);
config_func(parser);
if (!parse_func (parser)) {
const char *error = ucl_parser_get_error (parser); //Assigning here without checking result first causes a
if( error != NULL ) err.assign(error); // crash if ucl_parser_get_error returns NULL
ucl_parser_free (parser);
if (!parse_func(parser)) {
const char *error = ucl_parser_get_error(parser);//Assigning here without checking result first causes a
if (error != NULL) err.assign(error); // crash if ucl_parser_get_error returns NULL
ucl_parser_free(parser);
return nullptr;
}
auto obj = ucl_parser_get_object (parser);
ucl_parser_free (parser);
auto obj = ucl_parser_get_object(parser);
ucl_parser_free(parser);
// Obj will handle ownership
return Ucl (obj);
return Ucl(obj);
}
std::unique_ptr<ucl_object_t, ucl_deleter> obj;
public:
struct macro_handler_s {
ucl_macro_handler handler;
ucl_macro_handler handler;
ucl_context_macro_handler ctx_handler;
};
struct macro_userdata_s {
ucl_parser *parser;
void *userdata;
ucl_parser *parser;
void *userdata;
};
class const_iterator {
private:
struct ucl_iter_deleter {
void operator() (ucl_object_iter_t it) {
ucl_object_iterate_free (it);
void operator()(ucl_object_iter_t it)
{
ucl_object_iterate_free(it);
}
};
std::shared_ptr<void> it;
std::unique_ptr<Ucl> cur;
public:
typedef std::forward_iterator_tag iterator_category;
const_iterator(const Ucl &obj) {
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)));
const_iterator(const Ucl &obj)
{
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->obj) {
it.reset ();
cur.reset ();
it.reset();
cur.reset();
}
}
const_iterator() {}
const_iterator()
{
}
const_iterator(const const_iterator &other) = delete;
const_iterator(const_iterator &&other) = default;
~const_iterator() {}
~const_iterator()
{
}
const_iterator& operator=(const const_iterator &other) = delete;
const_iterator& operator=(const_iterator &&other) = default;
const_iterator &operator=(const const_iterator &other) = delete;
const_iterator &operator=(const_iterator &&other) = default;
bool operator==(const const_iterator &other) const
{
@ -224,135 +230,154 @@ public:
return !(*this == other);
}
const_iterator& operator++()
const_iterator &operator++()
{
if (it) {
cur.reset (new Ucl(ucl_object_iterate_safe (it.get(), true)));
cur.reset(new Ucl(ucl_object_iterate_safe(it.get(), true)));
}
if (cur && !cur->obj) {
it.reset ();
cur.reset ();
it.reset();
cur.reset();
}
return *this;
}
const Ucl& operator*() const
const Ucl &operator*() const
{
return *cur;
}
const Ucl* operator->() const
const Ucl *operator->() const
{
return cur.get();
}
};
struct variable_replacer {
virtual ~variable_replacer() {}
virtual bool is_variable (const std::string &str) const
virtual ~variable_replacer()
{
return !str.empty ();
}
virtual std::string replace (const std::string &var) const = 0;
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);
Ucl(ucl_object_t *other)
{
obj.reset(other);
}
// Shared ownership
Ucl(const ucl_object_t *other) {
obj.reset (ucl_object_ref (other));
Ucl(const ucl_object_t *other)
{
obj.reset(ucl_object_ref(other));
}
Ucl(const Ucl &other) {
obj.reset (ucl_object_ref (other.obj.get()));
Ucl(const Ucl &other)
{
obj.reset(ucl_object_ref(other.obj.get()));
}
Ucl(Ucl &&other) {
obj.swap (other.obj);
Ucl(Ucl &&other)
{
obj.swap(other.obj);
}
Ucl() noexcept {
obj.reset (ucl_object_typed_new (UCL_NULL));
Ucl() noexcept
{
obj.reset(ucl_object_typed_new(UCL_NULL));
}
Ucl(std::nullptr_t) noexcept {
obj.reset (ucl_object_typed_new (UCL_NULL));
Ucl(std::nullptr_t) noexcept
{
obj.reset(ucl_object_typed_new(UCL_NULL));
}
Ucl(double value) {
obj.reset (ucl_object_typed_new (UCL_FLOAT));
Ucl(double value)
{
obj.reset(ucl_object_typed_new(UCL_FLOAT));
obj->value.dv = value;
}
Ucl(int64_t value) {
obj.reset (ucl_object_typed_new (UCL_INT));
Ucl(int64_t value)
{
obj.reset(ucl_object_typed_new(UCL_INT));
obj->value.iv = value;
}
Ucl(bool value) {
obj.reset (ucl_object_typed_new (UCL_BOOLEAN));
Ucl(bool value)
{
obj.reset(ucl_object_typed_new(UCL_BOOLEAN));
obj->value.iv = static_cast<int64_t>(value);
}
Ucl(const std::string &value) {
obj.reset (ucl_object_fromstring_common (value.data (), value.size (),
UCL_STRING_RAW));
Ucl(const std::string &value)
{
obj.reset(ucl_object_fromstring_common(value.data(), value.size(),
UCL_STRING_RAW));
}
Ucl(const char *value) {
obj.reset (ucl_object_fromstring_common (value, 0, UCL_STRING_RAW));
Ucl(const char *value)
{
obj.reset(ucl_object_fromstring_common(value, 0, UCL_STRING_RAW));
}
// Implicit constructor: anything with a to_json() function.
template <class T, class = decltype(&T::to_ucl)>
Ucl(const T &t) : Ucl(t.to_ucl()) {}
template<class T, class = decltype(&T::to_ucl)>
Ucl(const T &t)
: Ucl(t.to_ucl())
{
}
// Implicit constructor: map-like objects (std::map, std::unordered_map, etc)
template <class M, typename std::enable_if<
std::is_constructible<std::string, typename M::key_type>::value
&& std::is_constructible<Ucl, typename M::mapped_type>::value,
int>::type = 0>
Ucl(const M &m) {
obj.reset (ucl_object_typed_new (UCL_OBJECT));
auto cobj = obj.get ();
template<class M, typename std::enable_if<
std::is_constructible<std::string, typename M::key_type>::value && std::is_constructible<Ucl, typename M::mapped_type>::value,
int>::type = 0>
Ucl(const M &m)
{
obj.reset(ucl_object_typed_new(UCL_OBJECT));
auto cobj = obj.get();
for (const auto &e : m) {
ucl_object_insert_key (cobj, ucl_object_ref (e.second.obj.get()),
e.first.data (), e.first.size (), true);
for (const auto &e: m) {
ucl_object_insert_key(cobj, ucl_object_ref(e.second.obj.get()),
e.first.data(), e.first.size(), true);
}
}
// Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc)
template <class V, typename std::enable_if<
std::is_constructible<Ucl, typename V::value_type>::value,
int>::type = 0>
Ucl(const V &v) {
obj.reset (ucl_object_typed_new (UCL_ARRAY));
auto cobj = obj.get ();
template<class V, typename std::enable_if<
std::is_constructible<Ucl, typename V::value_type>::value,
int>::type = 0>
Ucl(const V &v)
{
obj.reset(ucl_object_typed_new(UCL_ARRAY));
auto cobj = obj.get();
for (const auto &e : v) {
ucl_array_append (cobj, ucl_object_ref (e.obj.get()));
for (const auto &e: v) {
ucl_array_append(cobj, ucl_object_ref(e.obj.get()));
}
}
ucl_type_t type () const {
ucl_type_t type() const
{
if (obj) {
return ucl_object_type (obj.get ());
return ucl_object_type(obj.get());
}
return UCL_NULL;
}
std::string key () const {
std::string key() const
{
std::string res;
if (obj->key) {
res.assign (obj->key, obj->keylen);
res.assign(obj->key, obj->keylen);
}
return res;
}
double number_value (const double default_val = 0.0) const
double number_value(const double default_val = 0.0) const
{
double res;
@ -363,7 +388,7 @@ public:
return default_val;
}
int64_t int_value (const int64_t default_val = 0) const
int64_t int_value(const int64_t default_val = 0) const
{
int64_t res;
@ -374,7 +399,7 @@ public:
return default_val;
}
bool bool_value (const bool default_val = false) const
bool bool_value(const bool default_val = false) const
{
bool res;
@ -385,9 +410,9 @@ public:
return default_val;
}
std::string string_value (const std::string& default_val = "") const
std::string string_value(const std::string &default_val = "") const
{
const char* res = nullptr;
const char *res = nullptr;
if (ucl_object_tostring_safe(obj.get(), &res)) {
return res;
@ -396,35 +421,40 @@ public:
return default_val;
}
size_t size () const
std::string forced_string_value() const
{
if (type () == UCL_ARRAY) {
return ucl_array_size (obj.get());
return ucl_object_tostring_forced(obj.get());
}
size_t size() const
{
if (type() == UCL_ARRAY) {
return ucl_array_size(obj.get());
}
return 0;
}
Ucl at (size_t i) const
Ucl at(size_t i) const
{
if (type () == UCL_ARRAY) {
return Ucl (ucl_array_find_index (obj.get(), i));
if (type() == UCL_ARRAY) {
return Ucl(ucl_array_find_index(obj.get(), i));
}
return Ucl (nullptr);
return Ucl(nullptr);
}
Ucl lookup (const std::string &key) const
Ucl lookup(const std::string &key) const
{
if (type () == UCL_OBJECT) {
return Ucl (ucl_object_lookup_len (obj.get(),
key.data (), key.size ()));
if (type() == UCL_OBJECT) {
return Ucl(ucl_object_lookup_len(obj.get(),
key.data(), key.size()));
}
return Ucl (nullptr);
return Ucl(nullptr);
}
inline Ucl operator[] (size_t i) const
inline Ucl operator[](size_t i) const
{
return at(i);
}
@ -434,285 +464,297 @@ public:
return lookup(key);
}
// Serialize.
void dump (std::string &out, ucl_emitter_t type = UCL_EMIT_JSON) const
void dump(std::string &out, ucl_emitter_t type = UCL_EMIT_JSON) const
{
struct ucl_emitter_functions cbdata;
cbdata = Ucl::default_emit_funcs();
cbdata.ud = reinterpret_cast<void *>(&out);
ucl_object_emit_full (obj.get(), type, &cbdata, nullptr);
ucl_object_emit_full(obj.get(), type, &cbdata, nullptr);
}
std::string dump (ucl_emitter_t type = UCL_EMIT_JSON) const
std::string dump(ucl_emitter_t type = UCL_EMIT_JSON) const
{
std::string out;
dump (out, type);
dump(out, type);
return out;
}
static Ucl parse (const std::string &in, std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
static Ucl parse(const std::string &in, std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
{
return parse (in, std::map<std::string, std::string>(), err, duplicate_strategy);
return parse(in, std::map<std::string, std::string>(), err, duplicate_strategy);
}
static Ucl parse (const std::string &in, const std::map<std::string, std::string> &vars,
std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
static Ucl parse(const std::string &in, const std::map<std::string, std::string> &vars,
std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
{
std::vector< std::tuple< std::string, macro_handler_s, void * > > emptyVector;
return parse ( in, vars, emptyVector, err, duplicate_strategy );
std::vector<std::tuple<std::string, macro_handler_s, void *>> emptyVector;
return parse(in, vars, emptyVector, err, duplicate_strategy);
}
//Macro handler will receive a macro_userdata_s as void *ud
static Ucl parse (const std::string &in,
std::vector< std::tuple< std::string /*name*/, macro_handler_s, void * /*userdata*/ > > &macros,
std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
static Ucl parse(const std::string &in,
std::vector<std::tuple<std::string /*name*/, macro_handler_s, void * /*userdata*/>> &macros,
std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
{
return parse (in, std::map<std::string, std::string>(), macros, err, duplicate_strategy);
return parse(in, std::map<std::string, std::string>(), macros, err, duplicate_strategy);
}
//Macro handler will receive a macro_userdata_s as void *ud
static Ucl parse (const std::string &in, const std::map<std::string, std::string> &vars,
std::vector< std::tuple< std::string /*name*/, macro_handler_s, void * /*userdata*/ > > &macros,
std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
static Ucl parse(const std::string &in, const std::map<std::string, std::string> &vars,
std::vector<std::tuple<std::string /*name*/, macro_handler_s, void * /*userdata*/>> &macros,
std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
{
//Preserve macro_userdata_s memory for later use in parse_with_strategy_function()
std::vector<macro_userdata_s> userdata_list;
userdata_list.reserve (macros.size());
auto config_func = [&userdata_list, &vars, &macros] (ucl_parser *parser) {
for (const auto & item : vars) {
ucl_parser_register_variable (parser, item.first.c_str (), item.second.c_str ());
userdata_list.reserve(macros.size());
auto config_func = [&userdata_list, &vars, &macros](ucl_parser *parser) {
for (const auto &item: vars) {
ucl_parser_register_variable(parser, item.first.c_str(), item.second.c_str());
}
for (auto & macro : macros) {
userdata_list.push_back ({parser, std::get<2>(macro)});
for (auto &macro: macros) {
userdata_list.push_back({parser, std::get<2>(macro)});
if (std::get<1>(macro).handler != NULL) {
ucl_parser_register_macro (parser,
std::get<0>(macro).c_str(),
std::get<1>(macro).handler,
reinterpret_cast<void*>(&userdata_list.back()));
ucl_parser_register_macro(parser,
std::get<0>(macro).c_str(),
std::get<1>(macro).handler,
reinterpret_cast<void *>(&userdata_list.back()));
}
else if (std::get<1>(macro).ctx_handler != NULL) {
ucl_parser_register_context_macro (parser,
std::get<0>(macro).c_str(),
std::get<1>(macro).ctx_handler,
reinterpret_cast<void*>(&userdata_list.back()));
ucl_parser_register_context_macro(parser,
std::get<0>(macro).c_str(),
std::get<1>(macro).ctx_handler,
reinterpret_cast<void *>(&userdata_list.back()));
}
}
};
auto parse_func = [&in, &duplicate_strategy] (struct ucl_parser *parser) -> bool {
return ucl_parser_add_chunk_full (parser,
(unsigned char *) in.data (),
in.size (),
(unsigned int)ucl_parser_get_default_priority (parser),
duplicate_strategy,
UCL_PARSE_UCL);
auto parse_func = [&in, &duplicate_strategy](struct ucl_parser *parser) -> bool {
return ucl_parser_add_chunk_full(parser,
(unsigned char *) in.data(),
in.size(),
(unsigned int) ucl_parser_get_default_priority(parser),
duplicate_strategy,
UCL_PARSE_UCL);
};
return parse_with_strategy_function (config_func, parse_func, err);
return parse_with_strategy_function(config_func, parse_func, err);
}
static Ucl parse (const std::string &in, const variable_replacer &replacer,
std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
static Ucl parse(const std::string &in, const variable_replacer &replacer,
std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
{
std::vector< std::tuple< std::string, macro_handler_s, void * > > emptyVector;
return parse ( in, replacer, emptyVector, err, duplicate_strategy );
std::vector<std::tuple<std::string, macro_handler_s, void *>> emptyVector;
return parse(in, replacer, emptyVector, err, duplicate_strategy);
}
//Macro handler will receive a macro_userdata_s as void *ud
static Ucl parse (const std::string &in, const variable_replacer &replacer,
std::vector< std::tuple< std::string /*name*/, macro_handler_s, void * /*userdata*/ > > &macros,
std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
static Ucl parse(const std::string &in, const variable_replacer &replacer,
std::vector<std::tuple<std::string /*name*/, macro_handler_s, void * /*userdata*/>> &macros,
std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
{
//Preserve macro_userdata_s memory for later use in parse_with_strategy_function()
std::vector<macro_userdata_s> userdata_list;
userdata_list.reserve (macros.size());
auto config_func = [&userdata_list, &replacer, &macros] (ucl_parser *parser) {
ucl_parser_set_variables_handler (parser, ucl_variable_replacer, &const_cast<variable_replacer &>(replacer));
for (auto & macro : macros) {
userdata_list.push_back ({parser, std::get<2>(macro)});
userdata_list.reserve(macros.size());
auto config_func = [&userdata_list, &replacer, &macros](ucl_parser *parser) {
ucl_parser_set_variables_handler(parser, ucl_variable_replacer, &const_cast<variable_replacer &>(replacer));
for (auto &macro: macros) {
userdata_list.push_back({parser, std::get<2>(macro)});
if (std::get<1>(macro).handler != NULL) {
ucl_parser_register_macro (parser,
std::get<0>(macro).c_str(),
std::get<1>(macro).handler,
reinterpret_cast<void*>(&userdata_list.back()));
ucl_parser_register_macro(parser,
std::get<0>(macro).c_str(),
std::get<1>(macro).handler,
reinterpret_cast<void *>(&userdata_list.back()));
}
else if (std::get<1>(macro).ctx_handler != NULL) {
ucl_parser_register_context_macro (parser,
std::get<0>(macro).c_str(),
std::get<1>(macro).ctx_handler,
reinterpret_cast<void*>(&userdata_list.back()));
ucl_parser_register_context_macro(parser,
std::get<0>(macro).c_str(),
std::get<1>(macro).ctx_handler,
reinterpret_cast<void *>(&userdata_list.back()));
}
}
};
auto parse_func = [&in, &duplicate_strategy] (struct ucl_parser *parser) -> bool {
return ucl_parser_add_chunk_full (parser,
(unsigned char *) in.data (),
in.size (),
(unsigned int)ucl_parser_get_default_priority (parser),
duplicate_strategy,
UCL_PARSE_UCL);
auto parse_func = [&in, &duplicate_strategy](struct ucl_parser *parser) -> bool {
return ucl_parser_add_chunk_full(parser,
(unsigned char *) in.data(),
in.size(),
(unsigned int) ucl_parser_get_default_priority(parser),
duplicate_strategy,
UCL_PARSE_UCL);
};
return parse_with_strategy_function (config_func, parse_func, err);
return parse_with_strategy_function(config_func, parse_func, err);
}
static Ucl parse (const char *in, std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
static Ucl parse(const char *in, std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
{
return parse (in, std::map<std::string, std::string>(), err, duplicate_strategy);
return parse(in, std::map<std::string, std::string>(), err, duplicate_strategy);
}
static Ucl parse (const char *in, const std::map<std::string, std::string> &vars, std::string &err)
static Ucl parse(const char *in, const std::map<std::string, std::string> &vars, std::string &err)
{
if (!in) {
err = "null input";
return nullptr;
}
return parse (std::string (in), vars, err);
return parse(std::string(in), vars, err);
}
//Macro handler will receive a macro_userdata_s as void *ud
static Ucl parse (const char *in,
std::vector< std::tuple< std::string /*name*/, macro_handler_s, void * /*userdata*/ > > &macros,
std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
static Ucl parse(const char *in,
std::vector<std::tuple<std::string /*name*/, macro_handler_s, void * /*userdata*/>> &macros,
std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
{
return parse (in, std::map<std::string, std::string>(), macros, err, duplicate_strategy);
return parse(in, std::map<std::string, std::string>(), macros, err, duplicate_strategy);
}
//Macro handler will receive a macro_userdata_s as void *ud
static Ucl parse (const char *in, const std::map<std::string, std::string> &vars,
std::vector< std::tuple< std::string /*name*/, macro_handler_s, void * /*userdata*/ > > &macros,
std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
static Ucl parse(const char *in, const std::map<std::string, std::string> &vars,
std::vector<std::tuple<std::string /*name*/, macro_handler_s, void * /*userdata*/>> &macros,
std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
{
if (!in) {
err = "null input";
return nullptr;
}
return parse (std::string (in), vars, macros, err, duplicate_strategy);
return parse(std::string(in), vars, macros, err, duplicate_strategy);
}
static Ucl parse (const char *in, const variable_replacer &replacer,
std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
static Ucl parse(const char *in, const variable_replacer &replacer,
std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
{
if (!in) {
err = "null input";
return nullptr;
}
return parse (std::string(in), replacer, err, duplicate_strategy);
return parse(std::string(in), replacer, err, duplicate_strategy);
}
//Macro handler will receive a macro_userdata_s as void *ud
static Ucl parse (const char *in, const variable_replacer &replacer,
std::vector< std::tuple< std::string /*name*/, macro_handler_s, void * /*userdata*/ > > &macros,
std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
static Ucl parse(const char *in, const variable_replacer &replacer,
std::vector<std::tuple<std::string /*name*/, macro_handler_s, void * /*userdata*/>> &macros,
std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
{
if (!in) {
err = "null input";
return nullptr;
}
return parse (std::string (in), replacer, macros, err, duplicate_strategy);
return parse(std::string(in), replacer, macros, err, duplicate_strategy);
}
static Ucl parse_from_file (const std::string &filename, std::string &err)
static Ucl parse_from_file(const std::string &filename, std::string &err)
{
return parse_from_file (filename, std::map<std::string, std::string>(), err);
return parse_from_file(filename, std::map<std::string, std::string>(), err);
}
static Ucl parse_from_file (const std::string &filename, const std::map<std::string, std::string> &vars, std::string &err)
static Ucl parse_from_file(const std::string &filename, const std::map<std::string, std::string> &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 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 ());
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);
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)
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<variable_replacer &>(replacer));
auto config_func = [&replacer](ucl_parser *parser) {
ucl_parser_set_variables_handler(parser, ucl_variable_replacer,
&const_cast<variable_replacer &>(replacer));
};
auto parse_func = [&filename] (ucl_parser *parser) {
return ucl_parser_add_file (parser, filename.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);
return parse_with_strategy_function(config_func, parse_func, err);
}
static std::vector<std::string> find_variable (const std::string &in)
static std::vector<std::string> find_variable(const std::string &in)
{
auto parser = ucl_parser_new (UCL_PARSER_DEFAULT);
auto parser = ucl_parser_new(UCL_PARSER_DEFAULT);
std::set<std::string> 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);
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);
std::vector<std::string> result;
std::move (vars.begin (), vars.end (), std::back_inserter (result));
std::move(vars.begin(), vars.end(), std::back_inserter(result));
return result;
}
static std::vector<std::string> find_variable (const char *in)
static std::vector<std::string> find_variable(const char *in)
{
if (!in) {
return std::vector<std::string>();
}
return find_variable (std::string (in));
return find_variable(std::string(in));
}
static std::vector<std::string> find_variable_from_file (const std::string &filename)
static std::vector<std::string> find_variable_from_file(const std::string &filename)
{
auto parser = ucl_parser_new (UCL_PARSER_DEFAULT);
auto parser = ucl_parser_new(UCL_PARSER_DEFAULT);
std::set<std::string> vars;
ucl_parser_set_variables_handler (parser, ucl_variable_getter, &vars);
ucl_parser_add_file (parser, filename.c_str ());
ucl_parser_free (parser);
ucl_parser_set_variables_handler(parser, ucl_variable_getter, &vars);
ucl_parser_add_file(parser, filename.c_str());
ucl_parser_free(parser);
std::vector<std::string> result;
std::move (vars.begin (), vars.end (), std::back_inserter (result));
std::move(vars.begin(), vars.end(), std::back_inserter(result));
return result;
}
Ucl& operator= (Ucl rhs)
Ucl &operator=(Ucl rhs)
{
obj.swap (rhs.obj);
obj.swap(rhs.obj);
return *this;
}
bool operator== (const Ucl &rhs) const
bool operator==(const Ucl &rhs) const
{
return ucl_object_compare (obj.get(), rhs.obj.get ()) == 0;
return ucl_object_compare(obj.get(), rhs.obj.get()) == 0;
}
bool operator< (const Ucl &rhs) const
bool operator<(const Ucl &rhs) const
{
return ucl_object_compare (obj.get(), rhs.obj.get ()) < 0;
return ucl_object_compare(obj.get(), rhs.obj.get()) < 0;
}
bool operator!=(const Ucl &rhs) const
{
return !(*this == rhs);
}
bool operator<=(const Ucl &rhs) const
{
return !(rhs < *this);
}
bool operator>(const Ucl &rhs) const
{
return (rhs < *this);
}
bool operator>=(const Ucl &rhs) const
{
return !(*this < rhs);
}
bool operator!= (const Ucl &rhs) const { return !(*this == rhs); }
bool operator<= (const Ucl &rhs) const { return !(rhs < *this); }
bool operator> (const Ucl &rhs) const { return (rhs < *this); }
bool operator>= (const Ucl &rhs) const { return !(*this < rhs); }
explicit operator bool () const
explicit operator bool() const
{
if (!obj || type() == UCL_NULL) {
return false;
}
if (type () == UCL_BOOLEAN) {
return bool_value ();
if (type() == UCL_BOOLEAN) {
return bool_value();
}
return true;
@ -736,4 +778,4 @@ public:
}
};
};
};// namespace ucl

File diff suppressed because it is too large Load diff

View file

@ -648,7 +648,13 @@ static int
lua_ucl_parser_init (lua_State *L)
{
struct ucl_parser *parser, **pparser;
int flags = UCL_PARSER_NO_FILEVARS;
/*
* We disable file variables and macros by default, as
* the most use cases are parsing of JSON and not of the real
* files. Macros in the parser are very dangerous and should be used
* for trusted data only.
*/
int flags = UCL_PARSER_NO_FILEVARS|UCL_PARSER_DISABLE_MACRO;
if (lua_gettop (L) >= 1) {
flags = lua_tonumber (L, 1);

View file

@ -25,7 +25,7 @@
AC_DEFUN([AX_CODE_COVERAGE],
[
AC_ARG_ENABLE(coverage, AC_HELP_STRING([--enable-coverage],[configure code coverage analysis tools]))
AC_ARG_ENABLE(coverage, AS_HELP_STRING([--enable-coverage],[configure code coverage analysis tools]))
HAVE_GCOV_TOOLS=0

355
src/mum.h
View file

@ -69,14 +69,14 @@ typedef unsigned __int64 uint64_t;
#endif
#endif
#if defined(__GNUC__) && ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9) || (__GNUC__ > 4))
#if defined(__GNUC__) && ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9) || (__GNUC__ > 4))
#define _MUM_FRESH_GCC
#endif
#if defined(__GNUC__) && !defined(__llvm__) && defined(_MUM_FRESH_GCC)
#define _MUM_ATTRIBUTE_UNUSED __attribute__((unused))
#define _MUM_OPTIMIZE(opts) __attribute__((__optimize__ (opts)))
#define _MUM_TARGET(opts) __attribute__((__target__ (opts)))
#define _MUM_ATTRIBUTE_UNUSED __attribute__((unused))
#define _MUM_OPTIMIZE(opts) __attribute__((__optimize__(opts)))
#define _MUM_TARGET(opts) __attribute__((__target__(opts)))
#else
#define _MUM_ATTRIBUTE_UNUSED
#define _MUM_OPTIMIZE(opts)
@ -95,93 +95,108 @@ static uint64_t _mum_tail_prime = 0xaf47d47c99b1461bULL;
static uint64_t _mum_finish_prime1 = 0xa9a7ae7ceff79f3fULL;
static uint64_t _mum_finish_prime2 = 0xaf47d47c99b1461bULL;
static uint64_t _mum_primes [] = {
0X9ebdcae10d981691, 0X32b9b9b97a27ac7d, 0X29b5584d83d35bbd, 0X4b04e0e61401255f,
0X25e8f7b1f1c9d027, 0X80d4c8c000f3e881, 0Xbd1255431904b9dd, 0X8a3bd4485eee6d81,
0X3bc721b2aad05197, 0X71b1a19b907d6e33, 0X525e6c1084a8534b, 0X9e4c2cd340c1299f,
0Xde3add92e94caa37, 0X7e14eadb1f65311d, 0X3f5aa40f89812853, 0X33b15a3b587d15c9,
static uint64_t _mum_primes[] = {
0X9ebdcae10d981691,
0X32b9b9b97a27ac7d,
0X29b5584d83d35bbd,
0X4b04e0e61401255f,
0X25e8f7b1f1c9d027,
0X80d4c8c000f3e881,
0Xbd1255431904b9dd,
0X8a3bd4485eee6d81,
0X3bc721b2aad05197,
0X71b1a19b907d6e33,
0X525e6c1084a8534b,
0X9e4c2cd340c1299f,
0Xde3add92e94caa37,
0X7e14eadb1f65311d,
0X3f5aa40f89812853,
0X33b15a3b587d15c9,
};
/* Multiply 64-bit V and P and return sum of high and low parts of the
result. */
static inline uint64_t
_mum (uint64_t v, uint64_t p) {
uint64_t hi, lo;
_mum(uint64_t v, uint64_t p)
{
uint64_t hi, lo;
#if _MUM_USE_INT128
#if defined(__aarch64__)
/* AARCH64 needs 2 insns to calculate 128-bit result of the
/* AARCH64 needs 2 insns to calculate 128-bit result of the
multiplication. If we use a generic code we actually call a
function doing 128x128->128 bit multiplication. The function is
very slow. */
lo = v * p, hi;
asm ("umulh %0, %1, %2" : "=r" (hi) : "r" (v), "r" (p));
lo = v * p, hi;
asm("umulh %0, %1, %2" : "=r"(hi) : "r"(v), "r"(p));
#else
__uint128_t r = (__uint128_t) v * (__uint128_t) p;
hi = (uint64_t) (r >> 64);
lo = (uint64_t) r;
__uint128_t r = (__uint128_t) v * (__uint128_t) p;
hi = (uint64_t) (r >> 64);
lo = (uint64_t) r;
#endif
#else
/* Implementation of 64x64->128-bit multiplication by four 32x32->64
/* Implementation of 64x64->128-bit multiplication by four 32x32->64
bit multiplication. */
uint64_t hv = v >> 32, hp = p >> 32;
uint64_t lv = (uint32_t) v, lp = (uint32_t) p;
uint64_t rh = hv * hp;
uint64_t rm_0 = hv * lp;
uint64_t rm_1 = hp * lv;
uint64_t rl = lv * lp;
uint64_t t, carry = 0;
uint64_t hv = v >> 32, hp = p >> 32;
uint64_t lv = (uint32_t) v, lp = (uint32_t) p;
uint64_t rh = hv * hp;
uint64_t rm_0 = hv * lp;
uint64_t rm_1 = hp * lv;
uint64_t rl = lv * lp;
uint64_t t, carry = 0;
/* We could ignore a carry bit here if we did not care about the
/* We could ignore a carry bit here if we did not care about the
same hash for 32-bit and 64-bit targets. */
t = rl + (rm_0 << 32);
t = rl + (rm_0 << 32);
#ifdef MUM_TARGET_INDEPENDENT_HASH
carry = t < rl;
carry = t < rl;
#endif
lo = t + (rm_1 << 32);
lo = t + (rm_1 << 32);
#ifdef MUM_TARGET_INDEPENDENT_HASH
carry += lo < t;
carry += lo < t;
#endif
hi = rh + (rm_0 >> 32) + (rm_1 >> 32) + carry;
hi = rh + (rm_0 >> 32) + (rm_1 >> 32) + carry;
#endif
/* We could use XOR here too but, for some reasons, on Haswell and
/* We could use XOR here too but, for some reasons, on Haswell and
Power7 using an addition improves hashing performance by 10% for
small strings. */
return hi + lo;
return hi + lo;
}
#if defined(_MSC_VER)
#define _mum_bswap_32(x) _byteswap_uint32_t (x)
#define _mum_bswap_64(x) _byteswap_uint64_t (x)
#define _mum_bswap_32(x) _byteswap_uint32_t(x)
#define _mum_bswap_64(x) _byteswap_uint64_t(x)
#elif defined(__APPLE__)
#include <libkern/OSByteOrder.h>
#define _mum_bswap_32(x) OSSwapInt32 (x)
#define _mum_bswap_64(x) OSSwapInt64 (x)
#define _mum_bswap_32(x) OSSwapInt32(x)
#define _mum_bswap_64(x) OSSwapInt64(x)
#elif defined(__GNUC__)
#define _mum_bswap32(x) __builtin_bswap32 (x)
#define _mum_bswap64(x) __builtin_bswap64 (x)
#define _mum_bswap32(x) __builtin_bswap32(x)
#define _mum_bswap64(x) __builtin_bswap64(x)
#else
#include <byteswap.h>
#define _mum_bswap32(x) bswap32 (x)
#define _mum_bswap64(x) bswap64 (x)
#define _mum_bswap32(x) bswap32(x)
#define _mum_bswap64(x) bswap64(x)
#endif
static inline uint64_t
_mum_le (uint64_t v) {
_mum_le(uint64_t v)
{
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || !defined(MUM_TARGET_INDEPENDENT_HASH)
return v;
return v;
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
return _mum_bswap64 (v);
return _mum_bswap64(v);
#else
#error "Unknown endianness"
#endif
}
static inline uint32_t
_mum_le32 (uint32_t v) {
_mum_le32(uint32_t v)
{
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || !defined(MUM_TARGET_INDEPENDENT_HASH)
return v;
return v;
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
return _mum_bswap32 (v);
return _mum_bswap32(v);
#else
#error "Unknown endianness"
#endif
@ -214,71 +229,74 @@ _mum_le32 (uint32_t v) {
#define _MUM_UNROLL_FACTOR (1 << _MUM_UNROLL_FACTOR_POWER)
static inline uint64_t _MUM_OPTIMIZE("unroll-loops")
_mum_hash_aligned (uint64_t start, const void *key, size_t len) {
uint64_t result = start;
const unsigned char *str = (const unsigned char *) key;
uint64_t u64;
int i;
size_t n;
_mum_hash_aligned(uint64_t start, const void *key, size_t len)
{
uint64_t result = start;
const unsigned char *str = (const unsigned char *) key;
uint64_t u64;
int i;
size_t n;
result = _mum (result, _mum_block_start_prime);
while (len > _MUM_UNROLL_FACTOR * sizeof (uint64_t)) {
/* This loop could be vectorized when we have vector insns for
result = _mum(result, _mum_block_start_prime);
while (len > _MUM_UNROLL_FACTOR * sizeof(uint64_t)) {
/* This loop could be vectorized when we have vector insns for
64x64->128-bit multiplication. AVX2 currently only have a
vector insn for 4 32x32->64-bit multiplication. */
for (i = 0; i < _MUM_UNROLL_FACTOR; i++)
result ^= _mum (_mum_le (((uint64_t *) str)[i]), _mum_primes[i]);
len -= _MUM_UNROLL_FACTOR * sizeof (uint64_t);
str += _MUM_UNROLL_FACTOR * sizeof (uint64_t);
/* We will use the same prime numbers on the next iterations --
for (i = 0; i < _MUM_UNROLL_FACTOR; i++)
result ^= _mum(_mum_le(((uint64_t *) str)[i]), _mum_primes[i]);
len -= _MUM_UNROLL_FACTOR * sizeof(uint64_t);
str += _MUM_UNROLL_FACTOR * sizeof(uint64_t);
/* We will use the same prime numbers on the next iterations --
randomize the state. */
result = _mum (result, _mum_unroll_prime);
}
n = len / sizeof (uint64_t);
for (i = 0; i < (int)n; i++)
result ^= _mum (_mum_le (((uint64_t *) str)[i]), _mum_primes[i]);
len -= n * sizeof (uint64_t); str += n * sizeof (uint64_t);
switch (len) {
case 7:
u64 = _mum_le32 (*(uint32_t *) str);
u64 |= (uint64_t) str[4] << 32;
u64 |= (uint64_t) str[5] << 40;
u64 |= (uint64_t) str[6] << 48;
return result ^ _mum (u64, _mum_tail_prime);
case 6:
u64 = _mum_le32 (*(uint32_t *) str);
u64 |= (uint64_t) str[4] << 32;
u64 |= (uint64_t) str[5] << 40;
return result ^ _mum (u64, _mum_tail_prime);
case 5:
u64 = _mum_le32 (*(uint32_t *) str);
u64 |= (uint64_t) str[4] << 32;
return result ^ _mum (u64, _mum_tail_prime);
case 4:
u64 = _mum_le32 (*(uint32_t *) str);
return result ^ _mum (u64, _mum_tail_prime);
case 3:
u64 = str[0];
u64 |= (uint64_t) str[1] << 8;
u64 |= (uint64_t) str[2] << 16;
return result ^ _mum (u64, _mum_tail_prime);
case 2:
u64 = str[0];
u64 |= (uint64_t) str[1] << 8;
return result ^ _mum (u64, _mum_tail_prime);
case 1:
u64 = str[0];
return result ^ _mum (u64, _mum_tail_prime);
}
return result;
result = _mum(result, _mum_unroll_prime);
}
n = len / sizeof(uint64_t);
for (i = 0; i < (int) n; i++)
result ^= _mum(_mum_le(((uint64_t *) str)[i]), _mum_primes[i]);
len -= n * sizeof(uint64_t);
str += n * sizeof(uint64_t);
switch (len) {
case 7:
u64 = _mum_le32(*(uint32_t *) str);
u64 |= (uint64_t) str[4] << 32;
u64 |= (uint64_t) str[5] << 40;
u64 |= (uint64_t) str[6] << 48;
return result ^ _mum(u64, _mum_tail_prime);
case 6:
u64 = _mum_le32(*(uint32_t *) str);
u64 |= (uint64_t) str[4] << 32;
u64 |= (uint64_t) str[5] << 40;
return result ^ _mum(u64, _mum_tail_prime);
case 5:
u64 = _mum_le32(*(uint32_t *) str);
u64 |= (uint64_t) str[4] << 32;
return result ^ _mum(u64, _mum_tail_prime);
case 4:
u64 = _mum_le32(*(uint32_t *) str);
return result ^ _mum(u64, _mum_tail_prime);
case 3:
u64 = str[0];
u64 |= (uint64_t) str[1] << 8;
u64 |= (uint64_t) str[2] << 16;
return result ^ _mum(u64, _mum_tail_prime);
case 2:
u64 = str[0];
u64 |= (uint64_t) str[1] << 8;
return result ^ _mum(u64, _mum_tail_prime);
case 1:
u64 = str[0];
return result ^ _mum(u64, _mum_tail_prime);
}
return result;
}
/* Final randomization of H. */
static inline uint64_t
_mum_final (uint64_t h) {
h ^= _mum (h, _mum_finish_prime1);
h ^= _mum (h, _mum_finish_prime2);
return h;
_mum_final(uint64_t h)
{
h ^= _mum(h, _mum_finish_prime1);
h ^= _mum(h, _mum_finish_prime2);
return h;
}
#if defined(__x86_64__) && defined(_MUM_FRESH_GCC)
@ -288,16 +306,14 @@ _mum_final (uint64_t h) {
3-cycles vs. 4 for MULX, MULX permits more freedom in insn
scheduling as it uses less fixed registers. */
static inline uint64_t _MUM_TARGET("arch=haswell")
_mum_hash_avx2 (const void * key, size_t len, uint64_t seed) {
return _mum_final (_mum_hash_aligned (seed + len, key, len));
_mum_hash_avx2(const void *key, size_t len, uint64_t seed)
{
return _mum_final(_mum_hash_aligned(seed + len, key, len));
}
#endif
#ifndef _MUM_UNALIGNED_ACCESS
#if defined(__x86_64__) || defined(__i386__) || defined(__PPC64__) \
|| defined(__s390__) || defined(__m32c__) || defined(cris) \
|| defined(__CR16__) || defined(__vax__) || defined(__m68k__) \
|| defined(__aarch64__)
#if defined(__x86_64__) || defined(__i386__) || defined(__PPC64__) || defined(__s390__) || defined(__m32c__) || defined(cris) || defined(__CR16__) || defined(__vax__) || defined(__m68k__) || defined(__aarch64__)
#define _MUM_UNALIGNED_ACCESS 1
#else
#define _MUM_UNALIGNED_ACCESS 0
@ -317,101 +333,108 @@ _mum_hash_avx2 (const void * key, size_t len, uint64_t seed) {
static inline uint64_t
#if defined(__x86_64__)
_MUM_TARGET("inline-all-stringops")
_MUM_TARGET("inline-all-stringops")
#endif
_mum_hash_default (const void *key, size_t len, uint64_t seed) {
uint64_t result;
const unsigned char *str = (const unsigned char *) key;
size_t block_len;
uint64_t buf[_MUM_BLOCK_LEN / sizeof (uint64_t)];
_mum_hash_default(const void *key, size_t len, uint64_t seed)
{
uint64_t result;
const unsigned char *str = (const unsigned char *) key;
size_t block_len;
uint64_t buf[_MUM_BLOCK_LEN / sizeof(uint64_t)];
result = seed + len;
if (_MUM_UNALIGNED_ACCESS || ((size_t) str & 0x7) == 0)
result = _mum_hash_aligned (result, key, len);
else {
while (len != 0) {
block_len = len < _MUM_BLOCK_LEN ? len : _MUM_BLOCK_LEN;
memmove (buf, str, block_len);
result = _mum_hash_aligned (result, buf, block_len);
len -= block_len;
str += block_len;
}
}
return _mum_final (result);
result = seed + len;
if (_MUM_UNALIGNED_ACCESS || ((size_t) str & 0x7) == 0)
result = _mum_hash_aligned(result, key, len);
else {
while (len != 0) {
block_len = len < _MUM_BLOCK_LEN ? len : _MUM_BLOCK_LEN;
memmove(buf, str, block_len);
result = _mum_hash_aligned(result, buf, block_len);
len -= block_len;
str += block_len;
}
}
return _mum_final(result);
}
static inline uint64_t
_mum_next_factor (void) {
uint64_t start = 0;
int i;
_mum_next_factor(void)
{
uint64_t start = 0;
int i;
for (i = 0; i < 8; i++)
start = (start << 8) | rand() % 256;
return start;
for (i = 0; i < 8; i++)
start = (start << 8) | rand() % 256;
return start;
}
/* ++++++++++++++++++++++++++ Interface functions: +++++++++++++++++++ */
/* Set random multiplicators depending on SEED. */
static inline void
mum_hash_randomize (uint64_t seed) {
int i;
mum_hash_randomize(uint64_t seed)
{
int i;
srand (seed);
_mum_hash_step_prime = _mum_next_factor ();
_mum_key_step_prime = _mum_next_factor ();
_mum_finish_prime1 = _mum_next_factor ();
_mum_finish_prime2 = _mum_next_factor ();
_mum_block_start_prime = _mum_next_factor ();
_mum_unroll_prime = _mum_next_factor ();
_mum_tail_prime = _mum_next_factor ();
for (i = 0; i < (int)(sizeof (_mum_primes) / sizeof (uint64_t)); i++)
_mum_primes[i] = _mum_next_factor ();
srand(seed);
_mum_hash_step_prime = _mum_next_factor();
_mum_key_step_prime = _mum_next_factor();
_mum_finish_prime1 = _mum_next_factor();
_mum_finish_prime2 = _mum_next_factor();
_mum_block_start_prime = _mum_next_factor();
_mum_unroll_prime = _mum_next_factor();
_mum_tail_prime = _mum_next_factor();
for (i = 0; i < (int) (sizeof(_mum_primes) / sizeof(uint64_t)); i++)
_mum_primes[i] = _mum_next_factor();
}
/* Start hashing data with SEED. Return the state. */
static inline uint64_t
mum_hash_init (uint64_t seed) {
return seed;
mum_hash_init(uint64_t seed)
{
return seed;
}
/* Process data KEY with the state H and return the updated state. */
static inline uint64_t
mum_hash_step (uint64_t h, uint64_t key)
mum_hash_step(uint64_t h, uint64_t key)
{
return _mum (h, _mum_hash_step_prime) ^ _mum (key, _mum_key_step_prime);
return _mum(h, _mum_hash_step_prime) ^ _mum(key, _mum_key_step_prime);
}
/* Return the result of hashing using the current state H. */
static inline uint64_t
mum_hash_finish (uint64_t h) {
return _mum_final (h);
mum_hash_finish(uint64_t h)
{
return _mum_final(h);
}
/* Fast hashing of KEY with SEED. The hash is always the same for the
same key on any target. */
static inline size_t
mum_hash64 (uint64_t key, uint64_t seed) {
return mum_hash_finish (mum_hash_step (mum_hash_init (seed), key));
mum_hash64(uint64_t key, uint64_t seed)
{
return mum_hash_finish(mum_hash_step(mum_hash_init(seed), key));
}
/* Hash data KEY of length LEN and SEED. The hash depends on the
target endianness and the unroll factor. */
static inline uint64_t
mum_hash (const void *key, size_t len, uint64_t seed) {
mum_hash(const void *key, size_t len, uint64_t seed)
{
#if defined(__x86_64__) && defined(_MUM_FRESH_GCC)
static int avx2_support = 0;
static int avx2_support = 0;
if (avx2_support > 0)
return _mum_hash_avx2 (key, len, seed);
else if (! avx2_support) {
__builtin_cpu_init ();
avx2_support = __builtin_cpu_supports ("avx2") ? 1 : -1;
if (avx2_support > 0)
return _mum_hash_avx2 (key, len, seed);
}
if (avx2_support > 0)
return _mum_hash_avx2(key, len, seed);
else if (!avx2_support) {
__builtin_cpu_init();
avx2_support = __builtin_cpu_supports("avx2") ? 1 : -1;
if (avx2_support > 0)
return _mum_hash_avx2(key, len, seed);
}
#endif
return _mum_hash_default (key, len, seed);
return _mum_hash_default(key, len, seed);
}
#endif

View file

@ -43,177 +43,167 @@
#define __tree_h
#define TREE_DELTA_MAX 1
#define TREE_DELTA_MAX 1
#ifndef _HU_FUNCTION
# if defined(__GNUC__) || defined(__clang__)
# define _HU_FUNCTION(x) __attribute__((__unused__)) x
# else
# define _HU_FUNCTION(x) x
# endif
#if defined(__GNUC__) || defined(__clang__)
#define _HU_FUNCTION(x) __attribute__((__unused__)) x
#else
#define _HU_FUNCTION(x) x
#endif
#endif
#define TREE_ENTRY(type) \
struct { \
struct type *avl_left; \
struct type *avl_right; \
int avl_height; \
}
#define TREE_ENTRY(type) \
struct { \
struct type *avl_left; \
struct type *avl_right; \
int avl_height; \
}
#define TREE_HEAD(name, type) \
struct name { \
struct type *th_root; \
int (*th_cmp)(struct type *lhs, struct type *rhs); \
}
#define TREE_HEAD(name, type) \
struct name { \
struct type *th_root; \
int (*th_cmp)(struct type * lhs, struct type *rhs); \
}
#define TREE_INITIALIZER(cmp) { 0, cmp }
#define TREE_INITIALIZER(cmp) {0, cmp}
#define TREE_DELTA(self, field) \
(( (((self)->field.avl_left) ? (self)->field.avl_left->field.avl_height : 0)) \
- (((self)->field.avl_right) ? (self)->field.avl_right->field.avl_height : 0))
#define TREE_DELTA(self, field) \
(((((self)->field.avl_left) ? (self)->field.avl_left->field.avl_height : 0)) - (((self)->field.avl_right) ? (self)->field.avl_right->field.avl_height : 0))
/* Recursion prevents the following from being defined as macros. */
#define TREE_DEFINE(node, field) \
\
static struct node *_HU_FUNCTION(TREE_BALANCE_##node##_##field)(struct node *); \
\
static struct node *_HU_FUNCTION(TREE_ROTL_##node##_##field)(struct node *self) \
{ \
struct node *r= self->field.avl_right; \
self->field.avl_right= r->field.avl_left; \
r->field.avl_left= TREE_BALANCE_##node##_##field(self); \
return TREE_BALANCE_##node##_##field(r); \
} \
\
static struct node *_HU_FUNCTION(TREE_ROTR_##node##_##field)(struct node *self) \
{ \
struct node *l= self->field.avl_left; \
self->field.avl_left= l->field.avl_right; \
l->field.avl_right= TREE_BALANCE_##node##_##field(self); \
return TREE_BALANCE_##node##_##field(l); \
} \
\
static struct node *_HU_FUNCTION(TREE_BALANCE_##node##_##field)(struct node *self) \
{ \
int delta= TREE_DELTA(self, field); \
\
if (delta < -TREE_DELTA_MAX) \
{ \
if (TREE_DELTA(self->field.avl_right, field) > 0) \
self->field.avl_right= TREE_ROTR_##node##_##field(self->field.avl_right); \
return TREE_ROTL_##node##_##field(self); \
} \
else if (delta > TREE_DELTA_MAX) \
{ \
if (TREE_DELTA(self->field.avl_left, field) < 0) \
self->field.avl_left= TREE_ROTL_##node##_##field(self->field.avl_left); \
return TREE_ROTR_##node##_##field(self); \
} \
self->field.avl_height= 0; \
if (self->field.avl_left && (self->field.avl_left->field.avl_height > self->field.avl_height)) \
self->field.avl_height= self->field.avl_left->field.avl_height; \
if (self->field.avl_right && (self->field.avl_right->field.avl_height > self->field.avl_height)) \
self->field.avl_height= self->field.avl_right->field.avl_height; \
self->field.avl_height += 1; \
return self; \
} \
\
static struct node *_HU_FUNCTION(TREE_INSERT_##node##_##field) \
(struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs)) \
{ \
if (!self) \
return elm; \
if (compare(elm, self) < 0) \
self->field.avl_left= TREE_INSERT_##node##_##field(self->field.avl_left, elm, compare); \
else \
self->field.avl_right= TREE_INSERT_##node##_##field(self->field.avl_right, elm, compare); \
return TREE_BALANCE_##node##_##field(self); \
} \
\
static struct node *_HU_FUNCTION(TREE_FIND_##node##_##field) \
(struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs)) \
{ \
if (!self) \
return 0; \
if (compare(elm, self) == 0) \
return self; \
if (compare(elm, self) < 0) \
return TREE_FIND_##node##_##field(self->field.avl_left, elm, compare); \
else \
return TREE_FIND_##node##_##field(self->field.avl_right, elm, compare); \
} \
\
static struct node *_HU_FUNCTION(TREE_MOVE_RIGHT)(struct node *self, struct node *rhs) \
{ \
if (!self) \
return rhs; \
self->field.avl_right= TREE_MOVE_RIGHT(self->field.avl_right, rhs); \
return TREE_BALANCE_##node##_##field(self); \
} \
\
static struct node *_HU_FUNCTION(TREE_REMOVE_##node##_##field) \
(struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs)) \
{ \
if (!self) return 0; \
\
if (compare(elm, self) == 0) \
{ \
struct node *tmp= TREE_MOVE_RIGHT(self->field.avl_left, self->field.avl_right); \
self->field.avl_left= 0; \
self->field.avl_right= 0; \
return tmp; \
} \
if (compare(elm, self) < 0) \
self->field.avl_left= TREE_REMOVE_##node##_##field(self->field.avl_left, elm, compare); \
else \
self->field.avl_right= TREE_REMOVE_##node##_##field(self->field.avl_right, elm, compare); \
return TREE_BALANCE_##node##_##field(self); \
} \
\
static void _HU_FUNCTION(TREE_FORWARD_APPLY_ALL_##node##_##field) \
(struct node *self, void (*function)(struct node *node, void *data), void *data) \
{ \
if (self) \
{ \
TREE_FORWARD_APPLY_ALL_##node##_##field(self->field.avl_left, function, data); \
function(self, data); \
TREE_FORWARD_APPLY_ALL_##node##_##field(self->field.avl_right, function, data); \
} \
} \
\
static void _HU_FUNCTION(TREE_REVERSE_APPLY_ALL_##node##_##field) \
(struct node *self, void (*function)(struct node *node, void *data), void *data) \
{ \
if (self) \
{ \
TREE_REVERSE_APPLY_ALL_##node##_##field(self->field.avl_right, function, data); \
function(self, data); \
TREE_REVERSE_APPLY_ALL_##node##_##field(self->field.avl_left, function, data); \
} \
}
#define TREE_DEFINE(node, field) \
\
static struct node *_HU_FUNCTION(TREE_BALANCE_##node##_##field)(struct node *); \
\
static struct node *_HU_FUNCTION(TREE_ROTL_##node##_##field)(struct node * self) \
{ \
struct node *r = self->field.avl_right; \
self->field.avl_right = r->field.avl_left; \
r->field.avl_left = TREE_BALANCE_##node##_##field(self); \
return TREE_BALANCE_##node##_##field(r); \
} \
\
static struct node *_HU_FUNCTION(TREE_ROTR_##node##_##field)(struct node * self) \
{ \
struct node *l = self->field.avl_left; \
self->field.avl_left = l->field.avl_right; \
l->field.avl_right = TREE_BALANCE_##node##_##field(self); \
return TREE_BALANCE_##node##_##field(l); \
} \
\
static struct node *_HU_FUNCTION(TREE_BALANCE_##node##_##field)(struct node * self) \
{ \
int delta = TREE_DELTA(self, field); \
\
if (delta < -TREE_DELTA_MAX) { \
if (TREE_DELTA(self->field.avl_right, field) > 0) \
self->field.avl_right = TREE_ROTR_##node##_##field(self->field.avl_right); \
return TREE_ROTL_##node##_##field(self); \
} \
else if (delta > TREE_DELTA_MAX) { \
if (TREE_DELTA(self->field.avl_left, field) < 0) \
self->field.avl_left = TREE_ROTL_##node##_##field(self->field.avl_left); \
return TREE_ROTR_##node##_##field(self); \
} \
self->field.avl_height = 0; \
if (self->field.avl_left && (self->field.avl_left->field.avl_height > self->field.avl_height)) \
self->field.avl_height = self->field.avl_left->field.avl_height; \
if (self->field.avl_right && (self->field.avl_right->field.avl_height > self->field.avl_height)) \
self->field.avl_height = self->field.avl_right->field.avl_height; \
self->field.avl_height += 1; \
return self; \
} \
\
static struct node *_HU_FUNCTION(TREE_INSERT_##node##_##field)(struct node * self, struct node * elm, int (*compare)(struct node * lhs, struct node * rhs)) \
{ \
if (!self) \
return elm; \
if (compare(elm, self) < 0) \
self->field.avl_left = TREE_INSERT_##node##_##field(self->field.avl_left, elm, compare); \
else \
self->field.avl_right = TREE_INSERT_##node##_##field(self->field.avl_right, elm, compare); \
return TREE_BALANCE_##node##_##field(self); \
} \
\
static struct node *_HU_FUNCTION(TREE_FIND_##node##_##field)(struct node * self, struct node * elm, int (*compare)(struct node * lhs, struct node * rhs)) \
{ \
if (!self) \
return 0; \
if (compare(elm, self) == 0) \
return self; \
if (compare(elm, self) < 0) \
return TREE_FIND_##node##_##field(self->field.avl_left, elm, compare); \
else \
return TREE_FIND_##node##_##field(self->field.avl_right, elm, compare); \
} \
\
static struct node *_HU_FUNCTION(TREE_MOVE_RIGHT)(struct node * self, struct node * rhs) \
{ \
if (!self) \
return rhs; \
self->field.avl_right = TREE_MOVE_RIGHT(self->field.avl_right, rhs); \
return TREE_BALANCE_##node##_##field(self); \
} \
\
static struct node *_HU_FUNCTION(TREE_REMOVE_##node##_##field)(struct node * self, struct node * elm, int (*compare)(struct node * lhs, struct node * rhs)) \
{ \
if (!self) return 0; \
\
if (compare(elm, self) == 0) { \
struct node *tmp = TREE_MOVE_RIGHT(self->field.avl_left, self->field.avl_right); \
self->field.avl_left = 0; \
self->field.avl_right = 0; \
return tmp; \
} \
if (compare(elm, self) < 0) \
self->field.avl_left = TREE_REMOVE_##node##_##field(self->field.avl_left, elm, compare); \
else \
self->field.avl_right = TREE_REMOVE_##node##_##field(self->field.avl_right, elm, compare); \
return TREE_BALANCE_##node##_##field(self); \
} \
\
static void _HU_FUNCTION(TREE_FORWARD_APPLY_ALL_##node##_##field)(struct node * self, void (*function)(struct node * node, void *data), void *data) \
{ \
if (self) { \
TREE_FORWARD_APPLY_ALL_##node##_##field(self->field.avl_left, function, data); \
function(self, data); \
TREE_FORWARD_APPLY_ALL_##node##_##field(self->field.avl_right, function, data); \
} \
} \
\
static void _HU_FUNCTION(TREE_REVERSE_APPLY_ALL_##node##_##field)(struct node * self, void (*function)(struct node * node, void *data), void *data) \
{ \
if (self) { \
TREE_REVERSE_APPLY_ALL_##node##_##field(self->field.avl_right, function, data); \
function(self, data); \
TREE_REVERSE_APPLY_ALL_##node##_##field(self->field.avl_left, function, data); \
} \
}
#define TREE_INSERT(head, node, field, elm) \
((head)->th_root= TREE_INSERT_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
#define TREE_INSERT(head, node, field, elm) \
((head)->th_root = TREE_INSERT_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
#define TREE_FIND(head, node, field, elm) \
(TREE_FIND_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
#define TREE_FIND(head, node, field, elm) \
(TREE_FIND_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
#define TREE_REMOVE(head, node, field, elm) \
((head)->th_root= TREE_REMOVE_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
#define TREE_REMOVE(head, node, field, elm) \
((head)->th_root = TREE_REMOVE_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
#define TREE_DEPTH(head, field) \
((head)->th_root->field.avl_height)
#define TREE_DEPTH(head, field) \
((head)->th_root->field.avl_height)
#define TREE_FORWARD_APPLY(head, node, field, function, data) \
TREE_FORWARD_APPLY_ALL_##node##_##field((head)->th_root, function, data)
#define TREE_FORWARD_APPLY(head, node, field, function, data) \
TREE_FORWARD_APPLY_ALL_##node##_##field((head)->th_root, function, data)
#define TREE_REVERSE_APPLY(head, node, field, function, data) \
TREE_REVERSE_APPLY_ALL_##node##_##field((head)->th_root, function, data)
#define TREE_REVERSE_APPLY(head, node, field, function, data) \
TREE_REVERSE_APPLY_ALL_##node##_##field((head)->th_root, function, data)
#define TREE_INIT(head, cmp) do { \
(head)->th_root= 0; \
(head)->th_cmp= (cmp); \
} while (0)
#define TREE_INIT(head, cmp) \
do { \
(head)->th_root = 0; \
(head)->th_cmp = (cmp); \
} while (0)
#endif /* __tree_h */

View file

@ -27,240 +27,239 @@
#include "ucl_internal.h"
static const unsigned int ucl_chartable[256] = {
UCL_CHARACTER_JSON_UNSAFE|UCL_CHARACTER_VALUE_END|UCL_CHARACTER_UCL_UNSAFE, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_JSON_UNSAFE|UCL_CHARACTER_UCL_UNSAFE,
UCL_CHARACTER_WHITESPACE|UCL_CHARACTER_WHITESPACE_UNSAFE|UCL_CHARACTER_KEY_SEP|UCL_CHARACTER_JSON_UNSAFE|UCL_CHARACTER_UCL_UNSAFE,
UCL_CHARACTER_WHITESPACE_UNSAFE|UCL_CHARACTER_VALUE_END|UCL_CHARACTER_JSON_UNSAFE|UCL_CHARACTER_UCL_UNSAFE,
UCL_CHARACTER_WHITESPACE_UNSAFE,
UCL_CHARACTER_WHITESPACE_UNSAFE|UCL_CHARACTER_JSON_UNSAFE|UCL_CHARACTER_UCL_UNSAFE,
UCL_CHARACTER_WHITESPACE_UNSAFE|UCL_CHARACTER_VALUE_END|UCL_CHARACTER_JSON_UNSAFE|UCL_CHARACTER_UCL_UNSAFE,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_WHITESPACE|UCL_CHARACTER_WHITESPACE_UNSAFE|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_KEY_SEP|UCL_CHARACTER_UCL_UNSAFE /* */,
UCL_CHARACTER_VALUE_STR /* ! */,
UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_ESCAPE|UCL_CHARACTER_JSON_UNSAFE|UCL_CHARACTER_UCL_UNSAFE /* " */,
UCL_CHARACTER_VALUE_END /* # */, UCL_CHARACTER_VALUE_STR /* $ */,
UCL_CHARACTER_VALUE_STR /* % */, UCL_CHARACTER_VALUE_STR /* & */,
UCL_CHARACTER_VALUE_STR /* ' */, UCL_CHARACTER_VALUE_STR /* ( */,
UCL_CHARACTER_VALUE_STR /* ) */, UCL_CHARACTER_VALUE_STR /* * */,
UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT|UCL_CHARACTER_UCL_UNSAFE /* + */,
UCL_CHARACTER_VALUE_END /* , */,
UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT_START|UCL_CHARACTER_VALUE_DIGIT /* - */,
UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* . */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_ESCAPE /* / */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT_START|UCL_CHARACTER_VALUE_DIGIT /* 0 */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT_START|UCL_CHARACTER_VALUE_DIGIT /* 1 */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT_START|UCL_CHARACTER_VALUE_DIGIT /* 2 */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT_START|UCL_CHARACTER_VALUE_DIGIT /* 3 */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT_START|UCL_CHARACTER_VALUE_DIGIT /* 4 */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT_START|UCL_CHARACTER_VALUE_DIGIT /* 5 */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT_START|UCL_CHARACTER_VALUE_DIGIT /* 6 */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT_START|UCL_CHARACTER_VALUE_DIGIT /* 7 */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT_START|UCL_CHARACTER_VALUE_DIGIT /* 8 */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT_START|UCL_CHARACTER_VALUE_DIGIT /* 9 */,
UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_KEY_SEP|UCL_CHARACTER_UCL_UNSAFE /* : */,
UCL_CHARACTER_VALUE_END /* ; */, UCL_CHARACTER_VALUE_STR /* < */,
UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_KEY_SEP|UCL_CHARACTER_UCL_UNSAFE /* = */,
UCL_CHARACTER_VALUE_STR /* > */, UCL_CHARACTER_VALUE_STR /* ? */,
UCL_CHARACTER_VALUE_STR /* @ */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* A */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* B */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* C */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* D */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* E */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* F */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* G */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* H */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* I */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* J */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* K */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* L */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* M */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* N */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* O */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* P */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* Q */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* R */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* S */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* T */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* U */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* V */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* W */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* X */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* Y */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* Z */,
UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_UCL_UNSAFE /* [ */,
UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_ESCAPE|UCL_CHARACTER_JSON_UNSAFE|UCL_CHARACTER_UCL_UNSAFE /* \ */,
UCL_CHARACTER_VALUE_END /* ] */, UCL_CHARACTER_VALUE_STR /* ^ */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR /* _ */,
UCL_CHARACTER_VALUE_STR /* ` */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* a */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT|UCL_CHARACTER_ESCAPE /* b */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* c */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* d */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* e */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT|UCL_CHARACTER_ESCAPE /* f */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* g */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* h */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* i */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* j */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* k */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* l */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* m */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT|UCL_CHARACTER_ESCAPE /* n */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* o */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* p */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* q */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT|UCL_CHARACTER_ESCAPE /* r */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* s */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT|UCL_CHARACTER_ESCAPE /* t */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT|UCL_CHARACTER_ESCAPE /* u */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* v */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* w */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* x */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* y */,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_VALUE_DIGIT /* z */,
UCL_CHARACTER_VALUE_STR|UCL_CHARACTER_UCL_UNSAFE /* { */,
UCL_CHARACTER_VALUE_STR /* | */, UCL_CHARACTER_VALUE_END /* } */,
UCL_CHARACTER_VALUE_STR /* ~ */, UCL_CHARACTER_DENIED,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START|UCL_CHARACTER_KEY|UCL_CHARACTER_VALUE_STR
};
UCL_CHARACTER_JSON_UNSAFE | UCL_CHARACTER_VALUE_END | UCL_CHARACTER_UCL_UNSAFE, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_JSON_UNSAFE | UCL_CHARACTER_UCL_UNSAFE,
UCL_CHARACTER_WHITESPACE | UCL_CHARACTER_WHITESPACE_UNSAFE | UCL_CHARACTER_KEY_SEP | UCL_CHARACTER_JSON_UNSAFE | UCL_CHARACTER_UCL_UNSAFE,
UCL_CHARACTER_WHITESPACE_UNSAFE | UCL_CHARACTER_VALUE_END | UCL_CHARACTER_JSON_UNSAFE | UCL_CHARACTER_UCL_UNSAFE,
UCL_CHARACTER_WHITESPACE_UNSAFE,
UCL_CHARACTER_WHITESPACE_UNSAFE | UCL_CHARACTER_JSON_UNSAFE | UCL_CHARACTER_UCL_UNSAFE,
UCL_CHARACTER_WHITESPACE_UNSAFE | UCL_CHARACTER_VALUE_END | UCL_CHARACTER_JSON_UNSAFE | UCL_CHARACTER_UCL_UNSAFE,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED, UCL_CHARACTER_DENIED,
UCL_CHARACTER_WHITESPACE | UCL_CHARACTER_WHITESPACE_UNSAFE | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_KEY_SEP | UCL_CHARACTER_UCL_UNSAFE /* */,
UCL_CHARACTER_VALUE_STR /* ! */,
UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_ESCAPE | UCL_CHARACTER_JSON_UNSAFE | UCL_CHARACTER_UCL_UNSAFE /* " */,
UCL_CHARACTER_VALUE_END /* # */, UCL_CHARACTER_VALUE_STR /* $ */,
UCL_CHARACTER_VALUE_STR /* % */, UCL_CHARACTER_VALUE_STR /* & */,
UCL_CHARACTER_VALUE_STR /* ' */, UCL_CHARACTER_VALUE_STR /* ( */,
UCL_CHARACTER_VALUE_STR /* ) */, UCL_CHARACTER_VALUE_STR /* * */,
UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT | UCL_CHARACTER_UCL_UNSAFE /* + */,
UCL_CHARACTER_VALUE_END /* , */,
UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT_START | UCL_CHARACTER_VALUE_DIGIT /* - */,
UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* . */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_ESCAPE /* / */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT_START | UCL_CHARACTER_VALUE_DIGIT /* 0 */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT_START | UCL_CHARACTER_VALUE_DIGIT /* 1 */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT_START | UCL_CHARACTER_VALUE_DIGIT /* 2 */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT_START | UCL_CHARACTER_VALUE_DIGIT /* 3 */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT_START | UCL_CHARACTER_VALUE_DIGIT /* 4 */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT_START | UCL_CHARACTER_VALUE_DIGIT /* 5 */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT_START | UCL_CHARACTER_VALUE_DIGIT /* 6 */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT_START | UCL_CHARACTER_VALUE_DIGIT /* 7 */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT_START | UCL_CHARACTER_VALUE_DIGIT /* 8 */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT_START | UCL_CHARACTER_VALUE_DIGIT /* 9 */,
UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_KEY_SEP | UCL_CHARACTER_UCL_UNSAFE /* : */,
UCL_CHARACTER_VALUE_END /* ; */, UCL_CHARACTER_VALUE_STR /* < */,
UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_KEY_SEP | UCL_CHARACTER_UCL_UNSAFE /* = */,
UCL_CHARACTER_VALUE_STR /* > */, UCL_CHARACTER_VALUE_STR /* ? */,
UCL_CHARACTER_VALUE_STR /* @ */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* A */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* B */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* C */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* D */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* E */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* F */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* G */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* H */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* I */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* J */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* K */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* L */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* M */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* N */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* O */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* P */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* Q */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* R */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* S */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* T */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* U */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* V */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* W */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* X */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* Y */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* Z */,
UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_UCL_UNSAFE /* [ */,
UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_ESCAPE | UCL_CHARACTER_JSON_UNSAFE | UCL_CHARACTER_UCL_UNSAFE /* \ */,
UCL_CHARACTER_VALUE_END /* ] */, UCL_CHARACTER_VALUE_STR /* ^ */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR /* _ */,
UCL_CHARACTER_VALUE_STR /* ` */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* a */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT | UCL_CHARACTER_ESCAPE /* b */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* c */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* d */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* e */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT | UCL_CHARACTER_ESCAPE /* f */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* g */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* h */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* i */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* j */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* k */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* l */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* m */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT | UCL_CHARACTER_ESCAPE /* n */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* o */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* p */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* q */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT | UCL_CHARACTER_ESCAPE /* r */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* s */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT | UCL_CHARACTER_ESCAPE /* t */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT | UCL_CHARACTER_ESCAPE /* u */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* v */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* w */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* x */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* y */,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_VALUE_DIGIT /* z */,
UCL_CHARACTER_VALUE_STR | UCL_CHARACTER_UCL_UNSAFE /* { */,
UCL_CHARACTER_VALUE_STR /* | */, UCL_CHARACTER_VALUE_END /* } */,
UCL_CHARACTER_VALUE_STR /* ~ */, UCL_CHARACTER_DENIED,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR,
UCL_CHARACTER_KEY_START | UCL_CHARACTER_KEY | UCL_CHARACTER_VALUE_STR};
static inline bool
ucl_test_character (unsigned char c, int type_flags)
ucl_test_character(unsigned char c, int type_flags)
{
return (ucl_chartable[c] & type_flags) != 0;
}

View file

@ -40,20 +40,20 @@
* Serialise UCL object to various of output formats
*/
static void ucl_emitter_common_elt (struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool first, bool print_key, bool compact);
static void ucl_emitter_common_elt(struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool first, bool print_key, bool compact);
#define UCL_EMIT_TYPE_OPS(type) \
static void ucl_emit_ ## type ## _elt (struct ucl_emitter_context *ctx, \
const ucl_object_t *obj, bool first, bool print_key); \
static void ucl_emit_ ## type ## _start_obj (struct ucl_emitter_context *ctx, \
const ucl_object_t *obj, bool first, bool print_key); \
static void ucl_emit_ ## type## _start_array (struct ucl_emitter_context *ctx, \
const ucl_object_t *obj, bool first, bool print_key); \
static void ucl_emit_ ##type## _end_object (struct ucl_emitter_context *ctx, \
const ucl_object_t *obj); \
static void ucl_emit_ ##type## _end_array (struct ucl_emitter_context *ctx, \
const ucl_object_t *obj)
#define UCL_EMIT_TYPE_OPS(type) \
static void ucl_emit_##type##_elt(struct ucl_emitter_context *ctx, \
const ucl_object_t *obj, bool first, bool print_key); \
static void ucl_emit_##type##_start_obj(struct ucl_emitter_context *ctx, \
const ucl_object_t *obj, bool first, bool print_key); \
static void ucl_emit_##type##_start_array(struct ucl_emitter_context *ctx, \
const ucl_object_t *obj, bool first, bool print_key); \
static void ucl_emit_##type##_end_object(struct ucl_emitter_context *ctx, \
const ucl_object_t *obj); \
static void ucl_emit_##type##_end_array(struct ucl_emitter_context *ctx, \
const ucl_object_t *obj)
/*
* JSON format operations
@ -64,27 +64,25 @@ UCL_EMIT_TYPE_OPS(config);
UCL_EMIT_TYPE_OPS(yaml);
UCL_EMIT_TYPE_OPS(msgpack);
#define UCL_EMIT_TYPE_CONTENT(type) { \
.ucl_emitter_write_elt = ucl_emit_ ## type ## _elt, \
.ucl_emitter_start_object = ucl_emit_ ## type ##_start_obj, \
.ucl_emitter_start_array = ucl_emit_ ## type ##_start_array, \
.ucl_emitter_end_object = ucl_emit_ ## type ##_end_object, \
.ucl_emitter_end_array = ucl_emit_ ## type ##_end_array \
}
#define UCL_EMIT_TYPE_CONTENT(type) { \
.ucl_emitter_write_elt = ucl_emit_##type##_elt, \
.ucl_emitter_start_object = ucl_emit_##type##_start_obj, \
.ucl_emitter_start_array = ucl_emit_##type##_start_array, \
.ucl_emitter_end_object = ucl_emit_##type##_end_object, \
.ucl_emitter_end_array = ucl_emit_##type##_end_array}
const struct ucl_emitter_operations ucl_standartd_emitter_ops[] = {
[UCL_EMIT_JSON] = UCL_EMIT_TYPE_CONTENT(json),
[UCL_EMIT_JSON_COMPACT] = UCL_EMIT_TYPE_CONTENT(json_compact),
[UCL_EMIT_CONFIG] = UCL_EMIT_TYPE_CONTENT(config),
[UCL_EMIT_YAML] = UCL_EMIT_TYPE_CONTENT(yaml),
[UCL_EMIT_MSGPACK] = UCL_EMIT_TYPE_CONTENT(msgpack)
};
[UCL_EMIT_MSGPACK] = UCL_EMIT_TYPE_CONTENT(msgpack)};
/*
* Utility to check whether we need a top object
*/
#define UCL_EMIT_IDENT_TOP_OBJ(ctx, obj) ((ctx)->top != (obj) || \
((ctx)->id == UCL_EMIT_JSON_COMPACT || (ctx)->id == UCL_EMIT_JSON))
((ctx)->id == UCL_EMIT_JSON_COMPACT || (ctx)->id == UCL_EMIT_JSON))
/**
@ -93,11 +91,11 @@ const struct ucl_emitter_operations ucl_standartd_emitter_ops[] = {
* @param tabs number of tabs to add
*/
static inline void
ucl_add_tabs (const struct ucl_emitter_functions *func, unsigned int tabs,
bool compact)
ucl_add_tabs(const struct ucl_emitter_functions *func, unsigned int tabs,
bool compact)
{
if (!compact && tabs > 0) {
func->ucl_emitter_append_character (' ', tabs * 4, func->ud);
func->ucl_emitter_append_character(' ', tabs * 4, func->ud);
}
}
@ -107,8 +105,8 @@ ucl_add_tabs (const struct ucl_emitter_functions *func, unsigned int tabs,
* @param obj
*/
static void
ucl_emitter_print_key (bool print_key, struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool compact)
ucl_emitter_print_key(bool print_key, struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool compact)
{
const struct ucl_emitter_functions *func = ctx->func;
@ -118,52 +116,52 @@ ucl_emitter_print_key (bool print_key, struct ucl_emitter_context *ctx,
if (ctx->id == UCL_EMIT_CONFIG) {
if (obj->flags & UCL_OBJECT_NEED_KEY_ESCAPE) {
ucl_elt_string_write_json (obj->key, obj->keylen, ctx);
ucl_elt_string_write_json(obj->key, obj->keylen, ctx);
}
else {
func->ucl_emitter_append_len (obj->key, obj->keylen, func->ud);
func->ucl_emitter_append_len(obj->key, obj->keylen, func->ud);
}
if (obj->type != UCL_OBJECT && obj->type != UCL_ARRAY) {
func->ucl_emitter_append_len (" = ", 3, func->ud);
func->ucl_emitter_append_len(" = ", 3, func->ud);
}
else {
func->ucl_emitter_append_character (' ', 1, func->ud);
func->ucl_emitter_append_character(' ', 1, func->ud);
}
}
else if (ctx->id == UCL_EMIT_YAML) {
if (obj->keylen > 0 && (obj->flags & UCL_OBJECT_NEED_KEY_ESCAPE)) {
ucl_elt_string_write_json (obj->key, obj->keylen, ctx);
ucl_elt_string_write_json(obj->key, obj->keylen, ctx);
}
else if (obj->keylen > 0) {
func->ucl_emitter_append_len (obj->key, obj->keylen, func->ud);
func->ucl_emitter_append_len(obj->key, obj->keylen, func->ud);
}
else {
func->ucl_emitter_append_len ("null", 4, func->ud);
func->ucl_emitter_append_len("null", 4, func->ud);
}
func->ucl_emitter_append_len (": ", 2, func->ud);
func->ucl_emitter_append_len(": ", 2, func->ud);
}
else {
if (obj->keylen > 0) {
ucl_elt_string_write_json (obj->key, obj->keylen, ctx);
ucl_elt_string_write_json(obj->key, obj->keylen, ctx);
}
else {
func->ucl_emitter_append_len ("null", 4, func->ud);
func->ucl_emitter_append_len("null", 4, func->ud);
}
if (compact) {
func->ucl_emitter_append_character (':', 1, func->ud);
func->ucl_emitter_append_character(':', 1, func->ud);
}
else {
func->ucl_emitter_append_len (": ", 2, func->ud);
func->ucl_emitter_append_len(": ", 2, func->ud);
}
}
}
static void
ucl_emitter_finish_object (struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool compact, bool is_array)
ucl_emitter_finish_object(struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool compact, bool is_array)
{
const struct ucl_emitter_functions *func = ctx->func;
@ -171,15 +169,15 @@ ucl_emitter_finish_object (struct ucl_emitter_context *ctx,
if (obj->type != UCL_OBJECT && obj->type != UCL_ARRAY) {
if (!is_array) {
/* Objects are split by ';' */
func->ucl_emitter_append_len (";\n", 2, func->ud);
func->ucl_emitter_append_len(";\n", 2, func->ud);
}
else {
/* Use commas for arrays */
func->ucl_emitter_append_len (",\n", 2, func->ud);
func->ucl_emitter_append_len(",\n", 2, func->ud);
}
}
else {
func->ucl_emitter_append_character ('\n', 1, func->ud);
func->ucl_emitter_append_character('\n', 1, func->ud);
}
}
}
@ -190,27 +188,27 @@ ucl_emitter_finish_object (struct ucl_emitter_context *ctx,
* @param compact compact flag
*/
static void
ucl_emitter_common_end_object (struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool compact)
ucl_emitter_common_end_object(struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool compact)
{
const struct ucl_emitter_functions *func = ctx->func;
if (UCL_EMIT_IDENT_TOP_OBJ(ctx, obj)) {
ctx->indent --;
ctx->indent--;
if (compact) {
func->ucl_emitter_append_character ('}', 1, func->ud);
func->ucl_emitter_append_character('}', 1, func->ud);
}
else {
if (ctx->id != UCL_EMIT_CONFIG) {
/* newline is already added for this format */
func->ucl_emitter_append_character ('\n', 1, func->ud);
func->ucl_emitter_append_character('\n', 1, func->ud);
}
ucl_add_tabs (func, ctx->indent, compact);
func->ucl_emitter_append_character ('}', 1, func->ud);
ucl_add_tabs(func, ctx->indent, compact);
func->ucl_emitter_append_character('}', 1, func->ud);
}
}
ucl_emitter_finish_object (ctx, obj, compact, false);
ucl_emitter_finish_object(ctx, obj, compact, false);
}
/**
@ -219,25 +217,25 @@ ucl_emitter_common_end_object (struct ucl_emitter_context *ctx,
* @param compact compact flag
*/
static void
ucl_emitter_common_end_array (struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool compact)
ucl_emitter_common_end_array(struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool compact)
{
const struct ucl_emitter_functions *func = ctx->func;
ctx->indent --;
ctx->indent--;
if (compact) {
func->ucl_emitter_append_character (']', 1, func->ud);
func->ucl_emitter_append_character(']', 1, func->ud);
}
else {
if (ctx->id != UCL_EMIT_CONFIG) {
/* newline is already added for this format */
func->ucl_emitter_append_character ('\n', 1, func->ud);
func->ucl_emitter_append_character('\n', 1, func->ud);
}
ucl_add_tabs (func, ctx->indent, compact);
func->ucl_emitter_append_character (']', 1, func->ud);
ucl_add_tabs(func, ctx->indent, compact);
func->ucl_emitter_append_character(']', 1, func->ud);
}
ucl_emitter_finish_object (ctx, obj, compact, true);
ucl_emitter_finish_object(ctx, obj, compact, true);
}
/**
@ -247,8 +245,8 @@ ucl_emitter_common_end_array (struct ucl_emitter_context *ctx,
* @param compact compact flag
*/
static void
ucl_emitter_common_start_array (struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool first, bool print_key, bool compact)
ucl_emitter_common_start_array(struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool first, bool print_key, bool compact)
{
const ucl_object_t *cur;
ucl_object_iter_t iter = NULL;
@ -257,33 +255,34 @@ ucl_emitter_common_start_array (struct ucl_emitter_context *ctx,
if (ctx->id != UCL_EMIT_CONFIG && !first) {
if (compact) {
func->ucl_emitter_append_character (',', 1, func->ud);
func->ucl_emitter_append_character(',', 1, func->ud);
}
else {
if (ctx->id == UCL_EMIT_YAML && ctx->indent == 0) {
func->ucl_emitter_append_len ("\n", 1, func->ud);
} else {
func->ucl_emitter_append_len (",\n", 2, func->ud);
func->ucl_emitter_append_len("\n", 1, func->ud);
}
else {
func->ucl_emitter_append_len(",\n", 2, func->ud);
}
}
ucl_add_tabs (func, ctx->indent, compact);
ucl_add_tabs(func, ctx->indent, compact);
}
ucl_emitter_print_key (print_key, ctx, obj, compact);
ucl_emitter_print_key(print_key, ctx, obj, compact);
if (compact) {
func->ucl_emitter_append_character ('[', 1, func->ud);
func->ucl_emitter_append_character('[', 1, func->ud);
}
else {
func->ucl_emitter_append_len ("[\n", 2, func->ud);
func->ucl_emitter_append_len("[\n", 2, func->ud);
}
ctx->indent ++;
ctx->indent++;
if (obj->type == UCL_ARRAY) {
/* explicit array */
while ((cur = ucl_object_iterate (obj, &iter, true)) != NULL) {
ucl_emitter_common_elt (ctx, cur, first_key, false, compact);
while ((cur = ucl_object_iterate(obj, &iter, true)) != NULL) {
ucl_emitter_common_elt(ctx, cur, first_key, false, compact);
first_key = false;
}
}
@ -291,13 +290,11 @@ ucl_emitter_common_start_array (struct ucl_emitter_context *ctx,
/* implicit array */
cur = obj;
while (cur) {
ucl_emitter_common_elt (ctx, cur, first_key, false, compact);
ucl_emitter_common_elt(ctx, cur, first_key, false, compact);
first_key = false;
cur = cur->next;
}
}
}
/**
@ -307,8 +304,8 @@ ucl_emitter_common_start_array (struct ucl_emitter_context *ctx,
* @param compact compact flag
*/
static void
ucl_emitter_common_start_object (struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool first, bool print_key, bool compact)
ucl_emitter_common_start_object(struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool first, bool print_key, bool compact)
{
ucl_hash_iter_t it = NULL;
const ucl_object_t *cur, *elt;
@ -317,57 +314,53 @@ ucl_emitter_common_start_object (struct ucl_emitter_context *ctx,
if (ctx->id != UCL_EMIT_CONFIG && !first) {
if (compact) {
func->ucl_emitter_append_character (',', 1, func->ud);
func->ucl_emitter_append_character(',', 1, func->ud);
}
else {
if (ctx->id == UCL_EMIT_YAML && ctx->indent == 0) {
func->ucl_emitter_append_len ("\n", 1, func->ud);
} else {
func->ucl_emitter_append_len (",\n", 2, func->ud);
func->ucl_emitter_append_len("\n", 1, func->ud);
}
else {
func->ucl_emitter_append_len(",\n", 2, func->ud);
}
}
ucl_add_tabs (func, ctx->indent, compact);
ucl_add_tabs(func, ctx->indent, compact);
}
ucl_emitter_print_key (print_key, ctx, obj, compact);
ucl_emitter_print_key(print_key, ctx, obj, compact);
/*
* Print <ident_level>{
* <ident_level + 1><object content>
*/
if (UCL_EMIT_IDENT_TOP_OBJ(ctx, obj)) {
if (compact) {
func->ucl_emitter_append_character ('{', 1, func->ud);
func->ucl_emitter_append_character('{', 1, func->ud);
}
else {
func->ucl_emitter_append_len ("{\n", 2, func->ud);
func->ucl_emitter_append_len("{\n", 2, func->ud);
}
ctx->indent ++;
ctx->indent++;
}
while ((cur = ucl_hash_iterate (obj->value.ov, &it))) {
while ((cur = ucl_hash_iterate(obj->value.ov, &it))) {
if (ctx->id == UCL_EMIT_CONFIG) {
LL_FOREACH (cur, elt) {
ucl_emitter_common_elt (ctx, elt, first_key, true, compact);
LL_FOREACH(cur, elt)
{
ucl_emitter_common_elt(ctx, elt, first_key, true, compact);
}
}
else {
/* Expand implicit arrays */
if (cur->next != NULL) {
if (!first_key) {
if (compact) {
func->ucl_emitter_append_character (',', 1, func->ud);
}
else {
func->ucl_emitter_append_len (",\n", 2, func->ud);
}
if (first_key) {
ucl_add_tabs(func, ctx->indent, compact);
}
ucl_add_tabs (func, ctx->indent, compact);
ucl_emitter_common_start_array (ctx, cur, first_key, true, compact);
ucl_emitter_common_end_array (ctx, cur, compact);
ucl_emitter_common_start_array(ctx, cur, first_key, true, compact);
ucl_emitter_common_end_array(ctx, cur, compact);
}
else {
ucl_emitter_common_elt (ctx, cur, first_key, true, compact);
ucl_emitter_common_elt(ctx, cur, first_key, true, compact);
}
}
@ -384,8 +377,8 @@ ucl_emitter_common_start_object (struct ucl_emitter_context *ctx,
* @param compact compact output
*/
static void
ucl_emitter_common_elt (struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool first, bool print_key, bool compact)
ucl_emitter_common_elt(struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool first, bool print_key, bool compact)
{
const struct ucl_emitter_functions *func = ctx->func;
bool flag;
@ -395,31 +388,33 @@ ucl_emitter_common_elt (struct ucl_emitter_context *ctx,
if (ctx->id != UCL_EMIT_CONFIG && !first) {
if (compact) {
func->ucl_emitter_append_character (',', 1, func->ud);
func->ucl_emitter_append_character(',', 1, func->ud);
}
else {
if (ctx->id == UCL_EMIT_YAML && ctx->indent == 0) {
func->ucl_emitter_append_len ("\n", 1, func->ud);
} else {
func->ucl_emitter_append_len (",\n", 2, func->ud);
func->ucl_emitter_append_len("\n", 1, func->ud);
}
else {
func->ucl_emitter_append_len(",\n", 2, func->ud);
}
}
}
ucl_add_tabs (func, ctx->indent, compact);
ucl_add_tabs(func, ctx->indent, compact);
if (ctx->comments && ctx->id == UCL_EMIT_CONFIG) {
comment = ucl_object_lookup_len (ctx->comments, (const char *)&obj,
sizeof (void *));
comment = ucl_object_lookup_len(ctx->comments, (const char *) &obj,
sizeof(void *));
if (comment) {
if (!(comment->flags & UCL_OBJECT_INHERITED)) {
DL_FOREACH (comment, cur_comment) {
func->ucl_emitter_append_len (cur_comment->value.sv,
cur_comment->len,
func->ud);
func->ucl_emitter_append_character ('\n', 1, func->ud);
ucl_add_tabs (func, ctx->indent, compact);
DL_FOREACH(comment, cur_comment)
{
func->ucl_emitter_append_len(cur_comment->value.sv,
cur_comment->len,
func->ud);
func->ucl_emitter_append_character('\n', 1, func->ud);
ucl_add_tabs(func, ctx->indent, compact);
}
comment = NULL;
@ -429,81 +424,84 @@ ucl_emitter_common_elt (struct ucl_emitter_context *ctx,
switch (obj->type) {
case UCL_INT:
ucl_emitter_print_key (print_key, ctx, obj, compact);
func->ucl_emitter_append_int (ucl_object_toint (obj), func->ud);
ucl_emitter_finish_object (ctx, obj, compact, !print_key);
ucl_emitter_print_key(print_key, ctx, obj, compact);
func->ucl_emitter_append_int(ucl_object_toint(obj), func->ud);
ucl_emitter_finish_object(ctx, obj, compact, !print_key);
break;
case UCL_FLOAT:
case UCL_TIME:
ucl_emitter_print_key (print_key, ctx, obj, compact);
func->ucl_emitter_append_double (ucl_object_todouble (obj), func->ud);
ucl_emitter_finish_object (ctx, obj, compact, !print_key);
ucl_emitter_print_key(print_key, ctx, obj, compact);
func->ucl_emitter_append_double(ucl_object_todouble(obj), func->ud);
ucl_emitter_finish_object(ctx, obj, compact, !print_key);
break;
case UCL_BOOLEAN:
ucl_emitter_print_key (print_key, ctx, obj, compact);
flag = ucl_object_toboolean (obj);
ucl_emitter_print_key(print_key, ctx, obj, compact);
flag = ucl_object_toboolean(obj);
if (flag) {
func->ucl_emitter_append_len ("true", 4, func->ud);
func->ucl_emitter_append_len("true", 4, func->ud);
}
else {
func->ucl_emitter_append_len ("false", 5, func->ud);
func->ucl_emitter_append_len("false", 5, func->ud);
}
ucl_emitter_finish_object (ctx, obj, compact, !print_key);
ucl_emitter_finish_object(ctx, obj, compact, !print_key);
break;
case UCL_STRING:
ucl_emitter_print_key (print_key, ctx, obj, compact);
ucl_emitter_print_key(print_key, ctx, obj, compact);
if (ctx->id == UCL_EMIT_CONFIG) {
if (ucl_maybe_long_string (obj)) {
ucl_elt_string_write_multiline (obj->value.sv, obj->len, ctx);
} else {
if (ucl_maybe_long_string(obj)) {
ucl_elt_string_write_multiline(obj->value.sv, obj->len, ctx);
}
else {
if (obj->flags & UCL_OBJECT_SQUOTED) {
ucl_elt_string_write_squoted (obj->value.sv, obj->len, ctx);
} else {
ucl_elt_string_write_json (obj->value.sv, obj->len, ctx);
ucl_elt_string_write_squoted(obj->value.sv, obj->len, ctx);
}
else {
ucl_elt_string_write_json(obj->value.sv, obj->len, ctx);
}
}
}
else {
ucl_elt_string_write_json (obj->value.sv, obj->len, ctx);
ucl_elt_string_write_json(obj->value.sv, obj->len, ctx);
}
ucl_emitter_finish_object (ctx, obj, compact, !print_key);
ucl_emitter_finish_object(ctx, obj, compact, !print_key);
break;
case UCL_NULL:
ucl_emitter_print_key (print_key, ctx, obj, compact);
func->ucl_emitter_append_len ("null", 4, func->ud);
ucl_emitter_finish_object (ctx, obj, compact, !print_key);
ucl_emitter_print_key(print_key, ctx, obj, compact);
func->ucl_emitter_append_len("null", 4, func->ud);
ucl_emitter_finish_object(ctx, obj, compact, !print_key);
break;
case UCL_OBJECT:
ucl_emitter_common_start_object (ctx, obj, true, print_key, compact);
ucl_emitter_common_end_object (ctx, obj, compact);
ucl_emitter_common_start_object(ctx, obj, true, print_key, compact);
ucl_emitter_common_end_object(ctx, obj, compact);
break;
case UCL_ARRAY:
ucl_emitter_common_start_array (ctx, obj, true, print_key, compact);
ucl_emitter_common_end_array (ctx, obj, compact);
ucl_emitter_common_start_array(ctx, obj, true, print_key, compact);
ucl_emitter_common_end_array(ctx, obj, compact);
break;
case UCL_USERDATA:
ud = (struct ucl_object_userdata *)obj;
ucl_emitter_print_key (print_key, ctx, obj, compact);
ud = (struct ucl_object_userdata *) obj;
ucl_emitter_print_key(print_key, ctx, obj, compact);
if (ud->emitter) {
ud_out = ud->emitter (obj->value.ud);
ud_out = ud->emitter(obj->value.ud);
if (ud_out == NULL) {
ud_out = "null";
}
}
ucl_elt_string_write_json (ud_out, strlen (ud_out), ctx);
ucl_emitter_finish_object (ctx, obj, compact, !print_key);
ucl_elt_string_write_json(ud_out, strlen(ud_out), ctx);
ucl_emitter_finish_object(ctx, obj, compact, !print_key);
break;
}
if (comment) {
DL_FOREACH (comment, cur_comment) {
func->ucl_emitter_append_len (cur_comment->value.sv,
cur_comment->len,
func->ud);
func->ucl_emitter_append_character ('\n', 1, func->ud);
DL_FOREACH(comment, cur_comment)
{
func->ucl_emitter_append_len(cur_comment->value.sv,
cur_comment->len,
func->ud);
func->ucl_emitter_append_character('\n', 1, func->ud);
if (cur_comment->next) {
ucl_add_tabs (func, ctx->indent, compact);
ucl_add_tabs(func, ctx->indent, compact);
}
}
}
@ -512,26 +510,31 @@ ucl_emitter_common_elt (struct ucl_emitter_context *ctx,
/*
* Specific standard implementations of the emitter functions
*/
#define UCL_EMIT_TYPE_IMPL(type, compact) \
static void ucl_emit_ ## type ## _elt (struct ucl_emitter_context *ctx, \
const ucl_object_t *obj, bool first, bool print_key) { \
ucl_emitter_common_elt (ctx, obj, first, print_key, (compact)); \
} \
static void ucl_emit_ ## type ## _start_obj (struct ucl_emitter_context *ctx, \
const ucl_object_t *obj, bool first, bool print_key) { \
ucl_emitter_common_start_object (ctx, obj, first, print_key, (compact)); \
} \
static void ucl_emit_ ## type## _start_array (struct ucl_emitter_context *ctx, \
const ucl_object_t *obj, bool first, bool print_key) { \
ucl_emitter_common_start_array (ctx, obj, first, print_key, (compact)); \
} \
static void ucl_emit_ ##type## _end_object (struct ucl_emitter_context *ctx, \
const ucl_object_t *obj) { \
ucl_emitter_common_end_object (ctx, obj, (compact)); \
} \
static void ucl_emit_ ##type## _end_array (struct ucl_emitter_context *ctx, \
const ucl_object_t *obj) { \
ucl_emitter_common_end_array (ctx, obj, (compact)); \
#define UCL_EMIT_TYPE_IMPL(type, compact) \
static void ucl_emit_##type##_elt(struct ucl_emitter_context *ctx, \
const ucl_object_t *obj, bool first, bool print_key) \
{ \
ucl_emitter_common_elt(ctx, obj, first, print_key, (compact)); \
} \
static void ucl_emit_##type##_start_obj(struct ucl_emitter_context *ctx, \
const ucl_object_t *obj, bool first, bool print_key) \
{ \
ucl_emitter_common_start_object(ctx, obj, first, print_key, (compact)); \
} \
static void ucl_emit_##type##_start_array(struct ucl_emitter_context *ctx, \
const ucl_object_t *obj, bool first, bool print_key) \
{ \
ucl_emitter_common_start_array(ctx, obj, first, print_key, (compact)); \
} \
static void ucl_emit_##type##_end_object(struct ucl_emitter_context *ctx, \
const ucl_object_t *obj) \
{ \
ucl_emitter_common_end_object(ctx, obj, (compact)); \
} \
static void ucl_emit_##type##_end_array(struct ucl_emitter_context *ctx, \
const ucl_object_t *obj) \
{ \
ucl_emitter_common_end_array(ctx, obj, (compact)); \
}
UCL_EMIT_TYPE_IMPL(json, false)
@ -540,8 +543,8 @@ UCL_EMIT_TYPE_IMPL(config, false)
UCL_EMIT_TYPE_IMPL(yaml, false)
static void
ucl_emit_msgpack_elt (struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool _first, bool print_key)
ucl_emit_msgpack_elt(struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool _first, bool print_key)
{
ucl_object_iter_t it;
struct ucl_object_userdata *ud;
@ -550,46 +553,47 @@ ucl_emit_msgpack_elt (struct ucl_emitter_context *ctx,
switch (obj->type) {
case UCL_INT:
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
ucl_emitter_print_int_msgpack (ctx, ucl_object_toint (obj));
ucl_emitter_print_key_msgpack(print_key, ctx, obj);
ucl_emitter_print_int_msgpack(ctx, ucl_object_toint(obj));
break;
case UCL_FLOAT:
case UCL_TIME:
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
ucl_emitter_print_double_msgpack (ctx, ucl_object_todouble (obj));
ucl_emitter_print_key_msgpack(print_key, ctx, obj);
ucl_emitter_print_double_msgpack(ctx, ucl_object_todouble(obj));
break;
case UCL_BOOLEAN:
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
ucl_emitter_print_bool_msgpack (ctx, ucl_object_toboolean (obj));
ucl_emitter_print_key_msgpack(print_key, ctx, obj);
ucl_emitter_print_bool_msgpack(ctx, ucl_object_toboolean(obj));
break;
case UCL_STRING:
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
ucl_emitter_print_key_msgpack(print_key, ctx, obj);
if (obj->flags & UCL_OBJECT_BINARY) {
ucl_emitter_print_binary_string_msgpack (ctx, obj->value.sv,
obj->len);
ucl_emitter_print_binary_string_msgpack(ctx, obj->value.sv,
obj->len);
}
else {
ucl_emitter_print_string_msgpack (ctx, obj->value.sv, obj->len);
ucl_emitter_print_string_msgpack(ctx, obj->value.sv, obj->len);
}
break;
case UCL_NULL:
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
ucl_emitter_print_null_msgpack (ctx);
ucl_emitter_print_key_msgpack(print_key, ctx, obj);
ucl_emitter_print_null_msgpack(ctx);
break;
case UCL_OBJECT:
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
ucl_emit_msgpack_start_obj (ctx, obj, false, print_key);
ucl_emitter_print_key_msgpack(print_key, ctx, obj);
ucl_emit_msgpack_start_obj(ctx, obj, false, print_key);
it = NULL;
while ((cur = ucl_object_iterate (obj, &it, true)) != NULL) {
LL_FOREACH (cur, celt) {
ucl_emit_msgpack_elt (ctx, celt, false, true);
while ((cur = ucl_object_iterate(obj, &it, true)) != NULL) {
LL_FOREACH(cur, celt)
{
ucl_emit_msgpack_elt(ctx, celt, false, true);
/* XXX:
* in msgpack the length of objects is encoded within a single elt
* so in case of multi-value keys we are using merely the first
@ -602,68 +606,66 @@ ucl_emit_msgpack_elt (struct ucl_emitter_context *ctx,
break;
case UCL_ARRAY:
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
ucl_emit_msgpack_start_array (ctx, obj, false, print_key);
ucl_emitter_print_key_msgpack(print_key, ctx, obj);
ucl_emit_msgpack_start_array(ctx, obj, false, print_key);
it = NULL;
while ((cur = ucl_object_iterate (obj, &it, true)) != NULL) {
ucl_emit_msgpack_elt (ctx, cur, false, false);
while ((cur = ucl_object_iterate(obj, &it, true)) != NULL) {
ucl_emit_msgpack_elt(ctx, cur, false, false);
}
break;
case UCL_USERDATA:
ud = (struct ucl_object_userdata *)obj;
ucl_emitter_print_key_msgpack (print_key, ctx, obj);
ud = (struct ucl_object_userdata *) obj;
ucl_emitter_print_key_msgpack(print_key, ctx, obj);
if (ud->emitter) {
ud_out = ud->emitter (obj->value.ud);
ud_out = ud->emitter(obj->value.ud);
if (ud_out == NULL) {
ud_out = "null";
}
}
ucl_emitter_print_string_msgpack (ctx, obj->value.sv, obj->len);
ucl_emitter_print_string_msgpack(ctx, obj->value.sv, obj->len);
break;
}
}
static void
ucl_emit_msgpack_start_obj (struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool _first, bool _print_key)
ucl_emit_msgpack_start_obj(struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool _first, bool _print_key)
{
ucl_emitter_print_object_msgpack (ctx, obj->len);
ucl_emitter_print_object_msgpack(ctx, obj->len);
}
static void
ucl_emit_msgpack_start_array (struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool _first, bool _print_key)
ucl_emit_msgpack_start_array(struct ucl_emitter_context *ctx,
const ucl_object_t *obj, bool _first, bool _print_key)
{
ucl_emitter_print_array_msgpack (ctx, obj->len);
ucl_emitter_print_array_msgpack(ctx, obj->len);
}
static void
ucl_emit_msgpack_end_object (struct ucl_emitter_context *ctx,
const ucl_object_t *obj)
ucl_emit_msgpack_end_object(struct ucl_emitter_context *ctx,
const ucl_object_t *obj)
{
}
static void
ucl_emit_msgpack_end_array (struct ucl_emitter_context *ctx,
const ucl_object_t *obj)
ucl_emit_msgpack_end_array(struct ucl_emitter_context *ctx,
const ucl_object_t *obj)
{
}
unsigned char *
ucl_object_emit (const ucl_object_t *obj, enum ucl_emitter emit_type)
ucl_object_emit(const ucl_object_t *obj, enum ucl_emitter emit_type)
{
return ucl_object_emit_len (obj, emit_type, NULL);
return ucl_object_emit_len(obj, emit_type, NULL);
}
unsigned char *
ucl_object_emit_len (const ucl_object_t *obj, enum ucl_emitter emit_type,
size_t *outlen)
ucl_object_emit_len(const ucl_object_t *obj, enum ucl_emitter emit_type,
size_t *outlen)
{
unsigned char *res = NULL;
struct ucl_emitter_functions *func;
@ -673,40 +675,39 @@ ucl_object_emit_len (const ucl_object_t *obj, enum ucl_emitter emit_type,
return NULL;
}
func = ucl_object_emit_memory_funcs ((void **)&res);
func = ucl_object_emit_memory_funcs((void **) &res);
if (func != NULL) {
s = func->ud;
ucl_object_emit_full (obj, emit_type, func, NULL);
ucl_object_emit_full(obj, emit_type, func, NULL);
if (outlen != NULL) {
*outlen = s->i;
}
ucl_object_emit_funcs_free (func);
ucl_object_emit_funcs_free(func);
}
return res;
}
bool
ucl_object_emit_full (const ucl_object_t *obj, enum ucl_emitter emit_type,
struct ucl_emitter_functions *emitter,
const ucl_object_t *comments)
bool ucl_object_emit_full(const ucl_object_t *obj, enum ucl_emitter emit_type,
struct ucl_emitter_functions *emitter,
const ucl_object_t *comments)
{
const struct ucl_emitter_context *ctx;
struct ucl_emitter_context my_ctx;
bool res = false;
ctx = ucl_emit_get_standard_context (emit_type);
ctx = ucl_emit_get_standard_context(emit_type);
if (ctx != NULL) {
memcpy (&my_ctx, ctx, sizeof (my_ctx));
memcpy(&my_ctx, ctx, sizeof(my_ctx));
my_ctx.func = emitter;
my_ctx.indent = 0;
my_ctx.top = obj;
my_ctx.comments = comments;
my_ctx.ops->ucl_emitter_write_elt (&my_ctx, obj, true, false);
my_ctx.ops->ucl_emitter_write_elt(&my_ctx, obj, true, false);
res = true;
}

View file

@ -57,39 +57,38 @@ struct ucl_emitter_context_streamline {
struct ucl_emitter_streamline_stack *containers;
};
#define TO_STREAMLINE(ctx) (struct ucl_emitter_context_streamline *)(ctx)
#define TO_STREAMLINE(ctx) (struct ucl_emitter_context_streamline *) (ctx)
struct ucl_emitter_context*
ucl_object_emit_streamline_new (const ucl_object_t *obj,
enum ucl_emitter emit_type,
struct ucl_emitter_functions *emitter)
struct ucl_emitter_context *
ucl_object_emit_streamline_new(const ucl_object_t *obj,
enum ucl_emitter emit_type,
struct ucl_emitter_functions *emitter)
{
const struct ucl_emitter_context *ctx;
struct ucl_emitter_context_streamline *sctx;
ctx = ucl_emit_get_standard_context (emit_type);
ctx = ucl_emit_get_standard_context(emit_type);
if (ctx == NULL) {
return NULL;
}
sctx = calloc (1, sizeof (*sctx));
sctx = calloc(1, sizeof(*sctx));
if (sctx == NULL) {
return NULL;
}
memcpy (sctx, ctx, sizeof (*ctx));
memcpy(sctx, ctx, sizeof(*ctx));
sctx->func = emitter;
sctx->top = obj;
ucl_object_emit_streamline_start_container ((struct ucl_emitter_context *)sctx,
obj);
ucl_object_emit_streamline_start_container((struct ucl_emitter_context *) sctx,
obj);
return (struct ucl_emitter_context *)sctx;
return (struct ucl_emitter_context *) sctx;
}
void
ucl_object_emit_streamline_start_container (struct ucl_emitter_context *ctx,
const ucl_object_t *obj)
bool ucl_object_emit_streamline_start_container(struct ucl_emitter_context *ctx,
const ucl_object_t *obj)
{
struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx);
struct ucl_emitter_streamline_stack *st, *top;
@ -101,7 +100,7 @@ ucl_object_emit_streamline_start_container (struct ucl_emitter_context *ctx,
}
top = sctx->containers;
st = malloc (sizeof (*st));
st = malloc(sizeof(*st));
if (st != NULL) {
st->empty = true;
if (top && !top->is_array) {
@ -111,19 +110,26 @@ ucl_object_emit_streamline_start_container (struct ucl_emitter_context *ctx,
st->obj = obj;
if (obj != NULL && obj->type == UCL_ARRAY) {
st->is_array = true;
sctx->ops->ucl_emitter_start_array (ctx, obj, top == NULL, print_key);
sctx->ops->ucl_emitter_start_array(ctx, obj, top == NULL, print_key);
}
else if (obj != NULL && obj->type == UCL_OBJECT) {
st->is_array = false;
sctx->ops->ucl_emitter_start_object(ctx, obj, top == NULL, print_key);
}
else {
st->is_array = false;
sctx->ops->ucl_emitter_start_object (ctx, obj, top == NULL, print_key);
/* API MISUSE */
free(st);
return false;
}
LL_PREPEND (sctx->containers, st);
LL_PREPEND(sctx->containers, st);
}
return true;
}
void
ucl_object_emit_streamline_add_object (
struct ucl_emitter_context *ctx, const ucl_object_t *obj)
void ucl_object_emit_streamline_add_object(
struct ucl_emitter_context *ctx, const ucl_object_t *obj)
{
struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx);
bool is_array = false, is_first = false;
@ -138,11 +144,10 @@ ucl_object_emit_streamline_add_object (
}
}
sctx->ops->ucl_emitter_write_elt (ctx, obj, is_first, !is_array);
sctx->ops->ucl_emitter_write_elt(ctx, obj, is_first, !is_array);
}
void
ucl_object_emit_streamline_end_container (struct ucl_emitter_context *ctx)
void ucl_object_emit_streamline_end_container(struct ucl_emitter_context *ctx)
{
struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx);
struct ucl_emitter_streamline_stack *st;
@ -151,24 +156,23 @@ ucl_object_emit_streamline_end_container (struct ucl_emitter_context *ctx)
st = sctx->containers;
if (st->is_array) {
sctx->ops->ucl_emitter_end_array (ctx, st->obj);
sctx->ops->ucl_emitter_end_array(ctx, st->obj);
}
else {
sctx->ops->ucl_emitter_end_object (ctx, st->obj);
sctx->ops->ucl_emitter_end_object(ctx, st->obj);
}
sctx->containers = st->next;
free (st);
free(st);
}
}
void
ucl_object_emit_streamline_finish (struct ucl_emitter_context *ctx)
void ucl_object_emit_streamline_finish(struct ucl_emitter_context *ctx)
{
struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx);
while (sctx->containers != NULL) {
ucl_object_emit_streamline_end_container (ctx);
ucl_object_emit_streamline_end_container(ctx);
}
free (sctx);
free(sctx);
}

View file

@ -43,39 +43,17 @@ static const struct ucl_emitter_context ucl_standard_emitters[] = {
.name = "json",
.id = UCL_EMIT_JSON,
.func = NULL,
.ops = &ucl_standartd_emitter_ops[UCL_EMIT_JSON]
},
[UCL_EMIT_JSON_COMPACT] = {
.name = "json_compact",
.id = UCL_EMIT_JSON_COMPACT,
.func = NULL,
.ops = &ucl_standartd_emitter_ops[UCL_EMIT_JSON_COMPACT]
},
[UCL_EMIT_CONFIG] = {
.name = "config",
.id = UCL_EMIT_CONFIG,
.func = NULL,
.ops = &ucl_standartd_emitter_ops[UCL_EMIT_CONFIG]
},
[UCL_EMIT_YAML] = {
.name = "yaml",
.id = UCL_EMIT_YAML,
.func = NULL,
.ops = &ucl_standartd_emitter_ops[UCL_EMIT_YAML]
},
[UCL_EMIT_MSGPACK] = {
.name = "msgpack",
.id = UCL_EMIT_MSGPACK,
.func = NULL,
.ops = &ucl_standartd_emitter_ops[UCL_EMIT_MSGPACK]
}
};
.ops = &ucl_standartd_emitter_ops[UCL_EMIT_JSON]},
[UCL_EMIT_JSON_COMPACT] = {.name = "json_compact", .id = UCL_EMIT_JSON_COMPACT, .func = NULL, .ops = &ucl_standartd_emitter_ops[UCL_EMIT_JSON_COMPACT]},
[UCL_EMIT_CONFIG] = {.name = "config", .id = UCL_EMIT_CONFIG, .func = NULL, .ops = &ucl_standartd_emitter_ops[UCL_EMIT_CONFIG]},
[UCL_EMIT_YAML] = {.name = "yaml", .id = UCL_EMIT_YAML, .func = NULL, .ops = &ucl_standartd_emitter_ops[UCL_EMIT_YAML]},
[UCL_EMIT_MSGPACK] = {.name = "msgpack", .id = UCL_EMIT_MSGPACK, .func = NULL, .ops = &ucl_standartd_emitter_ops[UCL_EMIT_MSGPACK]}};
static inline void
_ucl_emitter_free(void *p)
{
free(p);
free(p);
}
/**
@ -84,7 +62,7 @@ _ucl_emitter_free(void *p)
* @return context or NULL if input is invalid
*/
const struct ucl_emitter_context *
ucl_emit_get_standard_context (enum ucl_emitter emit_type)
ucl_emit_get_standard_context(enum ucl_emitter emit_type)
{
if (emit_type >= UCL_EMIT_JSON && emit_type < UCL_EMIT_MAX) {
return &ucl_standard_emitters[emit_type];
@ -98,132 +76,129 @@ ucl_emit_get_standard_context (enum ucl_emitter emit_type)
* @param str string to emit
* @param buf target buffer
*/
void
ucl_elt_string_write_json (const char *str, size_t size,
struct ucl_emitter_context *ctx)
void ucl_elt_string_write_json(const char *str, size_t size,
struct ucl_emitter_context *ctx)
{
const char *p = str, *c = str;
size_t len = 0;
const struct ucl_emitter_functions *func = ctx->func;
func->ucl_emitter_append_character ('"', 1, func->ud);
func->ucl_emitter_append_character('"', 1, func->ud);
while (size) {
if (ucl_test_character (*p, (UCL_CHARACTER_JSON_UNSAFE|
UCL_CHARACTER_DENIED|
UCL_CHARACTER_WHITESPACE_UNSAFE))) {
if (ucl_test_character(*p, (UCL_CHARACTER_JSON_UNSAFE |
UCL_CHARACTER_DENIED |
UCL_CHARACTER_WHITESPACE_UNSAFE))) {
if (len > 0) {
func->ucl_emitter_append_len (c, len, func->ud);
func->ucl_emitter_append_len(c, len, func->ud);
}
switch (*p) {
case '\n':
func->ucl_emitter_append_len ("\\n", 2, func->ud);
func->ucl_emitter_append_len("\\n", 2, func->ud);
break;
case '\r':
func->ucl_emitter_append_len ("\\r", 2, func->ud);
func->ucl_emitter_append_len("\\r", 2, func->ud);
break;
case '\b':
func->ucl_emitter_append_len ("\\b", 2, func->ud);
func->ucl_emitter_append_len("\\b", 2, func->ud);
break;
case '\t':
func->ucl_emitter_append_len ("\\t", 2, func->ud);
func->ucl_emitter_append_len("\\t", 2, func->ud);
break;
case '\f':
func->ucl_emitter_append_len ("\\f", 2, func->ud);
func->ucl_emitter_append_len("\\f", 2, func->ud);
break;
case '\v':
func->ucl_emitter_append_len ("\\u000B", 6, func->ud);
func->ucl_emitter_append_len("\\u000B", 6, func->ud);
break;
case '\\':
func->ucl_emitter_append_len ("\\\\", 2, func->ud);
func->ucl_emitter_append_len("\\\\", 2, func->ud);
break;
case ' ':
func->ucl_emitter_append_character (' ', 1, func->ud);
func->ucl_emitter_append_character(' ', 1, func->ud);
break;
case '"':
func->ucl_emitter_append_len ("\\\"", 2, func->ud);
func->ucl_emitter_append_len("\\\"", 2, func->ud);
break;
default:
/* Emit unicode unknown character */
func->ucl_emitter_append_len ("\\uFFFD", 6, func->ud);
func->ucl_emitter_append_len("\\uFFFD", 6, func->ud);
break;
}
len = 0;
c = ++p;
}
else {
p ++;
len ++;
p++;
len++;
}
size --;
size--;
}
if (len > 0) {
func->ucl_emitter_append_len (c, len, func->ud);
func->ucl_emitter_append_len(c, len, func->ud);
}
func->ucl_emitter_append_character ('"', 1, func->ud);
func->ucl_emitter_append_character('"', 1, func->ud);
}
void
ucl_elt_string_write_squoted (const char *str, size_t size,
struct ucl_emitter_context *ctx)
void ucl_elt_string_write_squoted(const char *str, size_t size,
struct ucl_emitter_context *ctx)
{
const char *p = str, *c = str;
size_t len = 0;
const struct ucl_emitter_functions *func = ctx->func;
func->ucl_emitter_append_character ('\'', 1, func->ud);
func->ucl_emitter_append_character('\'', 1, func->ud);
while (size) {
if (*p == '\'') {
if (len > 0) {
func->ucl_emitter_append_len (c, len, func->ud);
func->ucl_emitter_append_len(c, len, func->ud);
}
len = 0;
c = ++p;
func->ucl_emitter_append_len ("\\\'", 2, func->ud);
func->ucl_emitter_append_len("\\\'", 2, func->ud);
}
else {
p ++;
len ++;
p++;
len++;
}
size --;
size--;
}
if (len > 0) {
func->ucl_emitter_append_len (c, len, func->ud);
func->ucl_emitter_append_len(c, len, func->ud);
}
func->ucl_emitter_append_character ('\'', 1, func->ud);
func->ucl_emitter_append_character('\'', 1, func->ud);
}
void
ucl_elt_string_write_multiline (const char *str, size_t size,
struct ucl_emitter_context *ctx)
void ucl_elt_string_write_multiline(const char *str, size_t size,
struct ucl_emitter_context *ctx)
{
const struct ucl_emitter_functions *func = ctx->func;
func->ucl_emitter_append_len ("<<EOD\n", sizeof ("<<EOD\n") - 1, func->ud);
func->ucl_emitter_append_len (str, size, func->ud);
func->ucl_emitter_append_len ("\nEOD", sizeof ("\nEOD") - 1, func->ud);
func->ucl_emitter_append_len("<<EOD\n", sizeof("<<EOD\n") - 1, func->ud);
func->ucl_emitter_append_len(str, size, func->ud);
func->ucl_emitter_append_len("\nEOD", sizeof("\nEOD") - 1, func->ud);
}
/*
* Generic utstring output
*/
static int
ucl_utstring_append_character (unsigned char c, size_t len, void *ud)
ucl_utstring_append_character(unsigned char c, size_t len, void *ud)
{
UT_string *buf = ud;
if (len == 1) {
utstring_append_c (buf, c);
utstring_append_c(buf, c);
}
else {
utstring_reserve (buf, len + 1);
memset (&buf->d[buf->i], c, len);
utstring_reserve(buf, len + 1);
memset(&buf->d[buf->i], c, len);
buf->i += len;
buf->d[buf->i] = '\0';
}
@ -232,39 +207,39 @@ ucl_utstring_append_character (unsigned char c, size_t len, void *ud)
}
static int
ucl_utstring_append_len (const unsigned char *str, size_t len, void *ud)
ucl_utstring_append_len(const unsigned char *str, size_t len, void *ud)
{
UT_string *buf = ud;
utstring_append_len (buf, str, len);
utstring_append_len(buf, str, len);
return 0;
}
static int
ucl_utstring_append_int (int64_t val, void *ud)
ucl_utstring_append_int(int64_t val, void *ud)
{
UT_string *buf = ud;
utstring_printf (buf, "%jd", (intmax_t)val);
utstring_printf(buf, "%jd", (intmax_t) val);
return 0;
}
static int
ucl_utstring_append_double (double val, void *ud)
ucl_utstring_append_double(double val, void *ud)
{
UT_string *buf = ud;
const double delta = 0.0000001;
if (val == (double)(int)val) {
utstring_printf (buf, "%.1lf", val);
if (val == (double) (int) val) {
utstring_printf(buf, "%.1lf", val);
}
else if (fabs (val - (double)(int)val) < delta) {
else if (fabs(val - (double) (int) val) < delta) {
/* Write at maximum precision */
utstring_printf (buf, "%.*lg", DBL_DIG, val);
utstring_printf(buf, "%.*lg", DBL_DIG, val);
}
else {
utstring_printf (buf, "%lf", val);
utstring_printf(buf, "%lf", val);
}
return 0;
@ -274,52 +249,52 @@ ucl_utstring_append_double (double val, void *ud)
* Generic file output
*/
static int
ucl_file_append_character (unsigned char c, size_t len, void *ud)
ucl_file_append_character(unsigned char c, size_t len, void *ud)
{
FILE *fp = ud;
while (len --) {
fputc (c, fp);
while (len--) {
fputc(c, fp);
}
return 0;
}
static int
ucl_file_append_len (const unsigned char *str, size_t len, void *ud)
ucl_file_append_len(const unsigned char *str, size_t len, void *ud)
{
FILE *fp = ud;
fwrite (str, len, 1, fp);
fwrite(str, len, 1, fp);
return 0;
}
static int
ucl_file_append_int (int64_t val, void *ud)
ucl_file_append_int(int64_t val, void *ud)
{
FILE *fp = ud;
fprintf (fp, "%jd", (intmax_t)val);
fprintf(fp, "%jd", (intmax_t) val);
return 0;
}
static int
ucl_file_append_double (double val, void *ud)
ucl_file_append_double(double val, void *ud)
{
FILE *fp = ud;
const double delta = 0.0000001;
if (val == (double)(int)val) {
fprintf (fp, "%.1lf", val);
if (val == (double) (int) val) {
fprintf(fp, "%.1lf", val);
}
else if (fabs (val - (double)(int)val) < delta) {
else if (fabs(val - (double) (int) val) < delta) {
/* Write at maximum precision */
fprintf (fp, "%.*lg", DBL_DIG, val);
fprintf(fp, "%.*lg", DBL_DIG, val);
}
else {
fprintf (fp, "%lf", val);
fprintf(fp, "%lf", val);
}
return 0;
@ -329,31 +304,31 @@ ucl_file_append_double (double val, void *ud)
* Generic file descriptor writing functions
*/
static int
ucl_fd_append_character (unsigned char c, size_t len, void *ud)
ucl_fd_append_character(unsigned char c, size_t len, void *ud)
{
int fd = *(int *)ud;
int fd = *(int *) ud;
unsigned char *buf;
if (len == 1) {
return write (fd, &c, 1);
return write(fd, &c, 1);
}
else {
buf = malloc (len);
buf = malloc(len);
if (buf == NULL) {
/* Fallback */
while (len --) {
if (write (fd, &c, 1) == -1) {
while (len--) {
if (write(fd, &c, 1) == -1) {
return -1;
}
}
}
else {
memset (buf, c, len);
if (write (fd, buf, len) == -1) {
memset(buf, c, len);
if (write(fd, buf, len) == -1) {
free(buf);
return -1;
}
free (buf);
free(buf);
}
}
@ -361,51 +336,51 @@ ucl_fd_append_character (unsigned char c, size_t len, void *ud)
}
static int
ucl_fd_append_len (const unsigned char *str, size_t len, void *ud)
ucl_fd_append_len(const unsigned char *str, size_t len, void *ud)
{
int fd = *(int *)ud;
int fd = *(int *) ud;
return write (fd, str, len);
return write(fd, str, len);
}
static int
ucl_fd_append_int (int64_t val, void *ud)
ucl_fd_append_int(int64_t val, void *ud)
{
int fd = *(int *)ud;
int fd = *(int *) ud;
char intbuf[64];
snprintf (intbuf, sizeof (intbuf), "%jd", (intmax_t)val);
return write (fd, intbuf, strlen (intbuf));
snprintf(intbuf, sizeof(intbuf), "%jd", (intmax_t) val);
return write(fd, intbuf, strlen(intbuf));
}
static int
ucl_fd_append_double (double val, void *ud)
ucl_fd_append_double(double val, void *ud)
{
int fd = *(int *)ud;
int fd = *(int *) ud;
const double delta = 0.0000001;
char nbuf[64];
if (val == (double)(int)val) {
snprintf (nbuf, sizeof (nbuf), "%.1lf", val);
if (val == (double) (int) val) {
snprintf(nbuf, sizeof(nbuf), "%.1lf", val);
}
else if (fabs (val - (double)(int)val) < delta) {
else if (fabs(val - (double) (int) val) < delta) {
/* Write at maximum precision */
snprintf (nbuf, sizeof (nbuf), "%.*lg", DBL_DIG, val);
snprintf(nbuf, sizeof(nbuf), "%.*lg", DBL_DIG, val);
}
else {
snprintf (nbuf, sizeof (nbuf), "%lf", val);
snprintf(nbuf, sizeof(nbuf), "%lf", val);
}
return write (fd, nbuf, strlen (nbuf));
return write(fd, nbuf, strlen(nbuf));
}
struct ucl_emitter_functions*
ucl_object_emit_memory_funcs (void **pmem)
struct ucl_emitter_functions *
ucl_object_emit_memory_funcs(void **pmem)
{
struct ucl_emitter_functions *f;
UT_string *s;
f = calloc (1, sizeof (*f));
f = calloc(1, sizeof(*f));
if (f != NULL) {
f->ucl_emitter_append_character = ucl_utstring_append_character;
@ -413,7 +388,7 @@ ucl_object_emit_memory_funcs (void **pmem)
f->ucl_emitter_append_int = ucl_utstring_append_int;
f->ucl_emitter_append_len = ucl_utstring_append_len;
f->ucl_emitter_free_func = _ucl_emitter_free;
utstring_new (s);
utstring_new(s);
f->ud = s;
*pmem = s->d;
s->pd = pmem;
@ -422,12 +397,12 @@ ucl_object_emit_memory_funcs (void **pmem)
return f;
}
struct ucl_emitter_functions*
ucl_object_emit_file_funcs (FILE *fp)
struct ucl_emitter_functions *
ucl_object_emit_file_funcs(FILE *fp)
{
struct ucl_emitter_functions *f;
f = calloc (1, sizeof (*f));
f = calloc(1, sizeof(*f));
if (f != NULL) {
f->ucl_emitter_append_character = ucl_file_append_character;
@ -441,22 +416,22 @@ ucl_object_emit_file_funcs (FILE *fp)
return f;
}
struct ucl_emitter_functions*
ucl_object_emit_fd_funcs (int fd)
struct ucl_emitter_functions *
ucl_object_emit_fd_funcs(int fd)
{
struct ucl_emitter_functions *f;
int *ip;
f = calloc (1, sizeof (*f));
f = calloc(1, sizeof(*f));
if (f != NULL) {
ip = malloc (sizeof (fd));
ip = malloc(sizeof(fd));
if (ip == NULL) {
free (f);
free(f);
return NULL;
}
memcpy (ip, &fd, sizeof (fd));
memcpy(ip, &fd, sizeof(fd));
f->ucl_emitter_append_character = ucl_fd_append_character;
f->ucl_emitter_append_double = ucl_fd_append_double;
f->ucl_emitter_append_int = ucl_fd_append_int;
@ -468,20 +443,19 @@ ucl_object_emit_fd_funcs (int fd)
return f;
}
void
ucl_object_emit_funcs_free (struct ucl_emitter_functions *f)
void ucl_object_emit_funcs_free(struct ucl_emitter_functions *f)
{
if (f != NULL) {
if (f->ucl_emitter_free_func != NULL) {
f->ucl_emitter_free_func (f->ud);
f->ucl_emitter_free_func(f->ud);
}
free (f);
free(f);
}
}
unsigned char *
ucl_object_emit_single_json (const ucl_object_t *obj)
ucl_object_emit_single_json(const ucl_object_t *obj)
{
UT_string *buf = NULL;
unsigned char *res = NULL;
@ -490,43 +464,43 @@ ucl_object_emit_single_json (const ucl_object_t *obj)
return NULL;
}
utstring_new (buf);
utstring_new(buf);
if (buf != NULL) {
switch (obj->type) {
case UCL_OBJECT:
ucl_utstring_append_len ("object", 6, buf);
ucl_utstring_append_len("object", 6, buf);
break;
case UCL_ARRAY:
ucl_utstring_append_len ("array", 5, buf);
ucl_utstring_append_len("array", 5, buf);
break;
case UCL_INT:
ucl_utstring_append_int (obj->value.iv, buf);
ucl_utstring_append_int(obj->value.iv, buf);
break;
case UCL_FLOAT:
case UCL_TIME:
ucl_utstring_append_double (obj->value.dv, buf);
ucl_utstring_append_double(obj->value.dv, buf);
break;
case UCL_NULL:
ucl_utstring_append_len ("null", 4, buf);
ucl_utstring_append_len("null", 4, buf);
break;
case UCL_BOOLEAN:
if (obj->value.iv) {
ucl_utstring_append_len ("true", 4, buf);
ucl_utstring_append_len("true", 4, buf);
}
else {
ucl_utstring_append_len ("false", 5, buf);
ucl_utstring_append_len("false", 5, buf);
}
break;
case UCL_STRING:
ucl_utstring_append_len (obj->value.sv, obj->len, buf);
ucl_utstring_append_len(obj->value.sv, obj->len, buf);
break;
case UCL_USERDATA:
ucl_utstring_append_len ("userdata", 8, buf);
ucl_utstring_append_len("userdata", 8, buf);
break;
}
res = utstring_body (buf);
free (buf);
res = utstring_body(buf);
free(buf);
}
return res;
@ -534,12 +508,11 @@ ucl_object_emit_single_json (const ucl_object_t *obj)
#define LONG_STRING_LIMIT 80
bool
ucl_maybe_long_string (const ucl_object_t *obj)
bool ucl_maybe_long_string(const ucl_object_t *obj)
{
if (obj->len > LONG_STRING_LIMIT || (obj->flags & UCL_OBJECT_MULTILINE)) {
/* String is long enough, so search for newline characters in it */
if (memchr (obj->value.sv, '\n', obj->len) != NULL) {
if (memchr(obj->value.sv, '\n', obj->len) != NULL) {
return true;
}
}

View file

@ -42,7 +42,7 @@ struct ucl_hash_struct {
};
static uint64_t
ucl_hash_seed (void)
ucl_hash_seed(void)
{
static uint64_t seed;
if (seed == 0) {
@ -50,7 +50,7 @@ ucl_hash_seed (void)
seed = UCL_RANDOM_FUNCTION;
#else
/* Not very random but can be useful for our purposes */
seed = time (NULL);
seed = time(NULL);
#endif
}
@ -58,72 +58,71 @@ ucl_hash_seed (void)
}
static const unsigned char lc_map[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff};
#if (defined(WORD_BIT) && WORD_BIT == 64) || \
#if (defined(WORD_BIT) && WORD_BIT == 64) || \
(defined(__WORDSIZE) && __WORDSIZE == 64) || \
defined(__x86_64__) || \
defined(__x86_64__) || \
defined(__amd64__)
#define UCL64_BIT_HASH 1
#endif
static inline uint32_t
ucl_hash_func (const ucl_object_t *o)
ucl_hash_func(const ucl_object_t *o)
{
return mum_hash (o->key, o->keylen, ucl_hash_seed ());
return mum_hash(o->key, o->keylen, ucl_hash_seed());
}
static inline int
ucl_hash_equal (const ucl_object_t *k1, const ucl_object_t *k2)
ucl_hash_equal(const ucl_object_t *k1, const ucl_object_t *k2)
{
if (k1->keylen == k2->keylen) {
return memcmp (k1->key, k2->key, k1->keylen) == 0;
return memcmp(k1->key, k2->key, k1->keylen) == 0;
}
return 0;
}
KHASH_INIT (ucl_hash_node, const ucl_object_t *, struct ucl_hash_elt *, 1,
ucl_hash_func, ucl_hash_equal)
KHASH_INIT(ucl_hash_node, const ucl_object_t *, struct ucl_hash_elt *, 1,
ucl_hash_func, ucl_hash_equal)
static inline uint32_t
ucl_hash_caseless_func (const ucl_object_t *o)
ucl_hash_caseless_func(const ucl_object_t *o)
{
unsigned len = o->keylen;
unsigned leftover = o->keylen % 8;
unsigned fp, i;
const uint8_t* s = (const uint8_t*)o->key;
const uint8_t *s = (const uint8_t *) o->key;
union {
struct {
unsigned char c1, c2, c3, c4, c5, c6, c7, c8;
@ -133,7 +132,7 @@ ucl_hash_caseless_func (const ucl_object_t *o)
uint64_t r;
fp = len - leftover;
r = ucl_hash_seed ();
r = ucl_hash_seed();
for (i = 0; i != fp; i += 8) {
u.c.c1 = s[i], u.c.c2 = s[i + 1], u.c.c3 = s[i + 2], u.c.c4 = s[i + 3];
@ -146,40 +145,40 @@ ucl_hash_caseless_func (const ucl_object_t *o)
u.c.c6 = lc_map[u.c.c6];
u.c.c7 = lc_map[u.c.c7];
u.c.c8 = lc_map[u.c.c8];
r = mum_hash_step (r, u.pp);
r = mum_hash_step(r, u.pp);
}
u.pp = 0;
switch (leftover) {
case 7:
u.c.c7 = lc_map[(unsigned char)s[i++]];
u.c.c7 = lc_map[(unsigned char) s[i++]];
/* FALLTHRU */
case 6:
u.c.c6 = lc_map[(unsigned char)s[i++]];
u.c.c6 = lc_map[(unsigned char) s[i++]];
/* FALLTHRU */
case 5:
u.c.c5 = lc_map[(unsigned char)s[i++]];
u.c.c5 = lc_map[(unsigned char) s[i++]];
/* FALLTHRU */
case 4:
u.c.c4 = lc_map[(unsigned char)s[i++]];
u.c.c4 = lc_map[(unsigned char) s[i++]];
/* FALLTHRU */
case 3:
u.c.c3 = lc_map[(unsigned char)s[i++]];
u.c.c3 = lc_map[(unsigned char) s[i++]];
/* FALLTHRU */
case 2:
u.c.c2 = lc_map[(unsigned char)s[i++]];
u.c.c2 = lc_map[(unsigned char) s[i++]];
/* FALLTHRU */
case 1:
u.c.c1 = lc_map[(unsigned char)s[i]];
r = mum_hash_step (r, u.pp);
u.c.c1 = lc_map[(unsigned char) s[i]];
r = mum_hash_step(r, u.pp);
break;
}
return mum_hash_finish (r);
return mum_hash_finish(r);
}
static inline int
ucl_hash_caseless_equal (const ucl_object_t *k1, const ucl_object_t *k2)
ucl_hash_caseless_equal(const ucl_object_t *k1, const ucl_object_t *k2)
{
if (k1->keylen == k2->keylen) {
unsigned fp, i;
@ -212,7 +211,7 @@ ucl_hash_caseless_equal (const ucl_object_t *k1, const ucl_object_t *k2)
}
while (leftover > 0) {
if (lc_map[(unsigned char)s[i]] != lc_map[(unsigned char)d[i]]) {
if (lc_map[(unsigned char) s[i]] != lc_map[(unsigned char) d[i]]) {
return 0;
}
@ -226,27 +225,27 @@ ucl_hash_caseless_equal (const ucl_object_t *k1, const ucl_object_t *k2)
return 0;
}
KHASH_INIT (ucl_hash_caseless_node, const ucl_object_t *, struct ucl_hash_elt *, 1,
ucl_hash_caseless_func, ucl_hash_caseless_equal)
KHASH_INIT(ucl_hash_caseless_node, const ucl_object_t *, struct ucl_hash_elt *, 1,
ucl_hash_caseless_func, ucl_hash_caseless_equal)
ucl_hash_t*
ucl_hash_create (bool ignore_case)
ucl_hash_t *
ucl_hash_create(bool ignore_case)
{
ucl_hash_t *new;
new = UCL_ALLOC (sizeof (ucl_hash_t));
new = UCL_ALLOC(sizeof(ucl_hash_t));
if (new != NULL) {
void *h;
new->head = NULL;
new->caseless = ignore_case;
if (ignore_case) {
h = (void *)kh_init (ucl_hash_caseless_node);
h = (void *) kh_init(ucl_hash_caseless_node);
}
else {
h = (void *)kh_init (ucl_hash_node);
h = (void *) kh_init(ucl_hash_node);
}
if (h == NULL) {
UCL_FREE (sizeof (ucl_hash_t), new);
UCL_FREE(sizeof(ucl_hash_t), new);
return NULL;
}
new->hash = h;
@ -254,7 +253,7 @@ ucl_hash_create (bool ignore_case)
return new;
}
void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func func)
void ucl_hash_destroy(ucl_hash_t *hashlin, ucl_hash_free_func func)
{
if (hashlin == NULL) {
@ -264,16 +263,16 @@ void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func func)
if (func != NULL) {
/* Iterate over the hash first */
khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
hashlin->hash;
hashlin->hash;
khiter_t k;
const ucl_object_t *cur, *tmp;
for (k = kh_begin (h); k != kh_end (h); ++k) {
if (kh_exist (h, k)) {
cur = (kh_value (h, k))->obj;
for (k = kh_begin(h); k != kh_end(h); ++k) {
if (kh_exist(h, k)) {
cur = (kh_value(h, k))->obj;
while (cur != NULL) {
tmp = cur->next;
func (__DECONST (ucl_object_t *, cur));
func(__DECONST(ucl_object_t *, cur));
cur = tmp;
}
}
@ -282,27 +281,27 @@ void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func func)
if (hashlin->caseless) {
khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
hashlin->hash;
kh_destroy (ucl_hash_caseless_node, h);
hashlin->hash;
kh_destroy(ucl_hash_caseless_node, h);
}
else {
khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
hashlin->hash;
kh_destroy (ucl_hash_node, h);
hashlin->hash;
kh_destroy(ucl_hash_node, h);
}
struct ucl_hash_elt *cur, *tmp;
DL_FOREACH_SAFE(hashlin->head, cur, tmp) {
DL_FOREACH_SAFE(hashlin->head, cur, tmp)
{
UCL_FREE(sizeof(*cur), cur);
}
UCL_FREE (sizeof (*hashlin), hashlin);
UCL_FREE(sizeof(*hashlin), hashlin);
}
bool
ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj,
const char *key, unsigned keylen)
bool ucl_hash_insert(ucl_hash_t *hashlin, const ucl_object_t *obj,
const char *key, unsigned keylen)
{
khiter_t k;
int ret;
@ -314,11 +313,11 @@ ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj,
if (hashlin->caseless) {
khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
hashlin->hash;
k = kh_put (ucl_hash_caseless_node, h, obj, &ret);
hashlin->hash;
k = kh_put(ucl_hash_caseless_node, h, obj, &ret);
if (ret > 0) {
elt = UCL_ALLOC(sizeof(*elt));
pelt = &kh_value (h, k);
pelt = &kh_value(h, k);
*pelt = elt;
DL_APPEND(hashlin->head, elt);
elt->obj = obj;
@ -329,15 +328,16 @@ ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj,
}
else {
khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
hashlin->hash;
k = kh_put (ucl_hash_node, h, obj, &ret);
hashlin->hash;
k = kh_put(ucl_hash_node, h, obj, &ret);
if (ret > 0) {
elt = UCL_ALLOC(sizeof(*elt));
pelt = &kh_value (h, k);
pelt = &kh_value(h, k);
*pelt = elt;
DL_APPEND(hashlin->head, elt);
elt->obj = obj;
} else if (ret < 0) {
}
else if (ret < 0) {
goto e0;
}
}
@ -346,8 +346,8 @@ e0:
return false;
}
void ucl_hash_replace (ucl_hash_t* hashlin, const ucl_object_t *old,
const ucl_object_t *new)
void ucl_hash_replace(ucl_hash_t *hashlin, const ucl_object_t *old,
const ucl_object_t *new)
{
khiter_t k;
int ret;
@ -359,12 +359,12 @@ void ucl_hash_replace (ucl_hash_t* hashlin, const ucl_object_t *old,
if (hashlin->caseless) {
khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
hashlin->hash;
k = kh_put (ucl_hash_caseless_node, h, old, &ret);
hashlin->hash;
k = kh_put(ucl_hash_caseless_node, h, old, &ret);
if (ret == 0) {
elt = kh_value(h, k);
kh_del (ucl_hash_caseless_node, h, k);
k = kh_put (ucl_hash_caseless_node, h, new, &ret);
kh_del(ucl_hash_caseless_node, h, k);
k = kh_put(ucl_hash_caseless_node, h, new, &ret);
nelt = UCL_ALLOC(sizeof(*nelt));
nelt->obj = new;
kh_value(h, k) = nelt;
@ -374,12 +374,12 @@ void ucl_hash_replace (ucl_hash_t* hashlin, const ucl_object_t *old,
}
else {
khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
hashlin->hash;
k = kh_put (ucl_hash_node, h, old, &ret);
hashlin->hash;
k = kh_put(ucl_hash_node, h, old, &ret);
if (ret == 0) {
elt = kh_value (h, k);
kh_del (ucl_hash_node, h, k);
k = kh_put (ucl_hash_node, h, new, &ret);
elt = kh_value(h, k);
kh_del(ucl_hash_node, h, k);
k = kh_put(ucl_hash_node, h, new, &ret);
nelt = UCL_ALLOC(sizeof(*nelt));
nelt->obj = new;
kh_value(h, k) = nelt;
@ -393,12 +393,15 @@ struct ucl_hash_real_iter {
const struct ucl_hash_elt *cur;
};
#define UHI_SETERR(ep, ern) {if (ep != NULL) *ep = (ern);}
#define UHI_SETERR(ep, ern) \
{ \
if (ep != NULL) *ep = (ern); \
}
const void*
ucl_hash_iterate2 (ucl_hash_t *hashlin, ucl_hash_iter_t *iter, int *ep)
const void *
ucl_hash_iterate2(ucl_hash_t *hashlin, ucl_hash_iter_t *iter, int *ep)
{
struct ucl_hash_real_iter *it = (struct ucl_hash_real_iter *)(*iter);
struct ucl_hash_real_iter *it = (struct ucl_hash_real_iter *) (*iter);
const ucl_object_t *ret = NULL;
if (hashlin == NULL) {
@ -407,7 +410,7 @@ ucl_hash_iterate2 (ucl_hash_t *hashlin, ucl_hash_iter_t *iter, int *ep)
}
if (it == NULL) {
it = UCL_ALLOC (sizeof (*it));
it = UCL_ALLOC(sizeof(*it));
if (it == NULL) {
UHI_SETERR(ep, ENOMEM);
@ -423,7 +426,7 @@ ucl_hash_iterate2 (ucl_hash_t *hashlin, ucl_hash_iter_t *iter, int *ep)
it->cur = it->cur->next;
}
else {
UCL_FREE (sizeof (*it), it);
UCL_FREE(sizeof(*it), it);
*iter = NULL;
return NULL;
}
@ -433,17 +436,16 @@ ucl_hash_iterate2 (ucl_hash_t *hashlin, ucl_hash_iter_t *iter, int *ep)
return ret;
}
bool
ucl_hash_iter_has_next (ucl_hash_t *hashlin, ucl_hash_iter_t iter)
bool ucl_hash_iter_has_next(ucl_hash_t *hashlin, ucl_hash_iter_t iter)
{
struct ucl_hash_real_iter *it = (struct ucl_hash_real_iter *)(iter);
struct ucl_hash_real_iter *it = (struct ucl_hash_real_iter *) (iter);
return it->cur != NULL;
}
const 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)
{
khiter_t k;
const ucl_object_t *ret = NULL;
@ -459,20 +461,20 @@ ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen)
if (hashlin->caseless) {
khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
hashlin->hash;
hashlin->hash;
k = kh_get (ucl_hash_caseless_node, h, &search);
if (k != kh_end (h)) {
elt = kh_value (h, k);
k = kh_get(ucl_hash_caseless_node, h, &search);
if (k != kh_end(h)) {
elt = kh_value(h, k);
ret = elt->obj;
}
}
else {
khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
hashlin->hash;
k = kh_get (ucl_hash_node, h, &search);
if (k != kh_end (h)) {
elt = kh_value (h, k);
hashlin->hash;
k = kh_get(ucl_hash_node, h, &search);
if (k != kh_end(h)) {
elt = kh_value(h, k);
ret = elt->obj;
}
}
@ -480,8 +482,7 @@ ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen)
return ret;
}
void
ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)
void ucl_hash_delete(ucl_hash_t *hashlin, const ucl_object_t *obj)
{
khiter_t k;
struct ucl_hash_elt *elt;
@ -492,52 +493,53 @@ ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)
if (hashlin->caseless) {
khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
hashlin->hash;
hashlin->hash;
k = kh_get (ucl_hash_caseless_node, h, obj);
if (k != kh_end (h)) {
elt = kh_value (h, k);
k = kh_get(ucl_hash_caseless_node, h, obj);
if (k != kh_end(h)) {
elt = kh_value(h, k);
DL_DELETE(hashlin->head, elt);
kh_del (ucl_hash_caseless_node, h, k);
kh_del(ucl_hash_caseless_node, h, k);
UCL_FREE(sizeof(*elt), elt);
}
}
else {
khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
hashlin->hash;
k = kh_get (ucl_hash_node, h, obj);
if (k != kh_end (h)) {
elt = kh_value (h, k);
hashlin->hash;
k = kh_get(ucl_hash_node, h, obj);
if (k != kh_end(h)) {
elt = kh_value(h, k);
DL_DELETE(hashlin->head, elt);
kh_del (ucl_hash_node, h, k);
kh_del(ucl_hash_node, h, k);
UCL_FREE(sizeof(*elt), elt);
}
}
}
bool ucl_hash_reserve (ucl_hash_t *hashlin, size_t sz)
bool ucl_hash_reserve(ucl_hash_t *hashlin, size_t sz)
{
if (hashlin == NULL) {
return false;
}
if (sz > kh_size((khash_t(ucl_hash_node) *)hashlin->hash)) {
if (sz > kh_size((khash_t(ucl_hash_node) *) hashlin->hash)) {
if (hashlin->caseless) {
khash_t(ucl_hash_caseless_node) *h = (khash_t(
ucl_hash_caseless_node) *)
hashlin->hash;
kh_resize (ucl_hash_caseless_node, h, sz * 2);
} else {
ucl_hash_caseless_node) *)
hashlin->hash;
kh_resize(ucl_hash_caseless_node, h, sz * 2);
}
else {
khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
hashlin->hash;
kh_resize (ucl_hash_node, h, sz * 2);
hashlin->hash;
kh_resize(ucl_hash_node, h, sz * 2);
}
}
return true;
}
static int
ucl_lc_cmp (const char *s, const char *d, size_t l)
ucl_lc_cmp(const char *s, const char *d, size_t l)
{
unsigned int fp, i;
unsigned char c1, c2, c3, c4;
@ -569,7 +571,7 @@ ucl_lc_cmp (const char *s, const char *d, size_t l)
}
while (leftover > 0) {
if (lc_map[(unsigned char)s[i]] != lc_map[(unsigned char)d[i]]) {
if (lc_map[(unsigned char) s[i]] != lc_map[(unsigned char) d[i]]) {
return s[i] - d[i];
}
@ -581,33 +583,32 @@ ucl_lc_cmp (const char *s, const char *d, size_t l)
}
static int
ucl_hash_cmp_icase (const void *a, const void *b)
ucl_hash_cmp_icase(const void *a, const void *b)
{
const struct ucl_hash_elt *oa = (const struct ucl_hash_elt *)a,
*ob = (const struct ucl_hash_elt *)b;
const struct ucl_hash_elt *oa = (const struct ucl_hash_elt *) a,
*ob = (const struct ucl_hash_elt *) b;
if (oa->obj->keylen == ob->obj->keylen) {
return ucl_lc_cmp (oa->obj->key, ob->obj->key, oa->obj->keylen);
return ucl_lc_cmp(oa->obj->key, ob->obj->key, oa->obj->keylen);
}
return ((int)(oa->obj->keylen)) - ob->obj->keylen;
return ((int) (oa->obj->keylen)) - ob->obj->keylen;
}
static int
ucl_hash_cmp_case_sens (const void *a, const void *b)
ucl_hash_cmp_case_sens(const void *a, const void *b)
{
const struct ucl_hash_elt *oa = (const struct ucl_hash_elt *)a,
*ob = (const struct ucl_hash_elt *)b;
const struct ucl_hash_elt *oa = (const struct ucl_hash_elt *) a,
*ob = (const struct ucl_hash_elt *) b;
if (oa->obj->keylen == ob->obj->keylen) {
return memcmp (oa->obj->key, ob->obj->key, oa->obj->keylen);
return memcmp(oa->obj->key, ob->obj->key, oa->obj->keylen);
}
return ((int)(oa->obj->keylen)) - ob->obj->keylen;
return ((int) (oa->obj->keylen)) - ob->obj->keylen;
}
void
ucl_hash_sort (ucl_hash_t *hashlin, enum ucl_object_keys_sort_flags fl)
void ucl_hash_sort(ucl_hash_t *hashlin, enum ucl_object_keys_sort_flags fl)
{
if (fl & UCL_SORT_KEYS_ICASE) {
@ -620,9 +621,10 @@ ucl_hash_sort (ucl_hash_t *hashlin, enum ucl_object_keys_sort_flags fl)
if (fl & UCL_SORT_KEYS_RECURSIVE) {
struct ucl_hash_elt *elt;
DL_FOREACH(hashlin->head, elt) {
if (ucl_object_type (elt->obj) == UCL_OBJECT) {
ucl_hash_sort (elt->obj->value.ov, fl);
DL_FOREACH(hashlin->head, elt)
{
if (ucl_object_type(elt->obj) == UCL_OBJECT) {
ucl_hash_sort(elt->obj->value.ov, fl);
}
}
}

View file

@ -31,9 +31,9 @@
struct ucl_hash_node_s;
typedef struct ucl_hash_node_s ucl_hash_node_t;
typedef int (*ucl_hash_cmp_func) (const void* void_a, const void* void_b);
typedef void (*ucl_hash_free_func) (void *ptr);
typedef void* ucl_hash_iter_t;
typedef int (*ucl_hash_cmp_func)(const void *void_a, const void *void_b);
typedef void (*ucl_hash_free_func)(void *ptr);
typedef void *ucl_hash_iter_t;
/**
@ -46,36 +46,36 @@ typedef struct ucl_hash_struct ucl_hash_t;
/**
* Initializes the hashtable.
*/
ucl_hash_t* ucl_hash_create (bool ignore_case);
ucl_hash_t *ucl_hash_create(bool ignore_case);
/**
* Deinitializes the hashtable.
*/
void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func func);
void ucl_hash_destroy(ucl_hash_t *hashlin, ucl_hash_free_func func);
/**
* Inserts an element in the the hashtable.
* @return true on success, false on failure (i.e. ENOMEM)
*/
bool ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj, const char *key,
unsigned keylen);
bool ucl_hash_insert(ucl_hash_t *hashlin, const ucl_object_t *obj, const char *key,
unsigned keylen);
/**
* Replace element in the hash
*/
void ucl_hash_replace (ucl_hash_t* hashlin, const ucl_object_t *old,
const ucl_object_t *new);
void ucl_hash_replace(ucl_hash_t *hashlin, const ucl_object_t *old,
const ucl_object_t *new);
/**
* Delete an element from the the hashtable.
*/
void ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj);
void ucl_hash_delete(ucl_hash_t *hashlin, const ucl_object_t *obj);
/**
* Searches an element in the hashtable.
*/
const 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);
/**
@ -85,7 +85,7 @@ const ucl_object_t* ucl_hash_search (ucl_hash_t* hashlin, const char *key,
* @param ep pointer record exception (such as ENOMEM), could be NULL
* @return the next object
*/
const void* ucl_hash_iterate2 (ucl_hash_t *hashlin, ucl_hash_iter_t *iter, int *ep);
const void *ucl_hash_iterate2(ucl_hash_t *hashlin, ucl_hash_iter_t *iter, int *ep);
/**
* Helper macro to support older code
@ -95,15 +95,15 @@ const void* ucl_hash_iterate2 (ucl_hash_t *hashlin, ucl_hash_iter_t *iter, int *
/**
* Check whether an iterator has next element
*/
bool ucl_hash_iter_has_next (ucl_hash_t *hashlin, ucl_hash_iter_t iter);
bool ucl_hash_iter_has_next(ucl_hash_t *hashlin, ucl_hash_iter_t iter);
/**
* Reserves space in hash
* @return true on sucess, false on failure (e.g. ENOMEM)
* @param hashlin
*/
bool ucl_hash_reserve (ucl_hash_t *hashlin, size_t sz);
bool ucl_hash_reserve(ucl_hash_t *hashlin, size_t sz);
void ucl_hash_sort (ucl_hash_t *hashlin, enum ucl_object_keys_sort_flags fl);
void ucl_hash_sort(ucl_hash_t *hashlin, enum ucl_object_keys_sort_flags fl);
#endif

View file

@ -46,7 +46,7 @@
#define HAVE_STDINT_H
#define HAVE_STDARG_H
#ifndef _WIN32
# define HAVE_REGEX_H
#define HAVE_REGEX_H
#endif
#endif
@ -55,17 +55,17 @@
#endif
#ifdef HAVE_SYS_MMAN_H
# ifndef _WIN32
# include <sys/mman.h>
# endif
#ifndef _WIN32
#include <sys/mman.h>
#endif
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_SYS_PARAM_H
# ifndef _WIN32
# include <sys/param.h>
# endif
#ifndef _WIN32
#include <sys/param.h>
#endif
#endif
#ifdef HAVE_LIMITS_H
@ -78,9 +78,9 @@
#include <errno.h>
#endif
#ifdef HAVE_UNISTD_H
# ifndef _WIN32
# include <unistd.h>
# endif
#ifndef _WIN32
#include <unistd.h>
#endif
#endif
#ifdef HAVE_CTYPE_H
#include <ctype.h>
@ -132,7 +132,7 @@ typedef SSIZE_T ssize_t;
#endif
#ifndef __DECONST
#define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
#define __DECONST(type, var) ((type) (uintptr_t) (const void *) (var))
#endif
/**
@ -182,14 +182,15 @@ struct ucl_macro {
ucl_macro_handler handler;
ucl_context_macro_handler context_handler;
} h;
void* ud;
void *ud;
bool is_context;
UT_hash_handle hh;
};
enum ucl_stack_flags {
UCL_STACK_HAS_OBRACE = (1u << 0),
UCL_STACK_MAX = (1u << 1),
UCL_STACK_AUTOMATIC = (1u << 1),
UCL_STACK_MAX = (1u << 2),
};
struct ucl_stack {
@ -284,14 +285,14 @@ struct ucl_object_userdata {
* Unescape json string inplace
* @param str
*/
size_t ucl_unescape_json_string (char *str, size_t len);
size_t ucl_unescape_json_string(char *str, size_t len);
/**
* Unescape single quoted string inplace
* @param str
*/
size_t ucl_unescape_squoted_string (char *str, size_t len);
size_t ucl_unescape_squoted_string(char *str, size_t len);
/**
* Handle include macro
@ -301,8 +302,8 @@ size_t ucl_unescape_squoted_string (char *str, size_t len);
* @param ud user data
* @return
*/
bool ucl_include_handler (const unsigned char *data, size_t len,
const ucl_object_t *args, void* ud);
bool ucl_include_handler(const unsigned char *data, size_t len,
const ucl_object_t *args, void *ud);
/**
* Handle tryinclude macro
@ -312,8 +313,8 @@ bool ucl_include_handler (const unsigned char *data, size_t len,
* @param ud user data
* @return
*/
bool ucl_try_include_handler (const unsigned char *data, size_t len,
const ucl_object_t *args, void* ud);
bool ucl_try_include_handler(const unsigned char *data, size_t len,
const ucl_object_t *args, void *ud);
/**
* Handle includes macro
@ -323,8 +324,8 @@ bool ucl_try_include_handler (const unsigned char *data, size_t len,
* @param ud user data
* @return
*/
bool ucl_includes_handler (const unsigned char *data, size_t len,
const ucl_object_t *args, void* ud);
bool ucl_includes_handler(const unsigned char *data, size_t len,
const ucl_object_t *args, void *ud);
/**
* Handle priority macro
@ -334,8 +335,8 @@ bool ucl_includes_handler (const unsigned char *data, size_t len,
* @param ud user data
* @return
*/
bool ucl_priority_handler (const unsigned char *data, size_t len,
const ucl_object_t *args, void* ud);
bool ucl_priority_handler(const unsigned char *data, size_t len,
const ucl_object_t *args, void *ud);
/**
* Handle load macro
@ -345,8 +346,8 @@ bool ucl_priority_handler (const unsigned char *data, size_t len,
* @param ud user data
* @return
*/
bool ucl_load_handler (const unsigned char *data, size_t len,
const ucl_object_t *args, void* ud);
bool ucl_load_handler(const unsigned char *data, size_t len,
const ucl_object_t *args, void *ud);
/**
* Handle inherit macro
* @param data include data
@ -356,37 +357,37 @@ bool ucl_load_handler (const unsigned char *data, size_t len,
* @param ud user data
* @return
*/
bool ucl_inherit_handler (const unsigned char *data, size_t len,
const ucl_object_t *args, const ucl_object_t *ctx, void* ud);
bool ucl_inherit_handler(const unsigned char *data, size_t len,
const ucl_object_t *args, const ucl_object_t *ctx, void *ud);
size_t ucl_strlcpy (char *dst, const char *src, size_t siz);
size_t ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz);
size_t ucl_strlcpy_tolower (char *dst, const char *src, size_t siz);
size_t ucl_strlcpy(char *dst, const char *src, size_t siz);
size_t ucl_strlcpy_unsafe(char *dst, const char *src, size_t siz);
size_t ucl_strlcpy_tolower(char *dst, const char *src, size_t siz);
char *ucl_strnstr (const char *s, const char *find, int len);
char *ucl_strncasestr (const char *s, const char *find, int len);
char *ucl_strnstr(const char *s, const char *find, int len);
char *ucl_strncasestr(const char *s, const char *find, int len);
#ifdef __GNUC__
static inline void
ucl_create_err (UT_string **err, const char *fmt, ...)
__attribute__ (( format( printf, 2, 3) ));
ucl_create_err(UT_string **err, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
#endif
#undef UCL_FATAL_ERRORS
static inline void
ucl_create_err (UT_string **err, const char *fmt, ...)
ucl_create_err(UT_string **err, const char *fmt, ...)
{
if (*err == NULL) {
utstring_new (*err);
utstring_new(*err);
va_list ap;
va_start (ap, fmt);
utstring_printf_va (*err, fmt, ap);
va_end (ap);
va_start(ap, fmt);
utstring_printf_va(*err, fmt, ap);
va_end(ap);
}
#ifdef UCL_FATAL_ERRORS
assert (0);
assert(0);
#endif
}
@ -398,39 +399,39 @@ ucl_create_err (UT_string **err, const char *fmt, ...)
* @return true if a string is a boolean value
*/
static inline bool
ucl_maybe_parse_boolean (ucl_object_t *obj, const unsigned char *start, size_t len)
ucl_maybe_parse_boolean(ucl_object_t *obj, const unsigned char *start, size_t len)
{
const char *p = (const char *)start;
const char *p = (const char *) start;
bool ret = false, val = false;
if (len == 5) {
if ((p[0] == 'f' || p[0] == 'F') && strncasecmp (p, "false", 5) == 0) {
if ((p[0] == 'f' || p[0] == 'F') && strncasecmp(p, "false", 5) == 0) {
ret = true;
val = false;
}
}
else if (len == 4) {
if ((p[0] == 't' || p[0] == 'T') && strncasecmp (p, "true", 4) == 0) {
if ((p[0] == 't' || p[0] == 'T') && strncasecmp(p, "true", 4) == 0) {
ret = true;
val = true;
}
}
else if (len == 3) {
if ((p[0] == 'y' || p[0] == 'Y') && strncasecmp (p, "yes", 3) == 0) {
if ((p[0] == 'y' || p[0] == 'Y') && strncasecmp(p, "yes", 3) == 0) {
ret = true;
val = true;
}
else if ((p[0] == 'o' || p[0] == 'O') && strncasecmp (p, "off", 3) == 0) {
else if ((p[0] == 'o' || p[0] == 'O') && strncasecmp(p, "off", 3) == 0) {
ret = true;
val = false;
}
}
else if (len == 2) {
if ((p[0] == 'n' || p[0] == 'N') && strncasecmp (p, "no", 2) == 0) {
if ((p[0] == 'n' || p[0] == 'N') && strncasecmp(p, "no", 2) == 0) {
ret = true;
val = false;
}
else if ((p[0] == 'o' || p[0] == 'O') && strncasecmp (p, "on", 2) == 0) {
else if ((p[0] == 'o' || p[0] == 'O') && strncasecmp(p, "on", 2) == 0) {
ret = true;
val = true;
}
@ -453,37 +454,38 @@ ucl_maybe_parse_boolean (ucl_object_t *obj, const unsigned char *start, size_t l
* @param allow_double allow parsing of floating point values
* @return 0 if string is numeric and error code (EINVAL or ERANGE) in case of conversion error
*/
int ucl_maybe_parse_number (ucl_object_t *obj,
const char *start, const char *end, const char **pos,
bool allow_double, bool number_bytes, bool allow_time);
int ucl_maybe_parse_number(ucl_object_t *obj,
const char *start, const char *end, const char **pos,
bool allow_double, bool number_bytes, bool allow_time);
static inline const ucl_object_t *
ucl_hash_search_obj (ucl_hash_t* hashlin, ucl_object_t *obj)
ucl_hash_search_obj(ucl_hash_t *hashlin, ucl_object_t *obj)
{
return (const 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,
const ucl_object_t *obj,
bool ignore_case) UCL_WARN_UNUSED_RESULT;
static inline ucl_hash_t *ucl_hash_insert_object(ucl_hash_t *hashlin,
const ucl_object_t *obj,
bool ignore_case) UCL_WARN_UNUSED_RESULT;
static inline ucl_hash_t *
ucl_hash_insert_object (ucl_hash_t *hashlin,
const ucl_object_t *obj,
bool ignore_case)
ucl_hash_insert_object(ucl_hash_t *hashlin,
const ucl_object_t *obj,
bool ignore_case)
{
ucl_hash_t *nhp;
if (hashlin == NULL) {
nhp = ucl_hash_create (ignore_case);
nhp = ucl_hash_create(ignore_case);
if (nhp == NULL) {
return NULL;
}
} else {
}
else {
nhp = hashlin;
}
if (!ucl_hash_insert (nhp, obj, obj->key, obj->keylen)) {
if (!ucl_hash_insert(nhp, obj, obj->key, obj->keylen)) {
if (nhp != hashlin) {
ucl_hash_destroy(nhp, NULL);
}
@ -499,15 +501,15 @@ ucl_hash_insert_object (ucl_hash_t *hashlin,
* @return context or NULL if input is invalid
*/
const struct ucl_emitter_context *
ucl_emit_get_standard_context (enum ucl_emitter emit_type);
ucl_emit_get_standard_context(enum ucl_emitter emit_type);
/**
* Serialize string as JSON string
* @param str string to emit
* @param buf target buffer
*/
void ucl_elt_string_write_json (const char *str, size_t size,
struct ucl_emitter_context *ctx);
void ucl_elt_string_write_json(const char *str, size_t size,
struct ucl_emitter_context *ctx);
/**
@ -515,9 +517,8 @@ void ucl_elt_string_write_json (const char *str, size_t size,
* @param str string to emit
* @param buf target buffer
*/
void
ucl_elt_string_write_squoted (const char *str, size_t size,
struct ucl_emitter_context *ctx);
void ucl_elt_string_write_squoted(const char *str, size_t size,
struct ucl_emitter_context *ctx);
/**
* Write multiline string using `EOD` as string terminator
@ -525,15 +526,15 @@ ucl_elt_string_write_squoted (const char *str, size_t size,
* @param size
* @param ctx
*/
void ucl_elt_string_write_multiline (const char *str, size_t size,
struct ucl_emitter_context *ctx);
void ucl_elt_string_write_multiline(const char *str, size_t size,
struct ucl_emitter_context *ctx);
/**
* Emit a single object to string
* @param obj
* @return
*/
unsigned char * ucl_object_emit_single_json (const ucl_object_t *obj);
unsigned char *ucl_object_emit_single_json(const ucl_object_t *obj);
/**
* Check whether a specified string is long and should be likely printed in
@ -541,37 +542,37 @@ unsigned char * ucl_object_emit_single_json (const ucl_object_t *obj);
* @param obj
* @return
*/
bool ucl_maybe_long_string (const ucl_object_t *obj);
bool ucl_maybe_long_string(const ucl_object_t *obj);
/**
* Print integer to the msgpack output
* @param ctx
* @param val
*/
void ucl_emitter_print_int_msgpack (struct ucl_emitter_context *ctx,
int64_t val);
void ucl_emitter_print_int_msgpack(struct ucl_emitter_context *ctx,
int64_t val);
/**
* Print integer to the msgpack output
* @param ctx
* @param val
*/
void ucl_emitter_print_double_msgpack (struct ucl_emitter_context *ctx,
double val);
void ucl_emitter_print_double_msgpack(struct ucl_emitter_context *ctx,
double val);
/**
* Print double to the msgpack output
* @param ctx
* @param val
*/
void ucl_emitter_print_bool_msgpack (struct ucl_emitter_context *ctx,
bool val);
void ucl_emitter_print_bool_msgpack(struct ucl_emitter_context *ctx,
bool val);
/**
* Print string to the msgpack output
* @param ctx
* @param s
* @param len
*/
void ucl_emitter_print_string_msgpack (struct ucl_emitter_context *ctx,
const char *s, size_t len);
void ucl_emitter_print_string_msgpack(struct ucl_emitter_context *ctx,
const char *s, size_t len);
/**
* Print binary string to the msgpack output
@ -579,38 +580,38 @@ void ucl_emitter_print_string_msgpack (struct ucl_emitter_context *ctx,
* @param s
* @param len
*/
void ucl_emitter_print_binary_string_msgpack (struct ucl_emitter_context *ctx,
const char *s, size_t len);
void ucl_emitter_print_binary_string_msgpack(struct ucl_emitter_context *ctx,
const char *s, size_t len);
/**
* Print array preamble for msgpack
* @param ctx
* @param len
*/
void ucl_emitter_print_array_msgpack (struct ucl_emitter_context *ctx,
size_t len);
void ucl_emitter_print_array_msgpack(struct ucl_emitter_context *ctx,
size_t len);
/**
* Print object preamble for msgpack
* @param ctx
* @param len
*/
void ucl_emitter_print_object_msgpack (struct ucl_emitter_context *ctx,
size_t len);
void ucl_emitter_print_object_msgpack(struct ucl_emitter_context *ctx,
size_t len);
/**
* Print NULL to the msgpack output
* @param ctx
*/
void ucl_emitter_print_null_msgpack (struct ucl_emitter_context *ctx);
void ucl_emitter_print_null_msgpack(struct ucl_emitter_context *ctx);
/**
* Print object's key if needed to the msgpack output
* @param print_key
* @param ctx
* @param obj
*/
void ucl_emitter_print_key_msgpack (bool print_key,
struct ucl_emitter_context *ctx,
const ucl_object_t *obj);
void ucl_emitter_print_key_msgpack(bool print_key,
struct ucl_emitter_context *ctx,
const ucl_object_t *obj);
/**
* Fetch URL into a buffer
@ -620,11 +621,11 @@ void ucl_emitter_print_key_msgpack (bool print_key,
* @param err pointer to error argument
* @param must_exist fail if cannot find a url
*/
bool ucl_fetch_url (const unsigned char *url,
unsigned char **buf,
size_t *buflen,
UT_string **err,
bool must_exist);
bool ucl_fetch_url(const unsigned char *url,
unsigned char **buf,
size_t *buflen,
UT_string **err,
bool must_exist);
/**
* Fetch a file and save results to the memory buffer
@ -634,11 +635,11 @@ bool ucl_fetch_url (const unsigned char *url,
* @param buflen target length
* @return
*/
bool ucl_fetch_file (const unsigned char *filename,
unsigned char **buf,
size_t *buflen,
UT_string **err,
bool must_exist);
bool ucl_fetch_file(const unsigned char *filename,
unsigned char **buf,
size_t *buflen,
UT_string **err,
bool must_exist);
/**
* Add new element to an object using the current merge strategy and priority
@ -646,22 +647,22 @@ bool ucl_fetch_file (const unsigned char *filename,
* @param nobj
* @return
*/
bool ucl_parser_process_object_element (struct ucl_parser *parser,
ucl_object_t *nobj);
bool ucl_parser_process_object_element(struct ucl_parser *parser,
ucl_object_t *nobj);
/**
* Parse msgpack chunk
* @param parser
* @return
*/
bool ucl_parse_msgpack (struct ucl_parser *parser);
bool ucl_parse_msgpack(struct ucl_parser *parser);
bool ucl_parse_csexp (struct ucl_parser *parser);
bool ucl_parse_csexp(struct ucl_parser *parser);
/**
* Free ucl chunk
* @param chunk
*/
void ucl_chunk_free (struct ucl_chunk *chunk);
void ucl_chunk_free(struct ucl_chunk *chunk);
#endif /* UCL_INTERNAL_H_ */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -31,33 +31,33 @@
#include "ucl_internal.h"
#include "utlist.h"
#define NEXT_STATE do { \
if (p >= end) { \
if (state != read_ebrace) { \
ucl_create_err (&parser->err,\
"extra data");\
state = parse_err; \
} \
} \
else { \
switch (*p) { \
case '(': \
state = read_obrace; \
break; \
case ')': \
state = read_ebrace; \
break; \
default: \
len = 0; \
mult = 1; \
state = read_length; \
break; \
} \
} \
} while(0)
#define NEXT_STATE \
do { \
if (p >= end) { \
if (state != read_ebrace) { \
ucl_create_err(&parser->err, \
"extra data"); \
state = parse_err; \
} \
} \
else { \
switch (*p) { \
case '(': \
state = read_obrace; \
break; \
case ')': \
state = read_ebrace; \
break; \
default: \
len = 0; \
mult = 1; \
state = read_length; \
break; \
} \
} \
} while (0)
bool
ucl_parse_csexp (struct ucl_parser *parser)
bool ucl_parse_csexp(struct ucl_parser *parser)
{
const unsigned char *p, *end;
ucl_object_t *obj;
@ -72,10 +72,10 @@ ucl_parse_csexp (struct ucl_parser *parser)
parse_err
} state = start_parse;
assert (parser != NULL);
assert (parser->chunks != NULL);
assert (parser->chunks->begin != NULL);
assert (parser->chunks->remain != 0);
assert(parser != NULL);
assert(parser->chunks != NULL);
assert(parser->chunks->begin != NULL);
assert(parser->chunks->remain != 0);
p = parser->chunks->begin;
end = p + parser->chunks->remain;
@ -88,27 +88,28 @@ ucl_parse_csexp (struct ucl_parser *parser)
state = read_obrace;
}
else {
ucl_create_err (&parser->err, "bad starting character for "
"sexp block: %x", (int)*p);
ucl_create_err(&parser->err, "bad starting character for "
"sexp block: %x",
(int) *p);
state = parse_err;
}
break;
case read_obrace:
st = calloc (1, sizeof (*st));
st = calloc(1, sizeof(*st));
if (st == NULL) {
ucl_create_err (&parser->err, "no memory");
ucl_create_err(&parser->err, "no memory");
state = parse_err;
continue;
}
st->obj = ucl_object_typed_new (UCL_ARRAY);
st->obj = ucl_object_typed_new(UCL_ARRAY);
if (st->obj == NULL) {
ucl_create_err (&parser->err, "no memory");
ucl_create_err(&parser->err, "no memory");
state = parse_err;
free (st);
free(st);
continue;
}
@ -122,10 +123,10 @@ ucl_parse_csexp (struct ucl_parser *parser)
}
else {
/* Prepend new element to the stack */
LL_PREPEND (parser->stack, st);
LL_PREPEND(parser->stack, st);
}
p ++;
p++;
NEXT_STATE;
break;
@ -133,7 +134,7 @@ ucl_parse_csexp (struct ucl_parser *parser)
case read_length:
if (*p == ':') {
if (len == 0) {
ucl_create_err (&parser->err, "zero length element");
ucl_create_err(&parser->err, "zero length element");
state = parse_err;
continue;
}
@ -145,40 +146,41 @@ ucl_parse_csexp (struct ucl_parser *parser)
mult *= 10;
if (len > UINT32_MAX) {
ucl_create_err (&parser->err, "too big length of an "
"element");
ucl_create_err(&parser->err, "too big length of an "
"element");
state = parse_err;
continue;
}
}
else {
ucl_create_err (&parser->err, "bad length character: %x",
(int)*p);
ucl_create_err(&parser->err, "bad length character: %x",
(int) *p);
state = parse_err;
continue;
}
p ++;
p++;
break;
case read_value:
if ((uint64_t)(end - p) > len || len == 0) {
ucl_create_err (&parser->err, "invalid length: %llu, %ld "
"remain", (long long unsigned)len, (long)(end - p));
if ((uint64_t) (end - p) > len || len == 0) {
ucl_create_err(&parser->err, "invalid length: %llu, %ld "
"remain",
(long long unsigned) len, (long) (end - p));
state = parse_err;
continue;
}
obj = ucl_object_typed_new (UCL_STRING);
obj = ucl_object_typed_new(UCL_STRING);
obj->value.sv = (const char*)p;
obj->value.sv = (const char *) p;
obj->len = len;
obj->flags |= UCL_OBJECT_BINARY;
if (!(parser->flags & UCL_PARSER_ZEROCOPY)) {
ucl_copy_value_trash (obj);
ucl_copy_value_trash(obj);
}
ucl_array_append (parser->stack->obj, obj);
ucl_array_append(parser->stack->obj, obj);
p += len;
NEXT_STATE;
break;
@ -186,8 +188,9 @@ ucl_parse_csexp (struct ucl_parser *parser)
case read_ebrace:
if (parser->stack == NULL) {
/* We have an extra end brace */
ucl_create_err (&parser->err, "invalid length: %llu, %ld "
"remain", (long long unsigned)len, (long)(end - p));
ucl_create_err(&parser->err, "invalid length: %llu, %ld "
"remain",
(long long unsigned) len, (long) (end - p));
state = parse_err;
continue;
}
@ -196,16 +199,16 @@ ucl_parse_csexp (struct ucl_parser *parser)
parser->stack = st->next;
if (parser->stack->obj->type == UCL_ARRAY) {
ucl_array_append (parser->stack->obj, st->obj);
ucl_array_append(parser->stack->obj, st->obj);
}
else {
ucl_create_err (&parser->err, "bad container object, array "
"expected");
ucl_create_err(&parser->err, "bad container object, array "
"expected");
state = parse_err;
continue;
}
free (st);
free(st);
st = NULL;
p++;
NEXT_STATE;
@ -218,7 +221,7 @@ ucl_parse_csexp (struct ucl_parser *parser)
}
if (state != read_ebrace) {
ucl_create_err (&parser->err, "invalid finishing state: %d", state);
ucl_create_err(&parser->err, "invalid finishing state: %d", state);
return false;
}

File diff suppressed because it is too large Load diff

31
tests/CMakeLists.txt Normal file
View file

@ -0,0 +1,31 @@
set(COMMON_TEST_INCLUDES
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/src
${CMAKE_SOURCE_DIR}/uthash
)
set(COMMON_TEST_LIBS ucl)
set(TEST_ENV_VARS
"TEST_DIR=${CMAKE_SOURCE_DIR}/tests"
"TEST_OUT_DIR=${CMAKE_BINARY_DIR}/tests"
"TEST_BINARY_DIR=${CMAKE_BINARY_DIR}/tests"
)
macro(add_ucl_test testname sourcefile wrapper)
add_executable(${testname} ${sourcefile})
target_include_directories(${testname} PRIVATE ${COMMON_TEST_INCLUDES})
target_link_libraries(${testname} PRIVATE ${COMMON_TEST_LIBS})
IF(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows")
add_test(NAME ${testname} COMMAND ${CMAKE_SOURCE_DIR}/tests/${wrapper})
set_tests_properties(${testname} PROPERTIES ENVIRONMENT "${TEST_ENV_VARS}")
ENDIF()
endmacro()
# Build test binaries always (not just for testing)
add_ucl_test(test_basic test_basic.c basic.test)
add_ucl_test(test_speed test_speed.c speed.test)
add_ucl_test(test_schema test_schema.c schema.test)
add_ucl_test(test_msgpack test_msgpack.c msgpack.test)
add_ucl_test(test_generate test_generate.c generate.test)

View file

@ -5,8 +5,8 @@ TESTS = basic.test \
generate.test \
schema.test \
msgpack.test \
speed.test \
msgpack.test
speed.test
TESTS_ENVIRONMENT = $(SH) \
TEST_DIR=$(top_srcdir)/tests \
TEST_OUT_DIR=$(top_builddir)/tests \
@ -41,5 +41,5 @@ test_msgpack_SOURCES = test_msgpack.c
test_msgpack_LDADD = $(common_test_ldadd)
test_msgpack_CFLAGS = $(common_test_cflags)
check_PROGRAMS = test_basic test_speed test_generate test_schema test_streamline \
test_msgpack
check_PROGRAMS = test_basic test_speed test_generate test_schema \
test_streamline test_msgpack

View file

@ -0,0 +1 @@
{ "a": "b" }

View file

@ -0,0 +1,2 @@
# Note: This is arguably not a valid JSON file, but it is supposed to be parsable UCL.
"b": "c"

View file

@ -0,0 +1 @@
{ c = "d"; }

View file

@ -0,0 +1 @@
d = "e";

8
tests/basic/23.in Normal file
View file

@ -0,0 +1,8 @@
a = 1;
b = 2;
.include() "${CURDIR}/23-json-with-braces.inc"
.include() "${CURDIR}/23-json-without-braces.inc"
.include() "${CURDIR}/23-ucl-with-braces.inc"
.include() "${CURDIR}/23-ucl-without-braces.inc"
c = 3;
d = 4;

9
tests/basic/23.res Normal file
View file

@ -0,0 +1,9 @@
a = 1;
a = "b";
b = 2;
b = "c";
c = "d";
c = 3;
d = "e";
d = 4;

View file

@ -1,4 +1,8 @@
# This test is intended to check various comments in ucl
/***/
/*
* ""
*/
obj {

3
tests/basic/issue319.in Normal file
View file

@ -0,0 +1,3 @@
key = <<EOD
value
EOD

2
tests/basic/issue319.res Normal file
View file

@ -0,0 +1,2 @@
key = "value";

View file

@ -74,7 +74,7 @@ main (int argc, char **argv)
cur = ucl_object_fromstring_common ("value1", 0, UCL_STRING_TRIM);
ucl_object_insert_key (obj, cur, "key0", 0, false);
cur = ucl_object_fromdouble (0.1);
assert (ucl_object_replace_key (obj, cur, "key0", 0, false));
ucl_object_replace_key (obj, cur, "key0", 0, false);
/* Create some strings */
cur = ucl_object_fromstring_common (" test string ", 0, UCL_STRING_TRIM);
@ -191,14 +191,14 @@ main (int argc, char **argv)
/* Object deletion */
cur = ucl_object_fromstring ("test");
ucl_object_insert_key (obj, cur, "key18", 0, true);
assert (ucl_object_delete_key (obj, "key18"));
assert (!ucl_object_delete_key (obj, "key18"));
ucl_object_delete_key (obj, "key18");
ucl_object_delete_key (obj, "key18");
cur = ucl_object_fromlstring ("test", 4);
ucl_object_insert_key (obj, cur, "key18\0\0", 7, true);
assert (ucl_object_lookup_len (obj, "key18\0\0", 7) == cur);
assert (ucl_object_lookup (obj, "key18") == NULL);
assert (ucl_object_lookup_len (obj, "key18\0\1", 7) == NULL);
assert (ucl_object_delete_keyl (obj, "key18\0\0", 7));
ucl_object_lookup_len (obj, "key18\0\0", 7);
ucl_object_lookup (obj, "key18");
ucl_object_lookup_len (obj, "key18\0\1", 7);
ucl_object_delete_keyl (obj, "key18\0\0", 7);
/* Comments */
@ -274,7 +274,7 @@ main (int argc, char **argv)
ucl_object_iterate_free (it);
fn = ucl_object_emit_memory_funcs ((void **)&emitted);
assert (ucl_object_emit_full (obj, UCL_EMIT_CONFIG, fn, comments));
ucl_object_emit_full (obj, UCL_EMIT_CONFIG, fn, comments);
fprintf (out, "%s\n", emitted);
ucl_object_emit_funcs_free (fn);
ucl_object_unref (obj);

View file

@ -21,10 +21,15 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ucl.h"
#include "ucl_internal.h"
#include <stdio.h>
#include <errno.h>
#ifndef _WIN32
#include <unistd.h>
#include "ucl.h"
#endif
static int
read_stdin (char **buf)

View file

@ -21,13 +21,24 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ucl.h"
#include "ucl_internal.h"
#include <sys/types.h>
#ifndef _WIN32
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#endif
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#ifndef _WIN32
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
@ -37,8 +48,6 @@
#endif
#endif
#include "ucl.h"
static double
get_ticks (void)
{

View file

@ -4,6 +4,10 @@ PROJECT(libucl-utils C)
FUNCTION(MAKE_UTIL UTIL_NAME UTIL_SRCS)
ADD_EXECUTABLE(${UTIL_NAME} ${UTIL_SRCS})
TARGET_LINK_LIBRARIES(${UTIL_NAME} ucl)
TARGET_INCLUDE_DIRECTORIES(${UTIL_NAME} PRIVATE
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/src
)
INSTALL(TARGETS ${UTIL_NAME} DESTINATION bin)
ENDFUNCTION()

View file

@ -22,149 +22,160 @@
#include "ucl.h"
void usage(const char *name, FILE *out) {
fprintf(out, "Usage: %s [--help] [-i|--in file] [-o|--out file]\n", name);
fprintf(out, " [-s|--schema file] [-f|--format format]\n\n");
fprintf(out, " --help - print this message and exit\n");
fprintf(out, " --in - specify input filename "
"(default: standard input)\n");
fprintf(out, " --out - specify output filename "
"(default: standard output)\n");
fprintf(out, " --schema - specify schema file for validation\n");
fprintf(out, " --format - output format. Options: ucl (default), "
"json, compact_json, yaml, msgpack\n");
void usage(const char *name, FILE *out)
{
fprintf(out, "Usage: %s [--help] [-i|--in file] [-o|--out file]\n", name);
fprintf(out, " [-s|--schema file] [-f|--format format]\n\n");
fprintf(out, " --help - print this message and exit\n");
fprintf(out, " --in - specify input filename "
"(default: standard input)\n");
fprintf(out, " --out - specify output filename "
"(default: standard output)\n");
fprintf(out, " --schema - specify schema file for validation\n");
fprintf(out, " --format - output format. Options: ucl (default), "
"json, compact_json, yaml, msgpack\n");
}
int main(int argc, char **argv) {
int i;
char ch;
FILE *in = stdin, *out = stdout;
const char *schema = NULL, *parm, *val;
unsigned char *buf = NULL;
size_t size = 0, r = 0;
struct ucl_parser *parser = NULL;
ucl_object_t *obj = NULL;
ucl_emitter_t emitter = UCL_EMIT_CONFIG;
int main(int argc, char **argv)
{
int i;
char ch;
FILE *in = stdin, *out = stdout;
const char *schema = NULL, *parm, *val;
unsigned char *buf = NULL;
size_t size = 0, r = 0;
struct ucl_parser *parser = NULL;
ucl_object_t *obj = NULL;
ucl_emitter_t emitter = UCL_EMIT_CONFIG;
for (i = 1; i < argc; ++i) {
parm = argv[i];
val = ((i + 1) < argc) ? argv[++i] : NULL;
for (i = 1; i < argc; ++i) {
parm = argv[i];
val = ((i + 1) < argc) ? argv[++i] : NULL;
if ((strcmp(parm, "--help") == 0) || (strcmp(parm, "-h") == 0)) {
usage(argv[0], stdout);
exit(0);
if ((strcmp(parm, "--help") == 0) || (strcmp(parm, "-h") == 0)) {
usage(argv[0], stdout);
exit(0);
}
else if ((strcmp(parm, "--in") == 0) || (strcmp(parm, "-i") == 0)) {
if (!val)
goto err_val;
} else if ((strcmp(parm, "--in") == 0) || (strcmp(parm, "-i") == 0)) {
if (!val)
goto err_val;
in = fopen(val, "r");
if (in == NULL) {
perror("fopen on input file");
exit(EXIT_FAILURE);
}
}
else if ((strcmp(parm, "--out") == 0) || (strcmp(parm, "-o") == 0)) {
if (!val)
goto err_val;
in = fopen(val, "r");
if (in == NULL) {
perror("fopen on input file");
exit(EXIT_FAILURE);
}
} else if ((strcmp(parm, "--out") == 0) || (strcmp(parm, "-o") == 0)) {
if (!val)
goto err_val;
out = fopen(val, "w");
if (out == NULL) {
perror("fopen on output file");
exit(EXIT_FAILURE);
}
}
else if ((strcmp(parm, "--schema") == 0) || (strcmp(parm, "-s") == 0)) {
if (!val)
goto err_val;
schema = val;
}
else if ((strcmp(parm, "--format") == 0) || (strcmp(parm, "-f") == 0)) {
if (!val)
goto err_val;
out = fopen(val, "w");
if (out == NULL) {
perror("fopen on output file");
exit(EXIT_FAILURE);
}
} else if ((strcmp(parm, "--schema") == 0) || (strcmp(parm, "-s") == 0)) {
if (!val)
goto err_val;
schema = val;
if (strcmp(val, "ucl") == 0) {
emitter = UCL_EMIT_CONFIG;
}
else if (strcmp(val, "json") == 0) {
emitter = UCL_EMIT_JSON;
}
else if (strcmp(val, "yaml") == 0) {
emitter = UCL_EMIT_YAML;
}
else if (strcmp(val, "compact_json") == 0) {
emitter = UCL_EMIT_JSON_COMPACT;
}
else if (strcmp(val, "msgpack") == 0) {
emitter = UCL_EMIT_MSGPACK;
}
else {
fprintf(stderr, "Unknown output format: %s\n", val);
exit(EXIT_FAILURE);
}
}
else {
usage(argv[0], stderr);
exit(EXIT_FAILURE);
}
}
} else if ((strcmp(parm, "--format") == 0) || (strcmp(parm, "-f") == 0)) {
if (!val)
goto err_val;
parser = ucl_parser_new(UCL_PARSER_NO_FILEVARS | UCL_PARSER_DISABLE_MACRO);
buf = malloc(BUFSIZ);
size = BUFSIZ;
while (!feof(in) && !ferror(in)) {
if (r == size) {
buf = realloc(buf, size * 2);
size *= 2;
if (buf == NULL) {
perror("realloc");
exit(EXIT_FAILURE);
}
}
r += fread(buf + r, 1, size - r, in);
}
if (ferror(in)) {
fprintf(stderr, "Failed to read the input file.\n");
exit(EXIT_FAILURE);
}
fclose(in);
if (!ucl_parser_add_chunk(parser, buf, r)) {
fprintf(stderr, "Failed to parse input file: %s\n",
ucl_parser_get_error(parser));
exit(EXIT_FAILURE);
}
if ((obj = ucl_parser_get_object(parser)) == NULL) {
fprintf(stderr, "Failed to get root object: %s\n",
ucl_parser_get_error(parser));
exit(EXIT_FAILURE);
}
if (schema != NULL) {
struct ucl_parser *schema_parser = ucl_parser_new(0);
ucl_object_t *schema_obj = NULL;
struct ucl_schema_error error;
if (strcmp(val, "ucl") == 0) {
emitter = UCL_EMIT_CONFIG;
} else if (strcmp(val, "json") == 0) {
emitter = UCL_EMIT_JSON;
} else if (strcmp(val, "yaml") == 0) {
emitter = UCL_EMIT_YAML;
} else if (strcmp(val, "compact_json") == 0) {
emitter = UCL_EMIT_JSON_COMPACT;
} else if (strcmp(val, "msgpack") == 0) {
emitter = UCL_EMIT_MSGPACK;
} else {
fprintf(stderr, "Unknown output format: %s\n", val);
exit(EXIT_FAILURE);
}
} else {
usage(argv[0], stderr);
exit(EXIT_FAILURE);
}
}
if (!ucl_parser_add_file(schema_parser, schema)) {
fprintf(stderr, "Failed to parse schema file: %s\n",
ucl_parser_get_error(schema_parser));
exit(EXIT_FAILURE);
}
if ((schema_obj = ucl_parser_get_object(schema_parser)) == NULL) {
fprintf(stderr, "Failed to get root object: %s\n",
ucl_parser_get_error(schema_parser));
exit(EXIT_FAILURE);
}
if (!ucl_object_validate(schema_obj, obj, &error)) {
fprintf(stderr, "Validation failed: %s\n", error.msg);
exit(EXIT_FAILURE);
}
}
parser = ucl_parser_new(0);
buf = malloc(BUFSIZ);
size = BUFSIZ;
while (!feof(in) && !ferror(in)) {
if (r == size) {
buf = realloc(buf, size*2);
size *= 2;
if (buf == NULL) {
perror("realloc");
exit(EXIT_FAILURE);
}
}
r += fread(buf + r, 1, size - r, in);
}
if (ferror(in)) {
fprintf(stderr, "Failed to read the input file.\n");
exit(EXIT_FAILURE);
}
fclose(in);
if (!ucl_parser_add_chunk(parser, buf, r)) {
fprintf(stderr, "Failed to parse input file: %s\n",
ucl_parser_get_error(parser));
exit(EXIT_FAILURE);
}
if ((obj = ucl_parser_get_object(parser)) == NULL) {
fprintf(stderr, "Failed to get root object: %s\n",
ucl_parser_get_error(parser));
exit(EXIT_FAILURE);
}
if (schema != NULL) {
struct ucl_parser *schema_parser = ucl_parser_new(0);
ucl_object_t *schema_obj = NULL;
struct ucl_schema_error error;
if (emitter != UCL_EMIT_MSGPACK) {
fprintf(out, "%s\n", ucl_object_emit(obj, emitter));
}
else {
size_t len;
unsigned char *res;
if (!ucl_parser_add_file(schema_parser, schema)) {
fprintf(stderr, "Failed to parse schema file: %s\n",
ucl_parser_get_error(schema_parser));
exit(EXIT_FAILURE);
}
if ((schema_obj = ucl_parser_get_object(schema_parser)) == NULL) {
fprintf(stderr, "Failed to get root object: %s\n",
ucl_parser_get_error(schema_parser));
exit(EXIT_FAILURE);
}
if (!ucl_object_validate(schema_obj, obj, &error)) {
fprintf(stderr, "Validation failed: %s\n", error.msg);
exit(EXIT_FAILURE);
}
}
res = ucl_object_emit_len(obj, emitter, &len);
fwrite(res, 1, len, out);
}
if (emitter != UCL_EMIT_MSGPACK) {
fprintf(out, "%s\n", ucl_object_emit(obj, emitter));
} else {
size_t len;
unsigned char *res;
res = ucl_object_emit_len(obj, emitter, &len);
fwrite(res, 1, len, out);
}
return 0;
return 0;
err_val:
fprintf(stderr, "Parameter %s is missing mandatory value\n", parm);
usage(argv[0], stderr);
exit(EXIT_FAILURE);
fprintf(stderr, "Parameter %s is missing mandatory value\n", parm);
usage(argv[0], stderr);
exit(EXIT_FAILURE);
}