Index: contrib/libucl/.gitignore =================================================================== --- contrib/libucl/.gitignore (revision 0) +++ contrib/libucl/.gitignore (working copy) @@ -0,0 +1,3 @@ +.cproject +.project +.settings Index: contrib/libucl/Doxyfile =================================================================== --- contrib/libucl/Doxyfile (revision 0) +++ contrib/libucl/Doxyfile (working copy) @@ -0,0 +1,1921 @@ +# Doxyfile 1.8.4 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = UCL + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = /auto/homes/vs374/libucl/doc + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Latvian, Lithuanian, Norwegian, Macedonian, +# Persian, Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, +# Slovak, Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. Note that you specify absolute paths here, but also +# relative paths, which will be relative from the directory where doxygen is +# started. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, +# and language is one of the parsers supported by doxygen: IDL, Java, +# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, +# C++. For instance to make doxygen treat .inc files as Fortran files (default +# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note +# that for custom extensions you also need to set FILE_PATTERNS otherwise the +# files are not read by doxygen. + +EXTENSION_MAPPING = + +# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all +# comments according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you +# can mix doxygen, HTML, and XML commands with Markdown formatting. +# Disable only in case of backward compatibilities issues. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES (the +# default) will make doxygen replace the get and set methods by a property in +# the documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields or simple typedef fields will be shown +# inline in the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO (the default), structs, classes, and unions are shown on a separate +# page (for HTML and Man pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can +# be an expensive process and often the same symbol appear multiple times in +# the code, doxygen keeps a cache of pre-resolved symbols. If the cache is too +# small doxygen will become slower. If the cache is too large, memory is wasted. +# The cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid +# range is 0..9, the default is 0, corresponding to a cache size of 2^16 = 65536 +# symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if section-label ... \endif +# and \cond section-label ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. Do not use +# file names with spaces, bibtex cannot handle them. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = /auto/homes/vs374/libucl/include + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.for \ + *.vhd \ + *.vhdl + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be ignored. +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C, C++ and Fortran comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If left blank doxygen will +# generate a default style sheet. Note that it is recommended to use +# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this +# tag will in the future become obsolete. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional +# user-defined cascading style sheet that is included after the standard +# style sheets created by doxygen. Using this option one can overrule +# certain style aspects. This is preferred over using HTML_STYLESHEET +# since it does not replace the standard style sheet and is therefor more +# robust against future updates. Doxygen will copy the style sheet file to +# the output directory. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of +# entries shown in the various tree structured indices initially; the user +# can expand and collapse entries dynamically later on. Doxygen will expand +# the tree to such a level that at most the specified number of entries are +# visible (unless a fully collapsed tree already exceeds this amount). +# So setting the number of entries 1 will produce a full collapsed tree by +# default. 0 is a special value representing an infinite number of entries +# and will result in a full expanded tree by default. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely +# identify the documentation publisher. This should be a reverse domain-name +# style string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = YES + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you may also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and +# SVG. The default value is HTML-CSS, which is slower, but has the best +# compatibility. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to +# the MathJax Content Delivery Network so you can quickly see the result without +# installing MathJax. However, it is strongly recommended to install a local +# copy of MathJax from http://www.mathjax.org before deployment. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript +# pieces of code that will be used on startup of the MathJax code. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = NO + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a web server instead of a web client using Javascript. +# There are two flavours of web server based search depending on the +# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for +# searching and an index file used by the script. When EXTERNAL_SEARCH is +# enabled the indexing and searching needs to be provided by external tools. +# See the manual for details. + +SERVER_BASED_SEARCH = NO + +# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP +# script for searching. Instead the search results are written to an XML file +# which needs to be processed by an external indexer. Doxygen will invoke an +# external search engine pointed to by the SEARCHENGINE_URL option to obtain +# the search results. Doxygen ships with an example indexer (doxyindexer) and +# search engine (doxysearch.cgi) which are based on the open source search +# engine library Xapian. See the manual for configuration details. + +EXTERNAL_SEARCH = NO + +# The SEARCHENGINE_URL should point to a search engine hosted by a web server +# which will returned the search results when EXTERNAL_SEARCH is enabled. +# Doxygen ships with an example search engine (doxysearch) which is based on +# the open source search engine library Xapian. See the manual for configuration +# details. + +SEARCHENGINE_URL = + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed +# search data is written to a file for indexing by an external tool. With the +# SEARCHDATA_FILE tag the name of this file can be specified. + +SEARCHDATA_FILE = searchdata.xml + +# When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the +# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is +# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple +# projects and redirect the results back to the right project. + +EXTERNAL_SEARCH_ID = + +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen +# projects other than the one defined by this configuration file, but that are +# all added to the same external search index. Each project needs to have a +# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id +# of to a relative location where the documentation can be found. +# The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ... + +EXTRA_SEARCH_MAPPINGS = + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4 will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images +# or other source files which should be copied to the LaTeX output directory. +# Note that the files will be copied as-is; there are no commands or markers +# available. + +LATEX_EXTRA_FILES = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- + +# If the GENERATE_DOCBOOK tag is set to YES Doxygen will generate DOCBOOK files +# that can be used to generate PDF. + +GENERATE_DOCBOOK = NO + +# The DOCBOOK_OUTPUT tag is used to specify where the DOCBOOK pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in +# front of it. If left blank docbook will be used as the default path. + +DOCBOOK_OUTPUT = docbook + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. For each +# tag file the location of the external documentation should be added. The +# format of a tag file without this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths +# or URLs. Note that each tag file must have a unique name (where the name does +# NOT include the path). If a tag file is not located in the directory in which +# doxygen is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed +# in the related pages index. If set to NO, only the current project's +# pages will be listed. + +EXTERNAL_PAGES = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside +# the class node. If there are many fields or methods and many nodes the +# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS +# threshold limits the number of items for each type to make the size more +# manageable. Set this to 0 for no limit. Note that the threshold may be +# exceeded by 50% before the limit is enforced. + +UML_LIMIT_NUM_FIELDS = 10 + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES Index: contrib/libucl/Makefile =================================================================== --- contrib/libucl/Makefile (revision 0) +++ contrib/libucl/Makefile (working copy) @@ -0,0 +1,79 @@ +CC ?= gcc +DESTDIR ?= /usr/local +LD ?= gcc +C_COMMON_FLAGS ?= -fPIC -Wall -W -Wno-unused-parameter -Wno-pointer-sign -I./include -I./uthash -I./src +MAJOR_VERSION = 0 +MINOR_VERSION = 2 +PATCH_VERSION = 5 +VERSION = "$(MAJOR_VERSION).$(MINOR_VERSION).$(PATCH_VERSION)" +SONAME = libucl.so +SONAME_FULL = $(SONAME).$(MAJOR_VERSION) +OBJDIR ?= .obj +TESTDIR ?= tests +SRCDIR ?= src +INCLUDEDIR ?= include +MKDIR ?= mkdir +INSTALL ?= install +RM ?= rm +RMDIR ?= rmdir +LN ?= ln +LD_SHARED_FLAGS ?= -Wl,-soname,$(SONAME) -shared -lm +LD_UCL_FLAGS ?= -L$(OBJDIR) -Wl,-rpath,$(OBJDIR) -lucl +LD_ADD ?= -lrt +COPT_FLAGS ?= -g -O0 +HDEPS = $(SRCDIR)/ucl_hash.h $(SRCDIR)/ucl_chartable.h $(SRCDIR)/ucl_internal.h $(INCLUDEDIR)/ucl.h $(SRCDIR)/xxhash.h +OBJECTS = $(OBJDIR)/ucl_hash.o $(OBJDIR)/ucl_util.o $(OBJDIR)/ucl_parser.o $(OBJDIR)/ucl_emitter.o $(OBJDIR)/xxhash.o + +all: $(OBJDIR) $(OBJDIR)/$(SONAME) + +$(OBJDIR)/$(SONAME): $(OBJDIR)/$(SONAME_FULL) + $(LN) -sf $(SONAME_FULL) $(OBJDIR)/$(SONAME) + +$(OBJDIR)/$(SONAME_FULL): $(OBJECTS) + $(CC) -o $(OBJDIR)/$(SONAME_FULL) $(OBJECTS) $(LD_SHARED_FLAGS) $(LDFLAGS) $(SSL_LIBS) $(FETCH_LIBS) + +$(OBJDIR): + @$(MKDIR) -p $(OBJDIR) + +# Compile rules +$(OBJDIR)/ucl_util.o: $(SRCDIR)/ucl_util.c $(HDEPS) + $(CC) -o $(OBJDIR)/ucl_util.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_util.c +$(OBJDIR)/ucl_parser.o: $(SRCDIR)/ucl_parser.c $(HDEPS) + $(CC) -o $(OBJDIR)/ucl_parser.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_parser.c +$(OBJDIR)/ucl_emitter.o: $(SRCDIR)/ucl_emitter.c $(HDEPS) + $(CC) -o $(OBJDIR)/ucl_emitter.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_emitter.c +$(OBJDIR)/ucl_hash.o: $(SRCDIR)/ucl_hash.c $(HDEPS) + $(CC) -o $(OBJDIR)/ucl_hash.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_hash.c +$(OBJDIR)/xxhash.o: $(SRCDIR)/xxhash.c $(HDEPS) + $(CC) -o $(OBJDIR)/xxhash.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/xxhash.c + +clean: + $(RM) $(OBJDIR)/*.o $(OBJDIR)/$(SONAME_FULL) $(OBJDIR)/$(SONAME) $(OBJDIR)/chargen $(OBJDIR)/test_basic $(OBJDIR)/test_speed $(OBJDIR)/objdump $(OBJDIR)/test_generate + $(RMDIR) $(OBJDIR) + +# Utils + +chargen: utils/chargen.c $(OBJDIR)/$(SONAME) + $(CC) -o $(OBJDIR)/chargen $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) $(LDFLAGS) utils/chargen.c +objdump: utils/objdump.c $(OBJDIR)/$(SONAME) + $(CC) -o $(OBJDIR)/objdump $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) $(LDFLAGS) utils/objdump.c $(LD_UCL_FLAGS) + +# Tests + +test: $(OBJDIR) $(OBJDIR)/$(SONAME) $(OBJDIR)/test_basic $(OBJDIR)/test_speed $(OBJDIR)/test_generate + +run-test: test + TEST_DIR=$(TESTDIR) $(TESTDIR)/run_tests.sh $(OBJDIR)/test_basic $(OBJDIR)/test_speed $(OBJDIR)/test_generate + +$(OBJDIR)/test_basic: $(TESTDIR)/test_basic.c $(OBJDIR)/$(SONAME) + $(CC) -o $(OBJDIR)/test_basic $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) $(LDFLAGS) $(TESTDIR)/test_basic.c $(LD_UCL_FLAGS) +$(OBJDIR)/test_speed: $(TESTDIR)/test_speed.c $(OBJDIR)/$(SONAME) + $(CC) -o $(OBJDIR)/test_speed $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) $(LDFLAGS) $(TESTDIR)/test_speed.c $(LD_UCL_FLAGS) $(LD_ADD) +$(OBJDIR)/test_generate: $(TESTDIR)/test_generate.c $(OBJDIR)/$(SONAME) + $(CC) -o $(OBJDIR)/test_generate $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) $(LDFLAGS) $(TESTDIR)/test_generate.c $(LD_UCL_FLAGS) $(LD_ADD) + +install: $(OBJDIR)/$(SONAME) + $(INSTALL) -m0755 $(SONAME) $(DESTDIR)/lib/$(SONAME) + $(INSTALL) -m0644 include/ucl.h $(DESTDIR)/include/ucl.h + +.PHONY: clean $(OBJDIR) Property changes on: contrib/libucl/Makefile ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/README.md =================================================================== --- contrib/libucl/README.md (revision 0) +++ contrib/libucl/README.md (working copy) @@ -0,0 +1,296 @@ +## Introduction + +This document describes the main features and principles of the configuration +language called `UCL` - universal configuration language. + +## Basic structure + +UCL is heavily infused by `nginx` configuration as the example of a convenient configuration +system. However, UCL is fully compatible with `JSON` format and is able to parse json files. +For example, you can write the same configuration in the following ways: + +* in nginx like: + +```nginx +param = value; +section { + param = value; + param1 = value1; + flag = true; + number = 10k; + time = 0.2s; + string = "something"; + subsection { + host = { + host = "hostname"; + port = 900; + } + host = { + host = "hostname"; + port = 901; + } + } +} +``` + +* or in JSON: + +```json +{ + "param": "value", + "param1": "value1", + "flag": true, + "subsection": { + "host": [ + { + "host": "hostname", + "port": 900 + }, + { + "host": "hostname", + "port": 901 + } + ] + } +} +``` + +## Improvements to the json notation. + +There are various things that make ucl configuration more convenient for editing than strict json: + +### General syntax sugar + +* Braces are not necessary to enclose a top object: it is automatically treated as an object: + +```json +"key": "value" +``` +is equal to: +```json +{"key": "value"} +``` + +* There is no requirement of quotes for strings and keys, moreover, `:` may be replaced `=` or even be skipped for objects: + +```nginx +key = value; +section { + key = value; +} +``` +is equal to: +```json +{ + "key": "value", + "section": { + "key": "value" + } +} +``` + +* No commas mess: you can safely place a comma or semicolon for the last element in an array or an object: + +```json +{ + "key1": "value", + "key2": "value", +} +``` +### Automatic arrays creation + +* Non-unique keys in an object are allowed and are automatically converted to the arrays internally: + +```json +{ + "key": "value1", + "key": "value2" +} +``` +is converted to: +```json +{ + "key": ["value1", "value2"] +} +``` + +### Named keys hierarchy + +UCL accepts named keys and organize them into objects hierarchy internally. Here is an example of this process: +```nginx +section "blah" { + key = value; +} +section foo { + key = value; +} +``` + +is converted to the following object: + +```nginx +section { + blah { + key = value; + } + foo { + key = value; + } +} +``` + +Plain definitions may be more complex and contain more than a single level of nested objects: + +```nginx +section "blah" "foo" { + key = value; +} +``` + +is presented as: + +```nginx +section { + blah { + foo { + key = value; + } + } +} +``` + +### Convenient numbers and booleans + +* Numbers can have suffixes to specify standard multipliers: + + `[kKmMgG]` - standard 10 base multipliers (so `1k` is translated to 1000) + + `[kKmMgG]b` - 2 power multipliers (so `1kb` is translated to 1024) + + `[s|min|d|w|y]` - time multipliers, all time values are translated to float number of seconds, for example `10min` is translated to 600.0 and `10ms` is translated to 0.01 +* Booleans can be specified as `true` or `yes` or `on` and `false` or `no` or `off`. +* It is still possible to treat numbers and booleans as strings by enclosing them in double quotes. + +## General improvements + +### Commments + +UCL supports different style of comments: + +* single line: `#` +* multiline: `/* ... */` + +Multiline comments may be nested: +```c +# Sample single line comment +/* + some comment + /* nested comment */ + end of comment +*/ +``` + +### Macros support + +UCL supports external macros both multiline and single line ones: +```nginx +.macro "sometext"; +.macro { + Some long text + .... +}; +``` +There are two internal macros provided by UCL: + +* `include` - read a file `/path/to/file` or an url `http://example.com/file` and include it to the current place of +UCL configuration; +* `includes` - read a file or an url like the previous macro, but fetch and check the signature file (which is obtained +by `.sig` suffix appending). + +Public keys which are used for the last command are specified by the concrete UCL user. + +### Variables support + +UCL supports variables in input. Variables are registered by a user of the UCL parser and can be presented in the following forms: + +* `${VARIABLE}` +* `$VARIABLE` + +UCL currently does not support nested variables. To escape variables one could use double dollar signs: + +* `$${VARIABLE}` is converted to `${VARIABLE}` +* `$$VARIABLE` is converted to `$VARIABLE` + +However, if no valid variables are found in a string, no expansion will be performed (and `$$` thus remains unchanged). This may be a subject +to change in future libucl releases. + +### Multiline strings + +UCL can handle multiline strings as well as single line ones. It uses shell/perl like notation for such objects: +``` +key = < + + + + + +UCL: Data Structures + + + + + + +
+
+ + + + + + +
+
UCL +
+
+
+ + +
+
+
+
Data Structures
+
+
+
Here are the data structures with brief descriptions:
+ + +
\Cucl_object_s
+
+
+ + + + Property changes on: contrib/libucl/doc/html/annotated.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: contrib/libucl/doc/html/bc_s.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/bc_s.png =================================================================== --- contrib/libucl/doc/html/bc_s.png (revision 0) +++ contrib/libucl/doc/html/bc_s.png (working copy) Property changes on: contrib/libucl/doc/html/bc_s.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/bdwn.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/bdwn.png =================================================================== --- contrib/libucl/doc/html/bdwn.png (revision 0) +++ contrib/libucl/doc/html/bdwn.png (working copy) Property changes on: contrib/libucl/doc/html/bdwn.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/classes.html =================================================================== --- contrib/libucl/doc/html/classes.html (revision 0) +++ contrib/libucl/doc/html/classes.html (working copy) @@ -0,0 +1,52 @@ + + + + + + +UCL: Data Structure Index + + + + + + +
+
+ + + + + + +
+
UCL +
+
+
+ + +
+
+
+
Data Structure Index
+
+
+ + + + + + +
  U  
+
ucl_object_s   
+ +
+ + + + Property changes on: contrib/libucl/doc/html/classes.html ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/doc/html/closed.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/closed.png =================================================================== --- contrib/libucl/doc/html/closed.png (revision 0) +++ contrib/libucl/doc/html/closed.png (working copy) Property changes on: contrib/libucl/doc/html/closed.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/dir_d44c64559bbebec7f509842c48db8b23.html =================================================================== --- contrib/libucl/doc/html/dir_d44c64559bbebec7f509842c48db8b23.html (revision 0) +++ contrib/libucl/doc/html/dir_d44c64559bbebec7f509842c48db8b23.html (working copy) @@ -0,0 +1,54 @@ + + + + + + +UCL: include Directory Reference + + + + + + +
+
+ + + + + + +
+
UCL +
+
+
+ + + +
+
+
+
include Directory Reference
+
+
+ + + + + +

+Files

file  ucl.h [code]
 UCL parsing and emitting functions.
 
+
+ + + + Property changes on: contrib/libucl/doc/html/dir_d44c64559bbebec7f509842c48db8b23.html ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/doc/html/doxygen.css =================================================================== --- contrib/libucl/doc/html/doxygen.css (revision 0) +++ contrib/libucl/doc/html/doxygen.css (working copy) @@ -0,0 +1,1186 @@ +/* The standard CSS for doxygen 1.8.4 */ + +body, table, div, p, dl { + font: 400 14px/22px Roboto,sans-serif; +} + +/* @group Heading Levels */ + +h1.groupheader { + font-size: 150%; +} + +.title { + font: 400 14px/28px Roboto,sans-serif; + font-size: 150%; + font-weight: bold; + margin: 10px 2px; +} + +h2.groupheader { + border-bottom: 1px solid #879ECB; + color: #354C7B; + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; +} + +h3.groupheader { + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + +dt { + font-weight: bold; +} + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd, p.starttd { + margin-top: 2px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #9CAFD4; + color: #ffffff; + border: 1px double #869DCA; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code, a.code:visited { + color: #4665A2; +} + +a.codeRef, a.codeRef:visited { + color: #4665A2; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +pre.fragment { + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; + font-family: monospace, fixed; + font-size: 105%; +} + +div.fragment { + padding: 0px; + margin: 0px; + background-color: #FBFCFD; + border: 1px solid #C4CFE5; +} + +div.line { + font-family: monospace, fixed; + font-size: 13px; + min-height: 13px; + line-height: 1.0; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -53px; + padding-left: 53px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + + +span.lineno { + padding-right: 4px; + text-align: right; + border-right: 2px solid #0F0; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a { + background-color: #D8D8D8; +} + +span.lineno a:hover { + background-color: #C8C8C8; +} + +div.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background-color: white; + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 8px; +} + +td.indexkey { + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; + white-space: nowrap; + vertical-align: top; +} + +td.indexvalue { + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #EEF1F7; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +/* @end */ + +/* +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +*/ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #A3B4D7; +} + +th.dirtab { + background: #EBEFF6; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memSeparator { + border-bottom: 1px solid #DEE4F0; + line-height: 1px; + margin: 0px; + padding: 0px; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memItemRight { + width: 100%; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; + font-size: 80%; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 9px; +} + +.memnav { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + -webkit-transition: box-shadow 0.5s linear; + -moz-transition: box-shadow 0.5s linear; + -ms-transition: box-shadow 0.5s linear; + -o-transition: box-shadow 0.5s linear; + transition: box-shadow 0.5s linear; + display: table !important; + width: 100%; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; +} + +.memname { + font-weight: bold; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 4px; + border-top-left-radius: 4px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 10px 2px 10px; + background-color: #FBFCFD; + border-top-width: 0; + background-image:url('nav_g.png'); + background-repeat:repeat-x; + background-color: #FFFFFF; + /* opera specific markup */ + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} +.paramname code { + line-height: 14px; +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; +} + +.params .paramname, .retval .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view when not used as main index */ + +div.directory { + margin: 10px 0px; + border-top: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.even { + padding-left: 6px; + background-color: #F7F8FB; +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; +} + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +table.fieldtable { + /*width: 100%;*/ + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; + /*width: 100%;*/ +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image:url('tab_b.png'); + background-repeat:repeat-x; + background-position: 0 -5px; + height:30px; + line-height:30px; + color:#8AA0CC; + border:solid 1px #C2CDE4; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right:15px; + background-image:url('bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color:#364D7C; +} + +.navpath li.navelem a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; + color: #283A5D; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; +} + +.navpath li.navelem a:hover +{ + color:#6884BD; +} + +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#364D7C; + font-size: 8pt; +} + + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + margin: 0px; + border-bottom: 1px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +dl +{ + padding: 0 0 0 10px; +} + +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ +dl.section +{ + margin-left: 0px; + padding-left: 0px; +} + +dl.note +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #D0C000; +} + +dl.warning, dl.attention +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00D000; +} + +dl.deprecated +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #505050; +} + +dl.todo +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00C0E0; +} + +dl.test +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #3030E0; +} + +dl.bug +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #C08050; +} + +dl.section dd { + margin-bottom: 6px; +} + + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectname +{ + font: 300% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font: 120% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font: 50% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #5373B4; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +div.zoom +{ + border: 1px solid #90A5CE; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; +} + +dl.citelist dd { + margin:2px 0; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 20px 10px 10px; + width: 200px; +} + +div.toc li { + background: url("bdwn.png") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 Arial,FreeSans,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.level2 { + margin-left: 15px; +} + +div.toc li.level3 { + margin-left: 30px; +} + +div.toc li.level4 { + margin-left: 45px; +} + +.inherit_header { + font-weight: bold; + color: gray; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0px 2px 5px; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 4px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + Property changes on: contrib/libucl/doc/html/doxygen.css ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/css \ No newline at end of property Index: contrib/libucl/doc/html/doxygen.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/doxygen.png =================================================================== --- contrib/libucl/doc/html/doxygen.png (revision 0) +++ contrib/libucl/doc/html/doxygen.png (working copy) Property changes on: contrib/libucl/doc/html/doxygen.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/dynsections.js =================================================================== --- contrib/libucl/doc/html/dynsections.js (revision 0) +++ contrib/libucl/doc/html/dynsections.js (working copy) @@ -0,0 +1,97 @@ +function toggleVisibility(linkObj) +{ + var base = $(linkObj).attr('id'); + var summary = $('#'+base+'-summary'); + var content = $('#'+base+'-content'); + var trigger = $('#'+base+'-trigger'); + var src=$(trigger).attr('src'); + if (content.is(':visible')===true) { + content.hide(); + summary.show(); + $(linkObj).addClass('closed').removeClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); + } else { + content.show(); + summary.hide(); + $(linkObj).removeClass('closed').addClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); + } + return false; +} + +function updateStripes() +{ + $('table.directory tr'). + removeClass('even').filter(':visible:even').addClass('even'); +} +function toggleLevel(level) +{ + $('table.directory tr').each(function(){ + var l = this.id.split('_').length-1; + var i = $('#img'+this.id.substring(3)); + var a = $('#arr'+this.id.substring(3)); + if (l + + + + + +UCL: File List + + + + + + +
+
+ + + + + + +
+
UCL +
+
+
+ + +
+
+
+
File List
+
+
+
Here is a list of all documented files with brief descriptions:
+
[detail level 12]
+ + +
\-include
 \*ucl.hUCL parsing and emitting functions
+
+
+ + + + Property changes on: contrib/libucl/doc/html/files.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: contrib/libucl/doc/html/ftv2blank.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/ftv2blank.png =================================================================== --- contrib/libucl/doc/html/ftv2blank.png (revision 0) +++ contrib/libucl/doc/html/ftv2blank.png (working copy) Property changes on: contrib/libucl/doc/html/ftv2blank.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/ftv2cl.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/ftv2cl.png =================================================================== --- contrib/libucl/doc/html/ftv2cl.png (revision 0) +++ contrib/libucl/doc/html/ftv2cl.png (working copy) Property changes on: contrib/libucl/doc/html/ftv2cl.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/ftv2doc.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/ftv2doc.png =================================================================== --- contrib/libucl/doc/html/ftv2doc.png (revision 0) +++ contrib/libucl/doc/html/ftv2doc.png (working copy) Property changes on: contrib/libucl/doc/html/ftv2doc.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/ftv2folderclosed.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/ftv2folderclosed.png =================================================================== --- contrib/libucl/doc/html/ftv2folderclosed.png (revision 0) +++ contrib/libucl/doc/html/ftv2folderclosed.png (working copy) Property changes on: contrib/libucl/doc/html/ftv2folderclosed.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/ftv2folderopen.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/ftv2folderopen.png =================================================================== --- contrib/libucl/doc/html/ftv2folderopen.png (revision 0) +++ contrib/libucl/doc/html/ftv2folderopen.png (working copy) Property changes on: contrib/libucl/doc/html/ftv2folderopen.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/ftv2lastnode.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/ftv2lastnode.png =================================================================== --- contrib/libucl/doc/html/ftv2lastnode.png (revision 0) +++ contrib/libucl/doc/html/ftv2lastnode.png (working copy) Property changes on: contrib/libucl/doc/html/ftv2lastnode.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/ftv2link.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/ftv2link.png =================================================================== --- contrib/libucl/doc/html/ftv2link.png (revision 0) +++ contrib/libucl/doc/html/ftv2link.png (working copy) Property changes on: contrib/libucl/doc/html/ftv2link.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/ftv2mlastnode.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/ftv2mlastnode.png =================================================================== --- contrib/libucl/doc/html/ftv2mlastnode.png (revision 0) +++ contrib/libucl/doc/html/ftv2mlastnode.png (working copy) Property changes on: contrib/libucl/doc/html/ftv2mlastnode.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/ftv2mnode.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/ftv2mnode.png =================================================================== --- contrib/libucl/doc/html/ftv2mnode.png (revision 0) +++ contrib/libucl/doc/html/ftv2mnode.png (working copy) Property changes on: contrib/libucl/doc/html/ftv2mnode.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/ftv2mo.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/ftv2mo.png =================================================================== --- contrib/libucl/doc/html/ftv2mo.png (revision 0) +++ contrib/libucl/doc/html/ftv2mo.png (working copy) Property changes on: contrib/libucl/doc/html/ftv2mo.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/ftv2node.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/ftv2node.png =================================================================== --- contrib/libucl/doc/html/ftv2node.png (revision 0) +++ contrib/libucl/doc/html/ftv2node.png (working copy) Property changes on: contrib/libucl/doc/html/ftv2node.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/ftv2ns.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/ftv2ns.png =================================================================== --- contrib/libucl/doc/html/ftv2ns.png (revision 0) +++ contrib/libucl/doc/html/ftv2ns.png (working copy) Property changes on: contrib/libucl/doc/html/ftv2ns.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/ftv2plastnode.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/ftv2plastnode.png =================================================================== --- contrib/libucl/doc/html/ftv2plastnode.png (revision 0) +++ contrib/libucl/doc/html/ftv2plastnode.png (working copy) Property changes on: contrib/libucl/doc/html/ftv2plastnode.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/ftv2pnode.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/ftv2pnode.png =================================================================== --- contrib/libucl/doc/html/ftv2pnode.png (revision 0) +++ contrib/libucl/doc/html/ftv2pnode.png (working copy) Property changes on: contrib/libucl/doc/html/ftv2pnode.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/ftv2splitbar.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/ftv2splitbar.png =================================================================== --- contrib/libucl/doc/html/ftv2splitbar.png (revision 0) +++ contrib/libucl/doc/html/ftv2splitbar.png (working copy) Property changes on: contrib/libucl/doc/html/ftv2splitbar.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/ftv2vertline.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/ftv2vertline.png =================================================================== --- contrib/libucl/doc/html/ftv2vertline.png (revision 0) +++ contrib/libucl/doc/html/ftv2vertline.png (working copy) Property changes on: contrib/libucl/doc/html/ftv2vertline.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/functions.html =================================================================== --- contrib/libucl/doc/html/functions.html (revision 0) +++ contrib/libucl/doc/html/functions.html (working copy) @@ -0,0 +1,89 @@ + + + + + + +UCL: Data Fields + + + + + + +
+
+ + + + + + +
+
UCL +
+
+
+ + +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+
+ + + + Property changes on: contrib/libucl/doc/html/functions.html ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/doc/html/functions_vars.html =================================================================== --- contrib/libucl/doc/html/functions_vars.html (revision 0) +++ contrib/libucl/doc/html/functions_vars.html (working copy) @@ -0,0 +1,89 @@ + + + + + + +UCL: Data Fields - Variables + + + + + + +
+
+ + + + + + +
+
UCL +
+
+
+ + +
+
+
+ + + + Property changes on: contrib/libucl/doc/html/functions_vars.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: contrib/libucl/doc/html/globals.html =================================================================== --- contrib/libucl/doc/html/globals.html (revision 0) +++ contrib/libucl/doc/html/globals.html (working copy) @@ -0,0 +1,250 @@ + + + + + + +UCL: Globals + + + + + + +
+
+ + + + + + +
+
UCL +
+
+
+ + +
+
+
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+ +

- u -

    +
  • UCL_ARRAY +: ucl.h +
  • +
  • UCL_BOOLEAN +: ucl.h +
  • +
  • ucl_copy_key_trash() +: ucl.h +
  • +
  • ucl_copy_value_trash() +: ucl.h +
  • +
  • UCL_EINTERNAL +: ucl.h +
  • +
  • UCL_EIO +: ucl.h +
  • +
  • UCL_EMACRO +: ucl.h +
  • +
  • UCL_EMIT_CONFIG +: ucl.h +
  • +
  • UCL_EMIT_JSON +: ucl.h +
  • +
  • UCL_EMIT_JSON_COMPACT +: ucl.h +
  • +
  • UCL_EMIT_YAML +: ucl.h +
  • +
  • ucl_emitter +: ucl.h +
  • +
  • ucl_emitter_t +: ucl.h +
  • +
  • UCL_ENESTED +: ucl.h +
  • +
  • UCL_EOK +: ucl.h +
  • +
  • ucl_error +: ucl.h +
  • +
  • ucl_error_t +: ucl.h +
  • +
  • UCL_ESSL +: ucl.h +
  • +
  • UCL_ESTATE +: ucl.h +
  • +
  • UCL_ESYNTAX +: ucl.h +
  • +
  • UCL_FLOAT +: ucl.h +
  • +
  • UCL_INT +: ucl.h +
  • +
  • ucl_iterate_object() +: ucl.h +
  • +
  • ucl_macro_handler +: ucl.h +
  • +
  • UCL_NULL +: ucl.h +
  • +
  • UCL_OBJECT +: ucl.h +
  • +
  • UCL_OBJECT_ALLOCATED_KEY +: ucl.h +
  • +
  • UCL_OBJECT_ALLOCATED_VALUE +: ucl.h +
  • +
  • ucl_object_emit() +: ucl.h +
  • +
  • ucl_object_find_key() +: ucl.h +
  • +
  • ucl_object_find_keyl() +: ucl.h +
  • +
  • ucl_object_flags +: ucl.h +
  • +
  • ucl_object_flags_t +: ucl.h +
  • +
  • ucl_object_free() +: ucl.h +
  • +
  • ucl_object_fromstring_common() +: ucl.h +
  • +
  • ucl_object_insert_key() +: ucl.h +
  • +
  • ucl_object_insert_key_merged() +: ucl.h +
  • +
  • ucl_object_iter_t +: ucl.h +
  • +
  • UCL_OBJECT_NEED_KEY_ESCAPE +: ucl.h +
  • +
  • ucl_object_t +: ucl.h +
  • +
  • ucl_parser_add_chunk() +: ucl.h +
  • +
  • ucl_parser_add_file() +: ucl.h +
  • +
  • ucl_parser_flags +: ucl.h +
  • +
  • ucl_parser_flags_t +: ucl.h +
  • +
  • ucl_parser_free() +: ucl.h +
  • +
  • ucl_parser_get_error() +: ucl.h +
  • +
  • ucl_parser_get_object() +: ucl.h +
  • +
  • UCL_PARSER_KEY_LOWERCASE +: ucl.h +
  • +
  • ucl_parser_new() +: ucl.h +
  • +
  • ucl_parser_register_macro() +: ucl.h +
  • +
  • ucl_parser_register_variable() +: ucl.h +
  • +
  • ucl_parser_set_filevars() +: ucl.h +
  • +
  • UCL_PARSER_ZEROCOPY +: ucl.h +
  • +
  • ucl_pubkey_add() +: ucl.h +
  • +
  • UCL_STRING +: ucl.h +
  • +
  • UCL_STRING_ESCAPE +: ucl.h +
  • +
  • ucl_string_flags +: ucl.h +
  • +
  • ucl_string_flags_t +: ucl.h +
  • +
  • UCL_STRING_PARSE +: ucl.h +
  • +
  • UCL_STRING_PARSE_BOOLEAN +: ucl.h +
  • +
  • UCL_STRING_PARSE_BYTES +: ucl.h +
  • +
  • UCL_STRING_PARSE_DOUBLE +: ucl.h +
  • +
  • UCL_STRING_PARSE_INT +: ucl.h +
  • +
  • UCL_STRING_PARSE_NUMBER +: ucl.h +
  • +
  • UCL_STRING_TRIM +: ucl.h +
  • +
  • UCL_TIME +: ucl.h +
  • +
  • ucl_type +: ucl.h +
  • +
  • ucl_type_t +: ucl.h +
  • +
  • UCL_USERDATA +: ucl.h +
  • +
+
+ + + + Property changes on: contrib/libucl/doc/html/globals.html ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/doc/html/globals_enum.html =================================================================== --- contrib/libucl/doc/html/globals_enum.html (revision 0) +++ contrib/libucl/doc/html/globals_enum.html (working copy) @@ -0,0 +1,59 @@ + + + + + + +UCL: Globals + + + + + + +
+
+ + + + + + +
+
UCL +
+
+
+ + +
+
    +
  • ucl_emitter +: ucl.h +
  • +
  • ucl_error +: ucl.h +
  • +
  • ucl_object_flags +: ucl.h +
  • +
  • ucl_parser_flags +: ucl.h +
  • +
  • ucl_string_flags +: ucl.h +
  • +
  • ucl_type +: ucl.h +
  • +
+
+ + + + Property changes on: contrib/libucl/doc/html/globals_enum.html ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/doc/html/globals_eval.html =================================================================== --- contrib/libucl/doc/html/globals_eval.html (revision 0) +++ contrib/libucl/doc/html/globals_eval.html (working copy) @@ -0,0 +1,145 @@ + + + + + + +UCL: Globals + + + + + + +
+
+ + + + + + +
+
UCL +
+
+
+ + +
+
+  + +

- u -

    +
  • UCL_ARRAY +: ucl.h +
  • +
  • UCL_BOOLEAN +: ucl.h +
  • +
  • UCL_EINTERNAL +: ucl.h +
  • +
  • UCL_EIO +: ucl.h +
  • +
  • UCL_EMACRO +: ucl.h +
  • +
  • UCL_EMIT_CONFIG +: ucl.h +
  • +
  • UCL_EMIT_JSON +: ucl.h +
  • +
  • UCL_EMIT_JSON_COMPACT +: ucl.h +
  • +
  • UCL_EMIT_YAML +: ucl.h +
  • +
  • UCL_ENESTED +: ucl.h +
  • +
  • UCL_EOK +: ucl.h +
  • +
  • UCL_ESSL +: ucl.h +
  • +
  • UCL_ESTATE +: ucl.h +
  • +
  • UCL_ESYNTAX +: ucl.h +
  • +
  • UCL_FLOAT +: ucl.h +
  • +
  • UCL_INT +: ucl.h +
  • +
  • UCL_NULL +: ucl.h +
  • +
  • UCL_OBJECT +: ucl.h +
  • +
  • UCL_OBJECT_ALLOCATED_KEY +: ucl.h +
  • +
  • UCL_OBJECT_ALLOCATED_VALUE +: ucl.h +
  • +
  • UCL_OBJECT_NEED_KEY_ESCAPE +: ucl.h +
  • +
  • UCL_PARSER_KEY_LOWERCASE +: ucl.h +
  • +
  • UCL_PARSER_ZEROCOPY +: ucl.h +
  • +
  • UCL_STRING +: ucl.h +
  • +
  • UCL_STRING_ESCAPE +: ucl.h +
  • +
  • UCL_STRING_PARSE +: ucl.h +
  • +
  • UCL_STRING_PARSE_BOOLEAN +: ucl.h +
  • +
  • UCL_STRING_PARSE_BYTES +: ucl.h +
  • +
  • UCL_STRING_PARSE_DOUBLE +: ucl.h +
  • +
  • UCL_STRING_PARSE_INT +: ucl.h +
  • +
  • UCL_STRING_PARSE_NUMBER +: ucl.h +
  • +
  • UCL_STRING_TRIM +: ucl.h +
  • +
  • UCL_TIME +: ucl.h +
  • +
  • UCL_USERDATA +: ucl.h +
  • +
+
+ + + + Property changes on: contrib/libucl/doc/html/globals_eval.html ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/doc/html/globals_func.html =================================================================== --- contrib/libucl/doc/html/globals_func.html (revision 0) +++ contrib/libucl/doc/html/globals_func.html (working copy) @@ -0,0 +1,101 @@ + + + + + + +UCL: Globals + + + + + + +
+
+ + + + + + +
+
UCL +
+
+
+ + +
+
    +
  • ucl_copy_key_trash() +: ucl.h +
  • +
  • ucl_copy_value_trash() +: ucl.h +
  • +
  • ucl_iterate_object() +: ucl.h +
  • +
  • ucl_object_emit() +: ucl.h +
  • +
  • ucl_object_find_key() +: ucl.h +
  • +
  • ucl_object_find_keyl() +: ucl.h +
  • +
  • ucl_object_free() +: ucl.h +
  • +
  • ucl_object_fromstring_common() +: ucl.h +
  • +
  • ucl_object_insert_key() +: ucl.h +
  • +
  • ucl_object_insert_key_merged() +: ucl.h +
  • +
  • ucl_parser_add_chunk() +: ucl.h +
  • +
  • ucl_parser_add_file() +: ucl.h +
  • +
  • ucl_parser_free() +: ucl.h +
  • +
  • ucl_parser_get_error() +: ucl.h +
  • +
  • ucl_parser_get_object() +: ucl.h +
  • +
  • ucl_parser_new() +: ucl.h +
  • +
  • ucl_parser_register_macro() +: ucl.h +
  • +
  • ucl_parser_register_variable() +: ucl.h +
  • +
  • ucl_parser_set_filevars() +: ucl.h +
  • +
  • ucl_pubkey_add() +: ucl.h +
  • +
+
+ + + + Property changes on: contrib/libucl/doc/html/globals_func.html ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/doc/html/globals_type.html =================================================================== --- contrib/libucl/doc/html/globals_type.html (revision 0) +++ contrib/libucl/doc/html/globals_type.html (working copy) @@ -0,0 +1,68 @@ + + + + + + +UCL: Globals + + + + + + +
+
+ + + + + + +
+
UCL +
+
+
+ + +
+
    +
  • ucl_emitter_t +: ucl.h +
  • +
  • ucl_error_t +: ucl.h +
  • +
  • ucl_macro_handler +: ucl.h +
  • +
  • ucl_object_flags_t +: ucl.h +
  • +
  • ucl_object_iter_t +: ucl.h +
  • +
  • ucl_object_t +: ucl.h +
  • +
  • ucl_parser_flags_t +: ucl.h +
  • +
  • ucl_string_flags_t +: ucl.h +
  • +
  • ucl_type_t +: ucl.h +
  • +
+
+ + + + Property changes on: contrib/libucl/doc/html/globals_type.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Index: contrib/libucl/doc/html/group__emitter.html =================================================================== --- contrib/libucl/doc/html/group__emitter.html (revision 0) +++ contrib/libucl/doc/html/group__emitter.html (working copy) @@ -0,0 +1,89 @@ + + + + + + +UCL: Emitting functions + + + + + + +
+
+ + + + + + +
+
UCL +
+
+
+ + +
+
+ +
+
Emitting functions
+
+
+ + + + +

+Functions

unsigned char * ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type)
 
+

Detailed Description

+

These functions are used to serialise UCL objects to some string representation.

+

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
unsigned char* ucl_object_emit (ucl_object_tobj,
enum ucl_emitter emit_type 
)
+
+

Emit object to a string

+
Parameters
+ + + +
objobject
emit_typeif type is UCL_EMIT_JSON then emit json, if type is UCL_EMIT_CONFIG then emit config like object
+
+
+
Returns
dump of an object (must be freed after using) or NULL in case of error
+ +
+
+
+ + + + Property changes on: contrib/libucl/doc/html/group__emitter.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: contrib/libucl/doc/html/group__parser.html =================================================================== --- contrib/libucl/doc/html/group__parser.html (revision 0) +++ contrib/libucl/doc/html/group__parser.html (working copy) @@ -0,0 +1,450 @@ + + + + + + +UCL: Parsing functions + + + + + + +
+
+ + + + + + +
+
UCL +
+
+
+ + +
+
+ +
+
Parsing functions
+
+
+ + + + +

+Typedefs

typedef bool(* ucl_macro_handler )(const unsigned char *data, size_t len, void *ud)
 
+ + + + + + + + + + + + + + + + + + + + + +

+Functions

struct ucl_parser * ucl_parser_new (int flags)
 
void ucl_parser_register_macro (struct ucl_parser *parser, const char *macro, ucl_macro_handler handler, void *ud)
 
void ucl_parser_register_variable (struct ucl_parser *parser, const char *var, const char *value)
 
bool ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, size_t len)
 
bool ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
 
ucl_object_tucl_parser_get_object (struct ucl_parser *parser)
 
const char * ucl_parser_get_error (struct ucl_parser *parser)
 
void ucl_parser_free (struct ucl_parser *parser)
 
bool ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len)
 
bool ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand)
 
+

Detailed Description

+

These functions are used to parse UCL objects

+

Typedef Documentation

+ +
+
+ + + + +
typedef bool(* ucl_macro_handler)(const unsigned char *data, size_t len, void *ud)
+
+

Macro handler for a parser

+
Parameters
+ + + + + +
datathe content of macro
lenthe length of content
udopaque user data
errerror pointer
+
+
+
Returns
true if macro has been parsed
+ +
+
+

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
bool ucl_parser_add_chunk (struct ucl_parser * parser,
const unsigned char * data,
size_t len 
)
+
+

Load new chunk to a parser

+
Parameters
+ + + + + +
parserparser structure
datathe pointer to the beginning of a chunk
lenthe length of a chunk
errif *err is NULL it is set to parser error
+
+
+
Returns
true if chunk has been added and false in case of error
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
bool ucl_parser_add_file (struct ucl_parser * parser,
const char * filename 
)
+
+

Load and add data from a file

+
Parameters
+ + + + +
parserparser structure
filenamethe name of file
errif *err is NULL it is set to parser error
+
+
+
Returns
true if chunk has been added and false in case of error
+ +
+
+ +
+
+ + + + + + + + +
void ucl_parser_free (struct ucl_parser * parser)
+
+

Free ucl parser object

+
Parameters
+ + +
parserparser object
+
+
+ +
+
+ +
+
+ + + + + + + + +
const char* ucl_parser_get_error (struct ucl_parser * parser)
+
+

Get the error string if failing

+
Parameters
+ + +
parserparser object
+
+
+ +
+
+ +
+
+ + + + + + + + +
ucl_object_t* ucl_parser_get_object (struct ucl_parser * parser)
+
+

Get a top object for a parser

+
Parameters
+ + + +
parserparser structure
errif *err is NULL it is set to parser error
+
+
+
Returns
top parser object or NULL
+ +
+
+ +
+
+ + + + + + + + +
struct ucl_parser* ucl_parser_new (int flags)
+
+

Creates new parser object

+
Parameters
+ + +
poolpool to allocate memory from
+
+
+
Returns
new parser object
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void ucl_parser_register_macro (struct ucl_parser * parser,
const char * macro,
ucl_macro_handler handler,
void * ud 
)
+
+

Register new handler for a macro

+
Parameters
+ + + + + +
parserparser object
macromacro name (without leading dot)
handlerhandler (it is called immediately after macro is parsed)
udopaque user data for a handler
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void ucl_parser_register_variable (struct ucl_parser * parser,
const char * var,
const char * value 
)
+
+

Register new parser variable

+
Parameters
+ + + + +
parserparser object
varvariable name
valuevariable value
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
bool ucl_parser_set_filevars (struct ucl_parser * parser,
const char * filename,
bool need_expand 
)
+
+

Set FILENAME and CURDIR variables in parser

+
Parameters
+ + + + +
parserparser object
filenamefilename to set or NULL to set FILENAME to "undef" and CURDIR to getcwd()
need_expandperform realpath() if this variable is true and filename is not NULL
+
+
+
Returns
true if variables has been set
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
bool ucl_pubkey_add (struct ucl_parser * parser,
const unsigned char * key,
size_t len 
)
+
+

Add new public key to parser for signatures check

+
Parameters
+ + + + + +
parserparser object
keyPEM representation of a key
lenlength of the key
errif *err is NULL it is set to parser error
+
+
+
Returns
true if a key has been successfully added
+ +
+
+
+ + + + Property changes on: contrib/libucl/doc/html/group__parser.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: contrib/libucl/doc/html/group__structures.html =================================================================== --- contrib/libucl/doc/html/group__structures.html (revision 0) +++ contrib/libucl/doc/html/group__structures.html (working copy) @@ -0,0 +1,416 @@ + + + + + + +UCL: Structures and types + + + + + + +
+
+ + + + + + +
+
UCL +
+
+
+ + +
+
+ +
+
Structures and types
+
+
+ + + + +

+Data Structures

struct  ucl_object_s
 
+ + + + + + + + + + + + + + + +

+Typedefs

typedef enum ucl_error ucl_error_t
 
typedef enum ucl_type ucl_type_t
 
typedef enum ucl_emitter ucl_emitter_t
 
typedef enum ucl_parser_flags ucl_parser_flags_t
 
typedef enum ucl_string_flags ucl_string_flags_t
 
typedef enum ucl_object_flags ucl_object_flags_t
 
typedef struct ucl_object_s ucl_object_t
 
+ + + + + + + + + + + + + +

+Enumerations

enum  ucl_error {
+  UCL_EOK = 0, +UCL_ESYNTAX, +UCL_EIO, +UCL_ESTATE, +
+  UCL_ENESTED, +UCL_EMACRO, +UCL_EINTERNAL, +UCL_ESSL +
+ }
 
enum  ucl_type {
+  UCL_OBJECT = 0, +UCL_ARRAY, +UCL_INT, +UCL_FLOAT, +
+  UCL_STRING, +UCL_BOOLEAN, +UCL_TIME, +UCL_USERDATA, +
+  UCL_NULL +
+ }
 
enum  ucl_emitter { UCL_EMIT_JSON = 0, +UCL_EMIT_JSON_COMPACT, +UCL_EMIT_CONFIG, +UCL_EMIT_YAML + }
 
enum  ucl_parser_flags { UCL_PARSER_KEY_LOWERCASE = 0x1, +UCL_PARSER_ZEROCOPY = 0x2 + }
 
enum  ucl_string_flags {
+  UCL_STRING_ESCAPE = 0x1, +UCL_STRING_TRIM = 0x2, +UCL_STRING_PARSE_BOOLEAN = 0x4, +UCL_STRING_PARSE_INT = 0x8, +
+  UCL_STRING_PARSE_DOUBLE = 0x10, +UCL_STRING_PARSE_NUMBER = UCL_STRING_PARSE_INT|UCL_STRING_PARSE_DOUBLE, +UCL_STRING_PARSE = UCL_STRING_PARSE_BOOLEAN|UCL_STRING_PARSE_NUMBER, +UCL_STRING_PARSE_BYTES = 0x20 +
+ }
 
enum  ucl_object_flags { UCL_OBJECT_ALLOCATED_KEY = 1, +UCL_OBJECT_ALLOCATED_VALUE = 2, +UCL_OBJECT_NEED_KEY_ESCAPE = 4 + }
 
+

Detailed Description

+

UCL defines several enumeration types used for error reporting or specifying flags and attributes.

+

Typedef Documentation

+ +
+
+ + + + +
typedef enum ucl_emitter ucl_emitter_t
+
+

You can use one of these types to serialise ucl_object_t by using ucl_object_emit().

+ +
+
+ +
+
+ + + + +
typedef enum ucl_error ucl_error_t
+
+

The common error codes returned by ucl parser

+ +
+
+ +
+
+ + + + +
typedef enum ucl_object_flags ucl_object_flags_t
+
+

Basic flags for an object

+ +
+
+ +
+
+ + + + +
typedef struct ucl_object_s ucl_object_t
+
+

UCL object structure. Please mention that the most of fields should not be touched by UCL users. In future, this structure may be converted to private one.

+ +
+
+ +
+
+ + + + +
typedef enum ucl_parser_flags ucl_parser_flags_t
+
+

These flags defines parser behaviour. If you specify UCL_PARSER_ZEROCOPY you must ensure that the input memory is not freed if an object is in use. Moreover, if you want to use zero-terminated keys and string values then you should not use zero-copy mode, as in this case UCL still has to perform copying implicitly.

+ +
+
+ +
+
+ + + + +
typedef enum ucl_string_flags ucl_string_flags_t
+
+

String conversion flags, that are used in ucl_object_fromstring_common function.

+ +
+
+ +
+
+ + + + +
typedef enum ucl_type ucl_type_t
+
+

ucl_object_t may have one of specified types, some types are compatible with each other and some are not. For example, you can always convert UCL_TIME to UCL_FLOAT. Also you can convert UCL_FLOAT to #UCL_INTEGER by loosing floating point. Every object may be converted to a string by ucl_object_tostring_forced() function.

+ +
+
+

Enumeration Type Documentation

+ +
+
+ + + + +
enum ucl_emitter
+
+

You can use one of these types to serialise ucl_object_t by using ucl_object_emit().

+ + + + + +
Enumerator
UCL_EMIT_JSON  +

Emit fine formatted JSON

+
UCL_EMIT_JSON_COMPACT  +

Emit compacted JSON

+
UCL_EMIT_CONFIG  +

Emit human readable config format

+
UCL_EMIT_YAML  +

Emit embedded YAML format

+
+ +
+
+ +
+
+ + + + +
enum ucl_error
+
+

The common error codes returned by ucl parser

+ + + + + + + + + +
Enumerator
UCL_EOK  +

No error

+
UCL_ESYNTAX  +

Syntax error occurred during parsing

+
UCL_EIO  +

IO error occurred during parsing

+
UCL_ESTATE  +

Invalid state machine state

+
UCL_ENESTED  +

Input has too many recursion levels

+
UCL_EMACRO  +

Error processing a macro

+
UCL_EINTERNAL  +

Internal unclassified error

+
UCL_ESSL  +

SSL error

+
+ +
+
+ +
+
+ + + + +
enum ucl_object_flags
+
+

Basic flags for an object

+ + + + +
Enumerator
UCL_OBJECT_ALLOCATED_KEY  +

An object has key allocated internally

+
UCL_OBJECT_ALLOCATED_VALUE  +

An object has a string value allocated internally

+
UCL_OBJECT_NEED_KEY_ESCAPE  +

The key of an object need to be escaped on output

+
+ +
+
+ +
+
+ + + + +
enum ucl_parser_flags
+
+

These flags defines parser behaviour. If you specify UCL_PARSER_ZEROCOPY you must ensure that the input memory is not freed if an object is in use. Moreover, if you want to use zero-terminated keys and string values then you should not use zero-copy mode, as in this case UCL still has to perform copying implicitly.

+ + + +
Enumerator
UCL_PARSER_KEY_LOWERCASE  +

Convert all keys to lower case

+
UCL_PARSER_ZEROCOPY  +

Parse input in zero-copy mode if possible

+
+ +
+
+ +
+
+ + + + +
enum ucl_string_flags
+
+

String conversion flags, that are used in ucl_object_fromstring_common function.

+ + + + + + + + + +
Enumerator
UCL_STRING_ESCAPE  +

Perform JSON escape

+
UCL_STRING_TRIM  +

Trim leading and trailing whitespaces

+
UCL_STRING_PARSE_BOOLEAN  +

Parse passed string and detect boolean

+
UCL_STRING_PARSE_INT  +

Parse passed string and detect integer number

+
UCL_STRING_PARSE_DOUBLE  +

Parse passed string and detect integer or float number

+
UCL_STRING_PARSE_NUMBER  +

Parse passed string and detect number

+
UCL_STRING_PARSE  +

Parse passed string (and detect booleans and numbers)

+
UCL_STRING_PARSE_BYTES  +

Treat numbers as bytes

+
+ +
+
+ +
+
+ + + + +
enum ucl_type
+
+

ucl_object_t may have one of specified types, some types are compatible with each other and some are not. For example, you can always convert UCL_TIME to UCL_FLOAT. Also you can convert UCL_FLOAT to #UCL_INTEGER by loosing floating point. Every object may be converted to a string by ucl_object_tostring_forced() function.

+ + + + + + + + + + +
Enumerator
UCL_OBJECT  +

UCL object - key/value pairs

+
UCL_ARRAY  +

UCL array

+
UCL_INT  +

Integer number

+
UCL_FLOAT  +

Floating point number

+
UCL_STRING  +

Null terminated string

+
UCL_BOOLEAN  +

Boolean value

+
UCL_TIME  +

Time value (floating point number of seconds)

+
UCL_USERDATA  +

Opaque userdata pointer (may be used in macros)

+
UCL_NULL  +

Null value

+
+ +
+
+
+ + + + Property changes on: contrib/libucl/doc/html/group__structures.html ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/doc/html/group__utils.html =================================================================== --- contrib/libucl/doc/html/group__utils.html (revision 0) +++ contrib/libucl/doc/html/group__utils.html (working copy) @@ -0,0 +1,433 @@ + + + + + + +UCL: Utility functions + + + + + + +
+
+ + + + + + +
+
UCL +
+
+
+ + +
+
+ +
+
Utility functions
+
+
+ + + + +

+Typedefs

typedef void * ucl_object_iter_t
 
+ + + + + + + + + + + + + + + + + + + +

+Functions

char * ucl_copy_key_trash (ucl_object_t *obj)
 
char * ucl_copy_value_trash (ucl_object_t *obj)
 
ucl_object_tucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags flags) UCL_WARN_UNUSED_RESULT
 
ucl_object_tucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT
 
ucl_object_tucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt, const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT
 
ucl_object_tucl_object_find_key (ucl_object_t *obj, const char *key)
 
ucl_object_tucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen)
 
void ucl_object_free (ucl_object_t *obj)
 
ucl_object_tucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values)
 
+

Detailed Description

+

A number of utility functions simplify handling of UCL objects

+

Typedef Documentation

+ +
+
+ + + + +
typedef void* ucl_object_iter_t
+
+

Opaque iterator object

+ +
+
+

Function Documentation

+ +
+
+ + + + + + + + +
char* ucl_copy_key_trash (ucl_object_tobj)
+
+

Copy and return a key of an object, returned key is zero-terminated

+
Parameters
+ + +
objCL object
+
+
+
Returns
zero terminated key
+ +
+
+ +
+
+ + + + + + + + +
char* ucl_copy_value_trash (ucl_object_tobj)
+
+

Copy and return a string value of an object, returned key is zero-terminated

+
Parameters
+ + +
objCL object
+
+
+
Returns
zero terminated string representation of object value
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
ucl_object_t* ucl_iterate_object (ucl_object_tobj,
ucl_object_iter_titer,
bool expand_values 
)
+
+

Get next key from an object

+
Parameters
+ + + +
objobject to iterate
iteropaque iterator, must be set to NULL on the first call: ucl_object_iter_t it = NULL; while ((cur = ucl_iterate_object (obj, &it)) != NULL) ...
+
+
+
Returns
the next object or NULL
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
ucl_object_t* ucl_object_find_key (ucl_object_tobj,
const char * key 
)
+
+

Return object identified by a key in the specified object

+
Parameters
+ + + +
objobject to get a key from (must be of type UCL_OBJECT)
keykey to search
+
+
+
Returns
object matched the specified key or NULL if key is not found
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
ucl_object_t* ucl_object_find_keyl (ucl_object_tobj,
const char * key,
size_t klen 
)
+
+

Return object identified by a fixed size key in the specified object

+
Parameters
+ + + + +
objobject to get a key from (must be of type UCL_OBJECT)
keykey to search
klenlength of a key
+
+
+
Returns
object matched the specified key or NULL if key is not found
+ +
+
+ +
+
+ + + + + + + + +
void ucl_object_free (ucl_object_tobj)
+
+

Free ucl object

+
Parameters
+ + +
objucl object to free
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
ucl_object_t* ucl_object_fromstring_common (const char * str,
size_t len,
enum ucl_string_flags flags 
)
+
+

Convert any string to an ucl object making the specified transformations

+
Parameters
+ + + + +
strfixed size or NULL terminated string
lenlength (if len is zero, than str is treated as NULL terminated)
flagsconversion flags
+
+
+
Returns
new object
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ucl_object_t* ucl_object_insert_key (ucl_object_ttop,
ucl_object_telt,
const char * key,
size_t keylen,
bool copy_key 
)
+
+

Insert a object 'elt' to the hash 'top' and associate it with key 'key'

+
Parameters
+ + + + + + +
topdestination object (will be created automatically if top is NULL)
eltelement to insert (must NOT be NULL)
keykey to associate with this object (either const or preallocated)
keylenlength of the key (or 0 for NULL terminated keys)
copy_keymake an internal copy of key
+
+
+
Returns
new value of top object
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ucl_object_t* ucl_object_insert_key_merged (ucl_object_ttop,
ucl_object_telt,
const char * key,
size_t keylen,
bool copy_key 
)
+
+

Insert a object 'elt' to the hash 'top' and associate it with key 'key', if the specified key exist, try to merge its content

+
Parameters
+ + + + + + +
topdestination object (will be created automatically if top is NULL)
eltelement to insert (must NOT be NULL)
keykey to associate with this object (either const or preallocated)
keylenlength of the key (or 0 for NULL terminated keys)
copy_keymake an internal copy of key
+
+
+
Returns
new value of top object
+ +
+
+
+ + + + Property changes on: contrib/libucl/doc/html/group__utils.html ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/doc/html/index.html =================================================================== --- contrib/libucl/doc/html/index.html (revision 0) +++ contrib/libucl/doc/html/index.html (working copy) @@ -0,0 +1,51 @@ + + + + + + +UCL: Main Page + + + + + + +
+
+ + + + + + +
+
UCL +
+
+
+ + +
+
+
+
UCL Documentation
+
+
+

This is a reference manual for UCL API. You may find the description of UCL format by following this github repository.

+

This manual has several main sections:

+ +
+ + + + Property changes on: contrib/libucl/doc/html/index.html ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/doc/html/modules.html =================================================================== --- contrib/libucl/doc/html/modules.html (revision 0) +++ contrib/libucl/doc/html/modules.html (working copy) @@ -0,0 +1,51 @@ + + + + + + +UCL: Modules + + + + + + +
+
+ + + + + + +
+
UCL +
+
+
+ + +
+
+
+
Modules
+
+
+
Here is a list of all modules:
+
+ + + + Property changes on: contrib/libucl/doc/html/modules.html ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/doc/html/nav_f.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/nav_f.png =================================================================== --- contrib/libucl/doc/html/nav_f.png (revision 0) +++ contrib/libucl/doc/html/nav_f.png (working copy) Property changes on: contrib/libucl/doc/html/nav_f.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/nav_g.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/nav_g.png =================================================================== --- contrib/libucl/doc/html/nav_g.png (revision 0) +++ contrib/libucl/doc/html/nav_g.png (working copy) Property changes on: contrib/libucl/doc/html/nav_g.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/nav_h.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/nav_h.png =================================================================== --- contrib/libucl/doc/html/nav_h.png (revision 0) +++ contrib/libucl/doc/html/nav_h.png (working copy) Property changes on: contrib/libucl/doc/html/nav_h.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/open.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/open.png =================================================================== --- contrib/libucl/doc/html/open.png (revision 0) +++ contrib/libucl/doc/html/open.png (working copy) Property changes on: contrib/libucl/doc/html/open.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/structucl__object__s.html =================================================================== --- contrib/libucl/doc/html/structucl__object__s.html (revision 0) +++ contrib/libucl/doc/html/structucl__object__s.html (working copy) @@ -0,0 +1,298 @@ + + + + + + +UCL: ucl_object_s Struct Reference + + + + + + +
+
+ + + + + + +
+
UCL +
+
+
+ + +
+
+ +
+
ucl_object_s Struct Reference
+
+
+ +

#include <ucl.h>

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Data Fields

union {
   int64_t   iv
 
   const char *   sv
 
   double   dv
 
   struct ucl_object_s *   av
 
   void *   ov
 
   void *   ud
 
value
 
const char * key
 
struct ucl_object_snext
 
struct ucl_object_sprev
 
unsigned char * trash_stack [2]
 
unsigned keylen
 
unsigned len
 
enum ucl_type type
 
uint16_t ref
 
uint16_t flags
 
+

Detailed Description

+

UCL object structure. Please mention that the most of fields should not be touched by UCL users. In future, this structure may be converted to private one.

+

Field Documentation

+ +
+
+ + + + +
struct ucl_object_s* av
+
+

Array

+ +
+
+ +
+
+ + + + +
double dv
+
+

Double value of an object

+ +
+
+ +
+
+ + + + +
uint16_t flags
+
+

Object flags

+ +
+
+ +
+
+ + + + +
int64_t iv
+
+

Int value of an object

+ +
+
+ +
+
+ + + + +
const char* key
+
+

Key of an object

+ +
+
+ +
+
+ + + + +
unsigned keylen
+
+

Lenght of a key

+ +
+
+ +
+
+ + + + +
unsigned len
+
+

Size of an object

+ +
+
+ +
+
+ + + + +
struct ucl_object_s* next
+
+

Array handle

+ +
+
+ +
+
+ + + + +
void* ov
+
+

Object

+ +
+
+ +
+
+ + + + +
struct ucl_object_s* prev
+
+

Array handle

+ +
+
+ +
+
+ + + + +
uint16_t ref
+
+

Reference count

+ +
+
+ +
+
+ + + + +
const char* sv
+
+

String value of an object

+ +
+
+ +
+
+ + + + +
unsigned char* trash_stack[2]
+
+

Pointer to allocated chunks

+ +
+
+ +
+
+ + + + +
enum ucl_type type
+
+

Real type

+ +
+
+ +
+
+ + + + +
void* ud
+
+

Opaque user data

+ +
+
+ +
+
+ + + + +
union { ... } value
+
+

Variant value type

+ +
+
+
The documentation for this struct was generated from the following file: +
+ + + + Property changes on: contrib/libucl/doc/html/structucl__object__s.html ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/doc/html/sync_off.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/sync_off.png =================================================================== --- contrib/libucl/doc/html/sync_off.png (revision 0) +++ contrib/libucl/doc/html/sync_off.png (working copy) Property changes on: contrib/libucl/doc/html/sync_off.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/sync_on.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/sync_on.png =================================================================== --- contrib/libucl/doc/html/sync_on.png (revision 0) +++ contrib/libucl/doc/html/sync_on.png (working copy) Property changes on: contrib/libucl/doc/html/sync_on.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/tab_a.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/tab_a.png =================================================================== --- contrib/libucl/doc/html/tab_a.png (revision 0) +++ contrib/libucl/doc/html/tab_a.png (working copy) Property changes on: contrib/libucl/doc/html/tab_a.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/tab_b.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/tab_b.png =================================================================== --- contrib/libucl/doc/html/tab_b.png (revision 0) +++ contrib/libucl/doc/html/tab_b.png (working copy) Property changes on: contrib/libucl/doc/html/tab_b.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/tab_h.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/tab_h.png =================================================================== --- contrib/libucl/doc/html/tab_h.png (revision 0) +++ contrib/libucl/doc/html/tab_h.png (working copy) Property changes on: contrib/libucl/doc/html/tab_h.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/tab_s.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: contrib/libucl/doc/html/tab_s.png =================================================================== --- contrib/libucl/doc/html/tab_s.png (revision 0) +++ contrib/libucl/doc/html/tab_s.png (working copy) Property changes on: contrib/libucl/doc/html/tab_s.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: contrib/libucl/doc/html/tabs.css =================================================================== --- contrib/libucl/doc/html/tabs.css (revision 0) +++ contrib/libucl/doc/html/tabs.css (working copy) @@ -0,0 +1,60 @@ +.tabs, .tabs2, .tabs3 { + background-image: url('tab_b.png'); + width: 100%; + z-index: 101; + font-size: 13px; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; +} + +.tabs2 { + font-size: 10px; +} +.tabs3 { + font-size: 9px; +} + +.tablist { + margin: 0; + padding: 0; + display: table; +} + +.tablist li { + float: left; + display: table-cell; + background-image: url('tab_b.png'); + line-height: 36px; + list-style: none; +} + +.tablist a { + display: block; + padding: 0 20px; + font-weight: bold; + background-image:url('tab_s.png'); + background-repeat:no-repeat; + background-position:right; + color: #283A5D; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; + outline: none; +} + +.tabs3 .tablist a { + padding: 0 10px; +} + +.tablist a:hover { + background-image: url('tab_h.png'); + background-repeat:repeat-x; + color: #fff; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); + text-decoration: none; +} + +.tablist li.current a { + background-image: url('tab_a.png'); + background-repeat:repeat-x; + color: #fff; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); +} Property changes on: contrib/libucl/doc/html/tabs.css ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/css \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: contrib/libucl/doc/html/ucl_8h.html =================================================================== --- contrib/libucl/doc/html/ucl_8h.html (revision 0) +++ contrib/libucl/doc/html/ucl_8h.html (working copy) @@ -0,0 +1,254 @@ + + + + + + +UCL: include/ucl.h File Reference + + + + + + +
+
+ + + + + + +
+
UCL +
+
+
+ + + +
+
+ +
+
ucl.h File Reference
+
+
+ +

UCL parsing and emitting functions. +More...

+
#include <string.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+

Go to the source code of this file.

+ + + + +

+Data Structures

struct  ucl_object_s
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Macros

+#define UCL_ALLOC(size)   malloc(size)
 
+#define UCL_FREE(size, ptr)   free(ptr)
 
+#define UCL_WARN_UNUSED_RESULT
 
+#define ucl_obj_todouble_safe   ucl_object_todouble_safe
 
+#define ucl_obj_todouble   ucl_object_todouble
 
+#define ucl_obj_tostring   ucl_object_tostring
 
+#define ucl_obj_tostring_safe   ucl_object_tostring_safe
 
+#define ucl_obj_tolstring   ucl_object_tolstring
 
+#define ucl_obj_tolstring_safe   ucl_object_tolstring_safe
 
+#define ucl_obj_toint   ucl_object_toint
 
+#define ucl_obj_toint_safe   ucl_object_toint_safe
 
+#define ucl_obj_toboolean   ucl_object_toboolean
 
+#define ucl_obj_toboolean_safe   ucl_object_toboolean_safe
 
+#define ucl_obj_get_key   ucl_object_find_key
 
+#define ucl_obj_get_keyl   ucl_object_find_keyl
 
+#define ucl_obj_unref   ucl_object_unref
 
+#define ucl_obj_ref   ucl_object_ref
 
+#define ucl_obj_free   ucl_object_free
 
+ + + + + + + + + + + + + + + + + + + +

+Typedefs

typedef enum ucl_error ucl_error_t
 
typedef enum ucl_type ucl_type_t
 
typedef enum ucl_emitter ucl_emitter_t
 
typedef enum ucl_parser_flags ucl_parser_flags_t
 
typedef enum ucl_string_flags ucl_string_flags_t
 
typedef enum ucl_object_flags ucl_object_flags_t
 
typedef struct ucl_object_s ucl_object_t
 
typedef void * ucl_object_iter_t
 
typedef bool(* ucl_macro_handler )(const unsigned char *data, size_t len, void *ud)
 
+ + + + + + + + + + + + + +

+Enumerations

enum  ucl_error {
+  UCL_EOK = 0, +UCL_ESYNTAX, +UCL_EIO, +UCL_ESTATE, +
+  UCL_ENESTED, +UCL_EMACRO, +UCL_EINTERNAL, +UCL_ESSL +
+ }
 
enum  ucl_type {
+  UCL_OBJECT = 0, +UCL_ARRAY, +UCL_INT, +UCL_FLOAT, +
+  UCL_STRING, +UCL_BOOLEAN, +UCL_TIME, +UCL_USERDATA, +
+  UCL_NULL +
+ }
 
enum  ucl_emitter { UCL_EMIT_JSON = 0, +UCL_EMIT_JSON_COMPACT, +UCL_EMIT_CONFIG, +UCL_EMIT_YAML + }
 
enum  ucl_parser_flags { UCL_PARSER_KEY_LOWERCASE = 0x1, +UCL_PARSER_ZEROCOPY = 0x2 + }
 
enum  ucl_string_flags {
+  UCL_STRING_ESCAPE = 0x1, +UCL_STRING_TRIM = 0x2, +UCL_STRING_PARSE_BOOLEAN = 0x4, +UCL_STRING_PARSE_INT = 0x8, +
+  UCL_STRING_PARSE_DOUBLE = 0x10, +UCL_STRING_PARSE_NUMBER = UCL_STRING_PARSE_INT|UCL_STRING_PARSE_DOUBLE, +UCL_STRING_PARSE = UCL_STRING_PARSE_BOOLEAN|UCL_STRING_PARSE_NUMBER, +UCL_STRING_PARSE_BYTES = 0x20 +
+ }
 
enum  ucl_object_flags { UCL_OBJECT_ALLOCATED_KEY = 1, +UCL_OBJECT_ALLOCATED_VALUE = 2, +UCL_OBJECT_NEED_KEY_ESCAPE = 4 + }
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

char * ucl_copy_key_trash (ucl_object_t *obj)
 
char * ucl_copy_value_trash (ucl_object_t *obj)
 
ucl_object_tucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags flags) UCL_WARN_UNUSED_RESULT
 
ucl_object_tucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT
 
ucl_object_tucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt, const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT
 
ucl_object_tucl_object_find_key (ucl_object_t *obj, const char *key)
 
ucl_object_tucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen)
 
void ucl_object_free (ucl_object_t *obj)
 
ucl_object_tucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values)
 
struct ucl_parser * ucl_parser_new (int flags)
 
void ucl_parser_register_macro (struct ucl_parser *parser, const char *macro, ucl_macro_handler handler, void *ud)
 
void ucl_parser_register_variable (struct ucl_parser *parser, const char *var, const char *value)
 
bool ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, size_t len)
 
bool ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
 
ucl_object_tucl_parser_get_object (struct ucl_parser *parser)
 
const char * ucl_parser_get_error (struct ucl_parser *parser)
 
void ucl_parser_free (struct ucl_parser *parser)
 
bool ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len)
 
bool ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand)
 
unsigned char * ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type)
 
+

Detailed Description

+

UCL parsing and emitting functions.

+

UCL is universal configuration language, which is a form of JSON with less strict rules that make it more comfortable for using as a configuration language

+
+ + + + Property changes on: contrib/libucl/doc/html/ucl_8h.html ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/doc/html/ucl_8h_source.html =================================================================== --- contrib/libucl/doc/html/ucl_8h_source.html (revision 0) +++ contrib/libucl/doc/html/ucl_8h_source.html (working copy) @@ -0,0 +1,554 @@ + + + + + + +UCL: include/ucl.h Source File + + + + + + +
+
+ + + + + + +
+
UCL +
+
+
+ + + +
+
+
+
ucl.h
+
+
+Go to the documentation of this file.
1 /* Copyright (c) 2013, Vsevolod Stakhov
+
2  * All rights reserved.
+
3  *
+
4  * Redistribution and use in source and binary forms, with or without
+
5  * modification, are permitted provided that the following conditions are met:
+
6  * * Redistributions of source code must retain the above copyright
+
7  * notice, this list of conditions and the following disclaimer.
+
8  * * Redistributions in binary form must reproduce the above copyright
+
9  * notice, this list of conditions and the following disclaimer in the
+
10  * documentation and/or other materials provided with the distribution.
+
11  *
+
12  * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
+
13  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+
14  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+
15  * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
+
16  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+
17  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+
18  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+
19  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+
20  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+
21  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
22  */
+
23 
+
24 #ifndef UCL_H_
+
25 #define UCL_H_
+
26 
+
27 #include <string.h>
+
28 #include <stddef.h>
+
29 #include <stdlib.h>
+
30 #include <stdint.h>
+
31 #include <stdbool.h>
+
32 #include <stdarg.h>
+
33 #include <stdio.h>
+
34 
+
55 #ifdef __cplusplus
+
56 extern "C" {
+
57 #endif
+
58 /*
+
59  * Memory allocation utilities
+
60  * UCL_ALLOC(size) - allocate memory for UCL
+
61  * UCL_FREE(size, ptr) - free memory of specified size at ptr
+
62  * Default: malloc and free
+
63  */
+
64 #ifndef UCL_ALLOC
+
65 #define UCL_ALLOC(size) malloc(size)
+
66 #endif
+
67 #ifndef UCL_FREE
+
68 #define UCL_FREE(size, ptr) free(ptr)
+
69 #endif
+
70 
+
71 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+
72 #define UCL_WARN_UNUSED_RESULT \
+
73  __attribute__((warn_unused_result))
+
74 #else
+
75 #define UCL_WARN_UNUSED_RESULT
+
76 #endif
+
77 
+
88 typedef enum ucl_error {
+
89  UCL_EOK = 0,
+ + + + + + + +
97 } ucl_error_t;
+
98 
+
105 typedef enum ucl_type {
+ + + + + + + + + +
115 } ucl_type_t;
+
116 
+
120 typedef enum ucl_emitter {
+ + + + +
125 } ucl_emitter_t;
+
126 
+
133 typedef enum ucl_parser_flags {
+ + + +
137 
+
141 typedef enum ucl_string_flags {
+ + + + + + + + + +
153 
+
157 typedef enum ucl_object_flags {
+ + + + +
162 
+
167 typedef struct ucl_object_s {
+
171  union {
+
172  int64_t iv;
+
173  const char *sv;
+
174  double dv;
+
175  struct ucl_object_s *av;
+
176  void *ov;
+
177  void* ud;
+
178  } value;
+
179  const char *key;
+
180  struct ucl_object_s *next;
+
181  struct ucl_object_s *prev;
+
182  unsigned char* trash_stack[2];
+
183  unsigned keylen;
+
184  unsigned len;
+
185  enum ucl_type type;
+
186  uint16_t ref;
+
187  uint16_t flags;
+
188 } ucl_object_t;
+
189 
+
203 char* ucl_copy_key_trash (ucl_object_t *obj);
+
204 
+ +
211 
+
216 static inline ucl_object_t* ucl_object_new (void) UCL_WARN_UNUSED_RESULT;
+
217 static inline ucl_object_t *
+
218 ucl_object_new (void)
+
219 {
+
220  ucl_object_t *new;
+
221  new = malloc (sizeof (ucl_object_t));
+
222  if (new != NULL) {
+
223  memset (new, 0, sizeof (ucl_object_t));
+
224  new->ref = 1;
+
225  new->type = UCL_NULL;
+
226  }
+
227  return new;
+
228 }
+
229 
+
235 static inline ucl_object_t* ucl_object_typed_new (unsigned int type) UCL_WARN_UNUSED_RESULT;
+
236 static inline ucl_object_t *
+
237 ucl_object_typed_new (unsigned int type)
+
238 {
+
239  ucl_object_t *new;
+
240  new = malloc (sizeof (ucl_object_t));
+
241  if (new != NULL) {
+
242  memset (new, 0, sizeof (ucl_object_t));
+
243  new->ref = 1;
+
244  new->type = (type <= UCL_NULL ? type : UCL_NULL);
+
245  }
+
246  return new;
+
247 }
+
248 
+
256 ucl_object_t * ucl_object_fromstring_common (const char *str, size_t len,
+
257  enum ucl_string_flags flags) UCL_WARN_UNUSED_RESULT;
+
258 
+
264 static inline ucl_object_t *
+
265 ucl_object_fromstring (const char *str)
+
266 {
+ +
268 }
+
269 
+
276 static inline ucl_object_t *
+
277 ucl_object_fromlstring (const char *str, size_t len)
+
278 {
+ +
280 }
+
281 
+
287 static inline ucl_object_t *
+
288 ucl_object_fromint (int64_t iv)
+
289 {
+
290  ucl_object_t *obj;
+
291 
+
292  obj = ucl_object_new ();
+
293  if (obj != NULL) {
+
294  obj->type = UCL_INT;
+
295  obj->value.iv = iv;
+
296  }
+
297 
+
298  return obj;
+
299 }
+
300 
+
306 static inline ucl_object_t *
+
307 ucl_object_fromdouble (double dv)
+
308 {
+
309  ucl_object_t *obj;
+
310 
+
311  obj = ucl_object_new ();
+
312  if (obj != NULL) {
+
313  obj->type = UCL_FLOAT;
+
314  obj->value.dv = dv;
+
315  }
+
316 
+
317  return obj;
+
318 }
+
319 
+
325 static inline ucl_object_t *
+
326 ucl_object_frombool (bool bv)
+
327 {
+
328  ucl_object_t *obj;
+
329 
+
330  obj = ucl_object_new ();
+
331  if (obj != NULL) {
+
332  obj->type = UCL_BOOLEAN;
+
333  obj->value.iv = bv;
+
334  }
+
335 
+
336  return obj;
+
337 }
+
338 
+ +
349  const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT;
+
350 
+ +
362  const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT;
+
363 
+
370 static inline ucl_object_t * ucl_array_append (ucl_object_t *top,
+
371  ucl_object_t *elt) UCL_WARN_UNUSED_RESULT;
+
372 static inline ucl_object_t *
+
373 ucl_array_append (ucl_object_t *top, ucl_object_t *elt)
+
374 {
+
375  ucl_object_t *head;
+
376 
+
377  if (elt == NULL) {
+
378  return NULL;
+
379  }
+
380 
+
381  if (top == NULL) {
+
382  top = ucl_object_new ();
+
383  top->type = UCL_ARRAY;
+
384  top->value.av = elt;
+
385  elt->next = NULL;
+
386  elt->prev = elt;
+
387  }
+
388  else {
+
389  head = top->value.av;
+
390  elt->prev = head->prev;
+
391  head->prev->next = elt;
+
392  head->prev = elt;
+
393  elt->next = NULL;
+
394  }
+
395 
+
396  return top;
+
397 }
+
398 
+
405 static inline ucl_object_t * ucl_elt_append (ucl_object_t *head,
+
406  ucl_object_t *elt) UCL_WARN_UNUSED_RESULT;
+
407 static inline ucl_object_t *
+
408 ucl_elt_append (ucl_object_t *head, ucl_object_t *elt)
+
409 {
+
410 
+
411  if (head == NULL) {
+
412  elt->next = NULL;
+
413  elt->prev = elt;
+
414  head = elt;
+
415  }
+
416  else {
+
417  elt->prev = head->prev;
+
418  head->prev->next = elt;
+
419  head->prev = elt;
+
420  elt->next = NULL;
+
421  }
+
422 
+
423  return head;
+
424 }
+
425 
+
432 static inline bool
+
433 ucl_object_todouble_safe (ucl_object_t *obj, double *target)
+
434 {
+
435  if (obj == NULL) {
+
436  return false;
+
437  }
+
438  switch (obj->type) {
+
439  case UCL_INT:
+
440  *target = obj->value.iv; /* Probaly could cause overflow */
+
441  break;
+
442  case UCL_FLOAT:
+
443  case UCL_TIME:
+
444  *target = obj->value.dv;
+
445  break;
+
446  default:
+
447  return false;
+
448  }
+
449 
+
450  return true;
+
451 }
+
452 
+
458 static inline double
+
459 ucl_object_todouble (ucl_object_t *obj)
+
460 {
+
461  double result = 0.;
+
462 
+
463  ucl_object_todouble_safe (obj, &result);
+
464  return result;
+
465 }
+
466 
+
473 static inline bool
+
474 ucl_object_toint_safe (ucl_object_t *obj, int64_t *target)
+
475 {
+
476  if (obj == NULL) {
+
477  return false;
+
478  }
+
479  switch (obj->type) {
+
480  case UCL_INT:
+
481  *target = obj->value.iv;
+
482  break;
+
483  case UCL_FLOAT:
+
484  case UCL_TIME:
+
485  *target = obj->value.dv; /* Loosing of decimal points */
+
486  break;
+
487  default:
+
488  return false;
+
489  }
+
490 
+
491  return true;
+
492 }
+
493 
+
499 static inline int64_t
+
500 ucl_object_toint (ucl_object_t *obj)
+
501 {
+
502  int64_t result = 0;
+
503 
+
504  ucl_object_toint_safe (obj, &result);
+
505  return result;
+
506 }
+
507 
+
514 static inline bool
+
515 ucl_object_toboolean_safe (ucl_object_t *obj, bool *target)
+
516 {
+
517  if (obj == NULL) {
+
518  return false;
+
519  }
+
520  switch (obj->type) {
+
521  case UCL_BOOLEAN:
+
522  *target = (obj->value.iv == true);
+
523  break;
+
524  default:
+
525  return false;
+
526  }
+
527 
+
528  return true;
+
529 }
+
530 
+
536 static inline bool
+
537 ucl_object_toboolean (ucl_object_t *obj)
+
538 {
+
539  bool result = false;
+
540 
+
541  ucl_object_toboolean_safe (obj, &result);
+
542  return result;
+
543 }
+
544 
+
551 static inline bool
+
552 ucl_object_tostring_safe (ucl_object_t *obj, const char **target)
+
553 {
+
554  if (obj == NULL) {
+
555  return false;
+
556  }
+
557 
+
558  switch (obj->type) {
+
559  case UCL_STRING:
+
560  *target = ucl_copy_value_trash (obj);
+
561  break;
+
562  default:
+
563  return false;
+
564  }
+
565 
+
566  return true;
+
567 }
+
568 
+
574 static inline const char *
+
575 ucl_object_tostring (ucl_object_t *obj)
+
576 {
+
577  const char *result = NULL;
+
578 
+
579  ucl_object_tostring_safe (obj, &result);
+
580  return result;
+
581 }
+
582 
+
588 static inline const char *
+
589 ucl_object_tostring_forced (ucl_object_t *obj)
+
590 {
+
591  return ucl_copy_value_trash (obj);
+
592 }
+
593 
+
602 static inline bool
+
603 ucl_object_tolstring_safe (ucl_object_t *obj, const char **target, size_t *tlen)
+
604 {
+
605  if (obj == NULL) {
+
606  return false;
+
607  }
+
608  switch (obj->type) {
+
609  case UCL_STRING:
+
610  *target = obj->value.sv;
+
611  *tlen = obj->len;
+
612  break;
+
613  default:
+
614  return false;
+
615  }
+
616 
+
617  return true;
+
618 }
+
619 
+
625 static inline const char *
+
626 ucl_object_tolstring (ucl_object_t *obj, size_t *tlen)
+
627 {
+
628  const char *result = NULL;
+
629 
+
630  ucl_object_tolstring_safe (obj, &result, tlen);
+
631  return result;
+
632 }
+
633 
+
640 ucl_object_t * ucl_object_find_key (ucl_object_t *obj, const char *key);
+
641 
+
649 ucl_object_t *ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen);
+
650 
+
656 static inline const char *
+
657 ucl_object_key (ucl_object_t *obj)
+
658 {
+
659  return ucl_copy_key_trash (obj);
+
660 }
+
661 
+
668 static inline const char *
+
669 ucl_object_keyl (ucl_object_t *obj, size_t *len)
+
670 {
+
671  *len = obj->keylen;
+
672  return obj->key;
+
673 }
+
674 
+
679 void ucl_object_free (ucl_object_t *obj);
+
680 
+
685 static inline ucl_object_t *
+
686 ucl_object_ref (ucl_object_t *obj) {
+
687  obj->ref ++;
+
688  return obj;
+
689 }
+
690 
+
695 static inline void
+
696 ucl_object_unref (ucl_object_t *obj) {
+
697  if (--obj->ref <= 0) {
+
698  ucl_object_free (obj);
+
699  }
+
700 }
+
704 typedef void* ucl_object_iter_t;
+
705 
+
714 ucl_object_t* ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values);
+
733 typedef bool (*ucl_macro_handler) (const unsigned char *data, size_t len, void* ud);
+
734 
+
735 /* Opaque parser */
+
736 struct ucl_parser;
+
737 
+
743 struct ucl_parser* ucl_parser_new (int flags);
+
744 
+
752 void ucl_parser_register_macro (struct ucl_parser *parser, const char *macro,
+
753  ucl_macro_handler handler, void* ud);
+
754 
+
761 void ucl_parser_register_variable (struct ucl_parser *parser, const char *var,
+
762  const char *value);
+
763 
+
772 bool ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, size_t len);
+
773 
+
781 bool ucl_parser_add_file (struct ucl_parser *parser, const char *filename);
+
782 
+
789 ucl_object_t* ucl_parser_get_object (struct ucl_parser *parser);
+
790 
+
795 const char *ucl_parser_get_error(struct ucl_parser *parser);
+
800 void ucl_parser_free (struct ucl_parser *parser);
+
801 
+
810 bool ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len);
+
811 
+
819 bool ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename,
+
820  bool need_expand);
+
821 
+
837 unsigned char *ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type);
+
840 #ifdef __cplusplus
+
841 }
+
842 #endif
+
843 /*
+
844  * XXX: Poorly named API functions, need to replace them with the appropriate
+
845  * named function. All API functions *must* use naming ucl_object_*. Usage of
+
846  * ucl_obj* should be avoided.
+
847  */
+
848 #define ucl_obj_todouble_safe ucl_object_todouble_safe
+
849 #define ucl_obj_todouble ucl_object_todouble
+
850 #define ucl_obj_tostring ucl_object_tostring
+
851 #define ucl_obj_tostring_safe ucl_object_tostring_safe
+
852 #define ucl_obj_tolstring ucl_object_tolstring
+
853 #define ucl_obj_tolstring_safe ucl_object_tolstring_safe
+
854 #define ucl_obj_toint ucl_object_toint
+
855 #define ucl_obj_toint_safe ucl_object_toint_safe
+
856 #define ucl_obj_toboolean ucl_object_toboolean
+
857 #define ucl_obj_toboolean_safe ucl_object_toboolean_safe
+
858 #define ucl_obj_get_key ucl_object_find_key
+
859 #define ucl_obj_get_keyl ucl_object_find_keyl
+
860 #define ucl_obj_unref ucl_object_unref
+
861 #define ucl_obj_ref ucl_object_ref
+
862 #define ucl_obj_free ucl_object_free
+
863 
+
864 #endif /* UCL_H_ */
+
+ + + + Property changes on: contrib/libucl/doc/html/ucl_8h_source.html ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/include/ucl.h =================================================================== --- contrib/libucl/include/ucl.h (revision 0) +++ contrib/libucl/include/ucl.h (working copy) @@ -0,0 +1,904 @@ +/* Copyright (c) 2013, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef UCL_H_ +#define UCL_H_ + +#include +#include +#include +#include +#include +#include +#include + +/** + * @mainpage + * This is a reference manual for UCL API. You may find the description of UCL format by following this + * [github repository](https://github.com/vstakhov/libucl). + * + * This manual has several main sections: + * - @ref structures + * - @ref utils + * - @ref parser + * - @ref emitter + */ + +/** + * @file ucl.h + * @brief UCL parsing and emitting functions + * + * UCL is universal configuration language, which is a form of + * JSON with less strict rules that make it more comfortable for + * using as a configuration language + */ +#ifdef __cplusplus +extern "C" { +#endif +/* + * Memory allocation utilities + * UCL_ALLOC(size) - allocate memory for UCL + * UCL_FREE(size, ptr) - free memory of specified size at ptr + * Default: malloc and free + */ +#ifndef UCL_ALLOC +#define UCL_ALLOC(size) malloc(size) +#endif +#ifndef UCL_FREE +#define UCL_FREE(size, ptr) free(ptr) +#endif + +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +#define UCL_WARN_UNUSED_RESULT \ + __attribute__((warn_unused_result)) +#else +#define UCL_WARN_UNUSED_RESULT +#endif + +/** + * @defgroup structures Structures and types + * UCL defines several enumeration types used for error reporting or specifying flags and attributes. + * + * @{ + */ + +/** + * The common error codes returned by ucl parser + */ +typedef enum ucl_error { + UCL_EOK = 0, /**< No error */ + UCL_ESYNTAX, /**< Syntax error occurred during parsing */ + UCL_EIO, /**< IO error occurred during parsing */ + UCL_ESTATE, /**< Invalid state machine state */ + UCL_ENESTED, /**< Input has too many recursion levels */ + UCL_EMACRO, /**< Error processing a macro */ + UCL_EINTERNAL, /**< Internal unclassified error */ + UCL_ESSL /**< SSL error */ +} ucl_error_t; + +/** + * #ucl_object_t may have one of specified types, some types are compatible with each other and some are not. + * For example, you can always convert #UCL_TIME to #UCL_FLOAT. Also you can convert #UCL_FLOAT to #UCL_INTEGER + * by loosing floating point. Every object may be converted to a string by #ucl_object_tostring_forced() function. + * + */ +typedef enum ucl_type { + UCL_OBJECT = 0, /**< UCL object - key/value pairs */ + UCL_ARRAY, /**< UCL array */ + UCL_INT, /**< Integer number */ + UCL_FLOAT, /**< Floating point number */ + UCL_STRING, /**< Null terminated string */ + UCL_BOOLEAN, /**< Boolean value */ + UCL_TIME, /**< Time value (floating point number of seconds) */ + UCL_USERDATA, /**< Opaque userdata pointer (may be used in macros) */ + UCL_NULL /**< Null value */ +} ucl_type_t; + +/** + * You can use one of these types to serialise #ucl_object_t by using ucl_object_emit(). + */ +typedef enum ucl_emitter { + UCL_EMIT_JSON = 0, /**< Emit fine formatted JSON */ + UCL_EMIT_JSON_COMPACT, /**< Emit compacted JSON */ + UCL_EMIT_CONFIG, /**< Emit human readable config format */ + UCL_EMIT_YAML /**< Emit embedded YAML format */ +} ucl_emitter_t; + +/** + * These flags defines parser behaviour. If you specify #UCL_PARSER_ZEROCOPY you must ensure + * that the input memory is not freed if an object is in use. Moreover, if you want to use + * zero-terminated keys and string values then you should not use zero-copy mode, as in this case + * UCL still has to perform copying implicitly. + */ +typedef enum ucl_parser_flags { + UCL_PARSER_KEY_LOWERCASE = 0x1, /**< Convert all keys to lower case */ + UCL_PARSER_ZEROCOPY = 0x2 /**< Parse input in zero-copy mode if possible */ +} ucl_parser_flags_t; + +/** + * String conversion flags, that are used in #ucl_object_fromstring_common function. + */ +typedef enum ucl_string_flags { + UCL_STRING_ESCAPE = 0x1, /**< Perform JSON escape */ + UCL_STRING_TRIM = 0x2, /**< Trim leading and trailing whitespaces */ + UCL_STRING_PARSE_BOOLEAN = 0x4, /**< Parse passed string and detect boolean */ + UCL_STRING_PARSE_INT = 0x8, /**< Parse passed string and detect integer number */ + UCL_STRING_PARSE_DOUBLE = 0x10, /**< Parse passed string and detect integer or float number */ + UCL_STRING_PARSE_NUMBER = UCL_STRING_PARSE_INT|UCL_STRING_PARSE_DOUBLE , /**< + Parse passed string and detect number */ + UCL_STRING_PARSE = UCL_STRING_PARSE_BOOLEAN|UCL_STRING_PARSE_NUMBER, /**< + Parse passed string (and detect booleans and numbers) */ + UCL_STRING_PARSE_BYTES = 0x20 /**< Treat numbers as bytes */ +} ucl_string_flags_t; + +/** + * Basic flags for an object + */ +typedef enum ucl_object_flags { + UCL_OBJECT_ALLOCATED_KEY = 1, /**< An object has key allocated internally */ + UCL_OBJECT_ALLOCATED_VALUE = 2, /**< An object has a string value allocated internally */ + UCL_OBJECT_NEED_KEY_ESCAPE = 4 /**< The key of an object need to be escaped on output */ +} ucl_object_flags_t; + +/** + * UCL object structure. Please mention that the most of fields should not be touched by + * UCL users. In future, this structure may be converted to private one. + */ +typedef struct ucl_object_s { + /** + * Variant value type + */ + union { + int64_t iv; /**< Int value of an object */ + const char *sv; /**< String value of an object */ + double dv; /**< Double value of an object */ + struct ucl_object_s *av; /**< Array */ + void *ov; /**< Object */ + void* ud; /**< Opaque user data */ + } value; + const char *key; /**< Key of an object */ + struct ucl_object_s *next; /**< Array handle */ + struct ucl_object_s *prev; /**< Array handle */ + unsigned char* trash_stack[2]; /**< Pointer to allocated chunks */ + unsigned keylen; /**< Lenght of a key */ + unsigned len; /**< Size of an object */ + enum ucl_type type; /**< Real type */ + uint16_t ref; /**< Reference count */ + uint16_t flags; /**< Object flags */ +} ucl_object_t; + +/** @} */ + +/** + * @defgroup utils Utility functions + * A number of utility functions simplify handling of UCL objects + * + * @{ + */ +/** + * Copy and return a key of an object, returned key is zero-terminated + * @param obj CL object + * @return zero terminated key + */ +char* ucl_copy_key_trash (ucl_object_t *obj); + +/** + * Copy and return a string value of an object, returned key is zero-terminated + * @param obj CL object + * @return zero terminated string representation of object value + */ +char* ucl_copy_value_trash (ucl_object_t *obj); + +/** + * Creates a new object + * @return new object + */ +static inline ucl_object_t* ucl_object_new (void) UCL_WARN_UNUSED_RESULT; +static inline ucl_object_t * +ucl_object_new (void) +{ + ucl_object_t *new; + new = malloc (sizeof (ucl_object_t)); + if (new != NULL) { + memset (new, 0, sizeof (ucl_object_t)); + new->ref = 1; + new->type = UCL_NULL; + } + return new; +} + +/** + * Create new object with type specified + * @param type type of a new object + * @return new object + */ +static inline ucl_object_t* ucl_object_typed_new (unsigned int type) UCL_WARN_UNUSED_RESULT; +static inline ucl_object_t * +ucl_object_typed_new (unsigned int type) +{ + ucl_object_t *new; + new = malloc (sizeof (ucl_object_t)); + if (new != NULL) { + memset (new, 0, sizeof (ucl_object_t)); + new->ref = 1; + new->type = (type <= UCL_NULL ? type : UCL_NULL); + } + return new; +} + +/** + * Convert any string to an ucl object making the specified transformations + * @param str fixed size or NULL terminated string + * @param len length (if len is zero, than str is treated as NULL terminated) + * @param flags conversion flags + * @return new object + */ +ucl_object_t * ucl_object_fromstring_common (const char *str, size_t len, + enum ucl_string_flags flags) UCL_WARN_UNUSED_RESULT; + +/** + * Create a UCL object from the specified string + * @param str NULL terminated string, will be json escaped + * @return new object + */ +static inline ucl_object_t * +ucl_object_fromstring (const char *str) +{ + return ucl_object_fromstring_common (str, 0, UCL_STRING_ESCAPE); +} + +/** + * Create a UCL object from the specified string + * @param str fixed size string, will be json escaped + * @param len length of a string + * @return new object + */ +static inline ucl_object_t * +ucl_object_fromlstring (const char *str, size_t len) +{ + return ucl_object_fromstring_common (str, len, UCL_STRING_ESCAPE); +} + +/** + * Create an object from an integer number + * @param iv number + * @return new object + */ +static inline ucl_object_t * +ucl_object_fromint (int64_t iv) +{ + ucl_object_t *obj; + + obj = ucl_object_new (); + if (obj != NULL) { + obj->type = UCL_INT; + obj->value.iv = iv; + } + + return obj; +} + +/** + * Create an object from a float number + * @param dv number + * @return new object + */ +static inline ucl_object_t * +ucl_object_fromdouble (double dv) +{ + ucl_object_t *obj; + + obj = ucl_object_new (); + if (obj != NULL) { + obj->type = UCL_FLOAT; + obj->value.dv = dv; + } + + return obj; +} + +/** + * Create an object from a boolean + * @param bv bool value + * @return new object + */ +static inline ucl_object_t * +ucl_object_frombool (bool bv) +{ + ucl_object_t *obj; + + obj = ucl_object_new (); + if (obj != NULL) { + obj->type = UCL_BOOLEAN; + obj->value.iv = bv; + } + + return obj; +} + +/** + * Insert a object 'elt' to the hash 'top' and associate it with key 'key' + * @param top destination object (will be created automatically if top is NULL) + * @param elt element to insert (must NOT be NULL) + * @param key key to associate with this object (either const or preallocated) + * @param keylen length of the key (or 0 for NULL terminated keys) + * @param copy_key make an internal copy of key + * @return new value of top object + */ +ucl_object_t* ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, + const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; + +/** + * Replace a object 'elt' to the hash 'top' and associate it with key 'key', old object will be unrefed, + * if no object has been found this function works like ucl_object_insert_key() + * @param top destination object (will be created automatically if top is NULL) + * @param elt element to insert (must NOT be NULL) + * @param key key to associate with this object (either const or preallocated) + * @param keylen length of the key (or 0 for NULL terminated keys) + * @param copy_key make an internal copy of key + * @return new value of top object + */ +ucl_object_t* ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt, + const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; + +/** + * Insert a object 'elt' to the hash 'top' and associate it with key 'key', if the specified key exist, + * try to merge its content + * @param top destination object (will be created automatically if top is NULL) + * @param elt element to insert (must NOT be NULL) + * @param key key to associate with this object (either const or preallocated) + * @param keylen length of the key (or 0 for NULL terminated keys) + * @param copy_key make an internal copy of key + * @return new value of top object + */ +ucl_object_t* ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt, + const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; + +/** + * Append an element to the array object + * @param top destination object (will be created automatically if top is NULL) + * @param eltelement to append (must NOT be NULL) + * @return new value of top object + */ +static inline ucl_object_t * ucl_array_append (ucl_object_t *top, + ucl_object_t *elt) UCL_WARN_UNUSED_RESULT; +static inline ucl_object_t * +ucl_array_append (ucl_object_t *top, ucl_object_t *elt) +{ + ucl_object_t *head; + + if (elt == NULL) { + return NULL; + } + + if (top == NULL) { + top = ucl_object_new (); + top->type = UCL_ARRAY; + top->value.av = elt; + elt->next = NULL; + elt->prev = elt; + } + else { + head = top->value.av; + elt->prev = head->prev; + head->prev->next = elt; + head->prev = elt; + elt->next = NULL; + } + + return top; +} + +/** + * Append a element to another element forming an implicit array + * @param head head to append (may be NULL) + * @param elt new element + * @return new head if applicable + */ +static inline ucl_object_t * ucl_elt_append (ucl_object_t *head, + ucl_object_t *elt) UCL_WARN_UNUSED_RESULT; +static inline ucl_object_t * +ucl_elt_append (ucl_object_t *head, ucl_object_t *elt) +{ + + if (head == NULL) { + elt->next = NULL; + elt->prev = elt; + head = elt; + } + else { + elt->prev = head->prev; + head->prev->next = elt; + head->prev = elt; + elt->next = NULL; + } + + return head; +} + +/** + * Converts an object to double value + * @param obj CL object + * @param target target double variable + * @return true if conversion was successful + */ +static inline bool +ucl_object_todouble_safe (ucl_object_t *obj, double *target) +{ + if (obj == NULL) { + return false; + } + switch (obj->type) { + case UCL_INT: + *target = obj->value.iv; /* Probaly could cause overflow */ + break; + case UCL_FLOAT: + case UCL_TIME: + *target = obj->value.dv; + break; + default: + return false; + } + + return true; +} + +/** + * Unsafe version of \ref ucl_obj_todouble_safe + * @param obj CL object + * @return double value + */ +static inline double +ucl_object_todouble (ucl_object_t *obj) +{ + double result = 0.; + + ucl_object_todouble_safe (obj, &result); + return result; +} + +/** + * Converts an object to integer value + * @param obj CL object + * @param target target integer variable + * @return true if conversion was successful + */ +static inline bool +ucl_object_toint_safe (ucl_object_t *obj, int64_t *target) +{ + if (obj == NULL) { + return false; + } + switch (obj->type) { + case UCL_INT: + *target = obj->value.iv; + break; + case UCL_FLOAT: + case UCL_TIME: + *target = obj->value.dv; /* Loosing of decimal points */ + break; + default: + return false; + } + + return true; +} + +/** + * Unsafe version of \ref ucl_obj_toint_safe + * @param obj CL object + * @return int value + */ +static inline int64_t +ucl_object_toint (ucl_object_t *obj) +{ + int64_t result = 0; + + ucl_object_toint_safe (obj, &result); + return result; +} + +/** + * Converts an object to boolean value + * @param obj CL object + * @param target target boolean variable + * @return true if conversion was successful + */ +static inline bool +ucl_object_toboolean_safe (ucl_object_t *obj, bool *target) +{ + if (obj == NULL) { + return false; + } + switch (obj->type) { + case UCL_BOOLEAN: + *target = (obj->value.iv == true); + break; + default: + return false; + } + + return true; +} + +/** + * Unsafe version of \ref ucl_obj_toboolean_safe + * @param obj CL object + * @return boolean value + */ +static inline bool +ucl_object_toboolean (ucl_object_t *obj) +{ + bool result = false; + + ucl_object_toboolean_safe (obj, &result); + return result; +} + +/** + * Converts an object to string value + * @param obj CL object + * @param target target string variable, no need to free value + * @return true if conversion was successful + */ +static inline bool +ucl_object_tostring_safe (ucl_object_t *obj, const char **target) +{ + if (obj == NULL) { + return false; + } + + switch (obj->type) { + case UCL_STRING: + *target = ucl_copy_value_trash (obj); + break; + default: + return false; + } + + return true; +} + +/** + * Unsafe version of \ref ucl_obj_tostring_safe + * @param obj CL object + * @return string value + */ +static inline const char * +ucl_object_tostring (ucl_object_t *obj) +{ + const char *result = NULL; + + ucl_object_tostring_safe (obj, &result); + return result; +} + +/** + * Convert any object to a string in JSON notation if needed + * @param obj CL object + * @return string value + */ +static inline const char * +ucl_object_tostring_forced (ucl_object_t *obj) +{ + return ucl_copy_value_trash (obj); +} + +/** + * Return string as char * and len, string may be not zero terminated, more efficient that \ref ucl_obj_tostring as it + * allows zero-copy (if #UCL_PARSER_ZEROCOPY has been used during parsing) + * @param obj CL object + * @param target target string variable, no need to free value + * @param tlen target length + * @return true if conversion was successful + */ +static inline bool +ucl_object_tolstring_safe (ucl_object_t *obj, const char **target, size_t *tlen) +{ + if (obj == NULL) { + return false; + } + switch (obj->type) { + case UCL_STRING: + *target = obj->value.sv; + *tlen = obj->len; + break; + default: + return false; + } + + return true; +} + +/** + * Unsafe version of \ref ucl_obj_tolstring_safe + * @param obj CL object + * @return string value + */ +static inline const char * +ucl_object_tolstring (ucl_object_t *obj, size_t *tlen) +{ + const char *result = NULL; + + ucl_object_tolstring_safe (obj, &result, tlen); + return result; +} + +/** + * Return object identified by a key in the specified object + * @param obj object to get a key from (must be of type UCL_OBJECT) + * @param key key to search + * @return object matched the specified key or NULL if key is not found + */ +ucl_object_t * ucl_object_find_key (ucl_object_t *obj, const char *key); + +/** + * Return object identified by a fixed size key in the specified object + * @param obj object to get a key from (must be of type UCL_OBJECT) + * @param key key to search + * @param klen length of a key + * @return object matched the specified key or NULL if key is not found + */ +ucl_object_t *ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen); + +/** + * Returns a key of an object as a NULL terminated string + * @param obj CL object + * @return key or NULL if there is no key + */ +static inline const char * +ucl_object_key (ucl_object_t *obj) +{ + return ucl_copy_key_trash (obj); +} + +/** + * Returns a key of an object as a fixed size string (may be more efficient) + * @param obj CL object + * @param len target key length + * @return key pointer + */ +static inline const char * +ucl_object_keyl (ucl_object_t *obj, size_t *len) +{ + *len = obj->keylen; + return obj->key; +} + +/** + * Free ucl object + * @param obj ucl object to free + */ +void ucl_object_free (ucl_object_t *obj); + +/** + * Increase reference count for an object + * @param obj object to ref + */ +static inline ucl_object_t * +ucl_object_ref (ucl_object_t *obj) { + obj->ref ++; + return obj; +} + +/** + * Decrease reference count for an object + * @param obj object to unref + */ +static inline void +ucl_object_unref (ucl_object_t *obj) { + if (--obj->ref <= 0) { + ucl_object_free (obj); + } +} +/** + * Opaque iterator object + */ +typedef void* ucl_object_iter_t; + +/** + * Get next key from an object + * @param obj object to iterate + * @param iter opaque iterator, must be set to NULL on the first call: + * ucl_object_iter_t it = NULL; + * while ((cur = ucl_iterate_object (obj, &it)) != NULL) ... + * @return the next object or NULL + */ +ucl_object_t* ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values); +/** @} */ + + +/** + * @defgroup parser Parsing functions + * These functions are used to parse UCL objects + * + * @{ + */ + +/** + * Macro handler for a parser + * @param data the content of macro + * @param len the length of content + * @param ud opaque user data + * @param err error pointer + * @return true if macro has been parsed + */ +typedef bool (*ucl_macro_handler) (const unsigned char *data, size_t len, void* ud); + +/* Opaque parser */ +struct ucl_parser; + +/** + * Creates new parser object + * @param pool pool to allocate memory from + * @return new parser object + */ +struct ucl_parser* ucl_parser_new (int flags); + +/** + * Register new handler for a macro + * @param parser parser object + * @param macro macro name (without leading dot) + * @param handler handler (it is called immediately after macro is parsed) + * @param ud opaque user data for a handler + */ +void ucl_parser_register_macro (struct ucl_parser *parser, const char *macro, + ucl_macro_handler handler, void* ud); + +/** + * Register new parser variable + * @param parser parser object + * @param var variable name + * @param value variable value + */ +void ucl_parser_register_variable (struct ucl_parser *parser, const char *var, + const char *value); + +/** + * Load new chunk to a parser + * @param parser parser structure + * @param data the pointer to the beginning of a chunk + * @param len the length of a chunk + * @param err if *err is NULL it is set to parser error + * @return true if chunk has been added and false in case of error + */ +bool ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, size_t len); + +/** + * Load and add data from a file + * @param parser parser structure + * @param filename the name of file + * @param err if *err is NULL it is set to parser error + * @return true if chunk has been added and false in case of error + */ +bool ucl_parser_add_file (struct ucl_parser *parser, const char *filename); + +/** + * Get a top object for a parser + * @param parser parser structure + * @param err if *err is NULL it is set to parser error + * @return top parser object or NULL + */ +ucl_object_t* ucl_parser_get_object (struct ucl_parser *parser); + +/** + * Get the error string if failing + * @param parser parser object + */ +const char *ucl_parser_get_error(struct ucl_parser *parser); +/** + * Free ucl parser object + * @param parser parser object + */ +void ucl_parser_free (struct ucl_parser *parser); + +/** + * Add new public key to parser for signatures check + * @param parser parser object + * @param key PEM representation of a key + * @param len length of the key + * @param err if *err is NULL it is set to parser error + * @return true if a key has been successfully added + */ +bool ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len); + +/** + * Set FILENAME and CURDIR variables in parser + * @param parser parser object + * @param filename filename to set or NULL to set FILENAME to "undef" and CURDIR to getcwd() + * @param need_expand perform realpath() if this variable is true and filename is not NULL + * @return true if variables has been set + */ +bool ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, + bool need_expand); + +/** @} */ + +/** + * @defgroup emitter Emitting functions + * These functions are used to serialise UCL objects to some string representation. + * + * @{ + */ + +/** + * Structure using for emitter callbacks + */ +struct ucl_emitter_functions { + /** Append a single character */ + int (*ucl_emitter_append_character) (unsigned char c, size_t nchars, void *ud); + /** Append a string of a specified length */ + int (*ucl_emitter_append_len) (unsigned const char *str, size_t len, void *ud); + /** Append a 64 bit integer */ + int (*ucl_emitter_append_int) (int64_t elt, void *ud); + /** Append floating point element */ + int (*ucl_emitter_append_double) (double elt, void *ud); + /** Opaque userdata pointer */ + void *ud; +}; + +/** + * Emit object to a string + * @param obj object + * @param emit_type if type is #UCL_EMIT_JSON then emit json, if type is + * #UCL_EMIT_CONFIG then emit config like object + * @return dump of an object (must be freed after using) or NULL in case of error + */ +unsigned char *ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type); + +/** + * Emit object to a string + * @param obj object + * @param emit_type if type is #UCL_EMIT_JSON then emit json, if type is + * #UCL_EMIT_CONFIG then emit config like object + * @return dump of an object (must be freed after using) or NULL in case of error + */ +bool ucl_object_emit_full (ucl_object_t *obj, enum ucl_emitter emit_type, + struct ucl_emitter_functions *emitter); +/** @} */ + +#ifdef __cplusplus +} +#endif +/* + * XXX: Poorly named API functions, need to replace them with the appropriate + * named function. All API functions *must* use naming ucl_object_*. Usage of + * ucl_obj* should be avoided. + */ +#define ucl_obj_todouble_safe ucl_object_todouble_safe +#define ucl_obj_todouble ucl_object_todouble +#define ucl_obj_tostring ucl_object_tostring +#define ucl_obj_tostring_safe ucl_object_tostring_safe +#define ucl_obj_tolstring ucl_object_tolstring +#define ucl_obj_tolstring_safe ucl_object_tolstring_safe +#define ucl_obj_toint ucl_object_toint +#define ucl_obj_toint_safe ucl_object_toint_safe +#define ucl_obj_toboolean ucl_object_toboolean +#define ucl_obj_toboolean_safe ucl_object_toboolean_safe +#define ucl_obj_get_key ucl_object_find_key +#define ucl_obj_get_keyl ucl_object_find_keyl +#define ucl_obj_unref ucl_object_unref +#define ucl_obj_ref ucl_object_ref +#define ucl_obj_free ucl_object_free + +#endif /* UCL_H_ */ Property changes on: contrib/libucl/include/ucl.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: contrib/libucl/src/ucl_chartable.h =================================================================== --- contrib/libucl/src/ucl_chartable.h (revision 0) +++ contrib/libucl/src/ucl_chartable.h (working copy) @@ -0,0 +1,267 @@ +/* Copyright (c) 2013, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef UCL_CHARTABLE_H_ +#define UCL_CHARTABLE_H_ + +#include "ucl_internal.h" + +static const unsigned int ucl_chartable[255] = { +UCL_CHARACTER_VALUE_END, 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_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 +}; + +static inline bool +ucl_test_character (unsigned char c, int type_flags) +{ + return (ucl_chartable[c] & type_flags) != 0; +} + +#endif /* UCL_CHARTABLE_H_ */ Property changes on: contrib/libucl/src/ucl_chartable.h ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/src/ucl_emitter.c =================================================================== --- contrib/libucl/src/ucl_emitter.c (revision 0) +++ contrib/libucl/src/ucl_emitter.c (working copy) @@ -0,0 +1,776 @@ +/* Copyright (c) 2013, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "ucl.h" +#include "ucl_internal.h" +#include "ucl_chartable.h" + +/** + * @file rcl_emitter.c + * Serialise UCL object to various of output formats + */ + + +static void ucl_obj_write_json (ucl_object_t *obj, + struct ucl_emitter_functions *func, + unsigned int tabs, + bool start_tabs, + bool compact); +static void ucl_elt_write_json (ucl_object_t *obj, + struct ucl_emitter_functions *func, + unsigned int tabs, + bool start_tabs, + bool compact); +static void ucl_elt_write_config (ucl_object_t *obj, + struct ucl_emitter_functions *func, + unsigned int tabs, + bool start_tabs, + bool is_top, + bool expand_array); +static void ucl_elt_write_yaml (ucl_object_t *obj, + struct ucl_emitter_functions *func, + unsigned int tabs, + bool start_tabs, + bool compact, + bool expand_array); +static void ucl_elt_array_write_yaml (ucl_object_t *obj, + struct ucl_emitter_functions *func, + unsigned int tabs, + bool start_tabs, + bool is_top); + +/** + * Add tabulation to the output buffer + * @param buf target buffer + * @param tabs number of tabs to add + */ +static inline void +ucl_add_tabs (struct ucl_emitter_functions *func, unsigned int tabs, bool compact) +{ + if (!compact) { + func->ucl_emitter_append_character (' ', tabs * 4, func->ud); + } +} + +/** + * Serialise string + * @param str string to emit + * @param buf target buffer + */ +static void +ucl_elt_string_write_json (const char *str, size_t size, + struct ucl_emitter_functions *func) +{ + const char *p = str, *c = str; + size_t len = 0; + + func->ucl_emitter_append_character ('"', 1, func->ud); + while (size) { + if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) { + if (len > 0) { + func->ucl_emitter_append_len (c, len, func->ud); + } + switch (*p) { + case '\n': + func->ucl_emitter_append_len ("\\n", 2, func->ud); + break; + case '\r': + func->ucl_emitter_append_len ("\\r", 2, func->ud); + break; + case '\b': + func->ucl_emitter_append_len ("\\b", 2, func->ud); + break; + case '\t': + func->ucl_emitter_append_len ("\\t", 2, func->ud); + break; + case '\f': + func->ucl_emitter_append_len ("\\f", 2, func->ud); + break; + case '\\': + func->ucl_emitter_append_len ("\\\\", 2, func->ud); + break; + case '"': + func->ucl_emitter_append_len ("\\\"", 2, func->ud); + break; + } + len = 0; + c = ++p; + } + else { + p ++; + len ++; + } + size --; + } + if (len > 0) { + func->ucl_emitter_append_len (c, len, func->ud); + } + func->ucl_emitter_append_character ('"', 1, func->ud); +} + +/** + * Write a single object to the buffer + * @param obj object to write + * @param buf target buffer + */ +static void +ucl_elt_obj_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func, + unsigned int tabs, bool start_tabs, bool compact) +{ + ucl_object_t *cur; + ucl_hash_iter_t it = NULL; + + if (start_tabs) { + ucl_add_tabs (func, tabs, compact); + } + if (compact) { + func->ucl_emitter_append_character ('{', 1, func->ud); + } + else { + func->ucl_emitter_append_len ("{\n", 2, func->ud); + } + while ((cur = ucl_hash_iterate (obj->value.ov, &it))) { + ucl_add_tabs (func, tabs + 1, compact); + if (cur->keylen > 0) { + ucl_elt_string_write_json (cur->key, cur->keylen, func); + } + else { + func->ucl_emitter_append_len ("null", 4, func->ud); + } + if (compact) { + func->ucl_emitter_append_character (':', 1, func->ud); + } + else { + func->ucl_emitter_append_len (": ", 2, func->ud); + } + ucl_obj_write_json (cur, func, tabs + 1, false, compact); + if (ucl_hash_iter_has_next (it)) { + if (compact) { + func->ucl_emitter_append_character (',', 1, func->ud); + } + else { + func->ucl_emitter_append_len (",\n", 2, func->ud); + } + } + else if (!compact) { + func->ucl_emitter_append_character ('\n', 1, func->ud); + } + } + ucl_add_tabs (func, tabs, compact); + func->ucl_emitter_append_character ('}', 1, func->ud); +} + +/** + * Write a single array to the buffer + * @param obj array to write + * @param buf target buffer + */ +static void +ucl_elt_array_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func, + unsigned int tabs, bool start_tabs, bool compact) +{ + ucl_object_t *cur = obj; + + if (start_tabs) { + ucl_add_tabs (func, tabs, compact); + } + if (compact) { + func->ucl_emitter_append_character ('[', 1, func->ud); + } + else { + func->ucl_emitter_append_len ("[\n", 2, func->ud); + } + while (cur) { + ucl_elt_write_json (cur, func, tabs + 1, true, compact); + if (cur->next != NULL) { + if (compact) { + func->ucl_emitter_append_character (',', 1, func->ud); + } + else { + func->ucl_emitter_append_len (",\n", 2, func->ud); + } + } + else if (!compact) { + func->ucl_emitter_append_character ('\n', 1, func->ud); + } + cur = cur->next; + } + ucl_add_tabs (func, tabs, compact); + func->ucl_emitter_append_character (']', 1, func->ud); +} + +/** + * Emit a single element + * @param obj object + * @param buf buffer + */ +static void +ucl_elt_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func, + unsigned int tabs, bool start_tabs, bool compact) +{ + bool flag; + + switch (obj->type) { + case UCL_INT: + if (start_tabs) { + ucl_add_tabs (func, tabs, compact); + } + func->ucl_emitter_append_int (ucl_object_toint (obj), func->ud); + break; + case UCL_FLOAT: + case UCL_TIME: + if (start_tabs) { + ucl_add_tabs (func, tabs, compact); + } + func->ucl_emitter_append_double (ucl_object_todouble (obj), func->ud); + break; + case UCL_BOOLEAN: + if (start_tabs) { + ucl_add_tabs (func, tabs, compact); + } + flag = ucl_object_toboolean (obj); + if (flag) { + func->ucl_emitter_append_len ("true", 4, func->ud); + } + else { + func->ucl_emitter_append_len ("false", 5, func->ud); + } + break; + case UCL_STRING: + if (start_tabs) { + ucl_add_tabs (func, tabs, compact); + } + ucl_elt_string_write_json (obj->value.sv, obj->len, func); + break; + case UCL_NULL: + if (start_tabs) { + ucl_add_tabs (func, tabs, compact); + } + func->ucl_emitter_append_len ("null", 4, func->ud); + break; + case UCL_OBJECT: + ucl_elt_obj_write_json (obj, func, tabs, start_tabs, compact); + break; + case UCL_ARRAY: + ucl_elt_array_write_json (obj->value.av, func, tabs, start_tabs, compact); + break; + case UCL_USERDATA: + break; + } +} + +/** + * Write a single object to the buffer + * @param obj object + * @param buf target buffer + */ +static void +ucl_obj_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func, + unsigned int tabs, bool start_tabs, bool compact) +{ + ucl_object_t *cur; + bool is_array = (obj->next != NULL); + + if (is_array) { + /* This is an array actually */ + if (start_tabs) { + ucl_add_tabs (func, tabs, compact); + } + + if (compact) { + func->ucl_emitter_append_character ('[', 1, func->ud); + } + else { + func->ucl_emitter_append_len ("[\n", 2, func->ud); + } + cur = obj; + while (cur != NULL) { + ucl_elt_write_json (cur, func, tabs + 1, true, compact); + if (cur->next) { + func->ucl_emitter_append_character (',', 1, func->ud); + } + if (!compact) { + func->ucl_emitter_append_character ('\n', 1, func->ud); + } + cur = cur->next; + } + ucl_add_tabs (func, tabs, compact); + func->ucl_emitter_append_character (']', 1, func->ud); + } + else { + ucl_elt_write_json (obj, func, tabs, start_tabs, compact); + } + +} + +/** + * Emit an object to json + * @param obj object + * @return json output (should be freed after using) + */ +static void +ucl_object_emit_json (ucl_object_t *obj, bool compact, struct ucl_emitter_functions *func) +{ + ucl_obj_write_json (obj, func, 0, false, compact); +} + +/** + * Write a single object to the buffer + * @param obj object to write + * @param buf target buffer + */ +static void +ucl_elt_obj_write_config (ucl_object_t *obj, struct ucl_emitter_functions *func, + unsigned int tabs, bool start_tabs, bool is_top) +{ + ucl_object_t *cur, *cur_obj; + ucl_hash_iter_t it = NULL; + + if (start_tabs) { + ucl_add_tabs (func, tabs, is_top); + } + if (!is_top) { + func->ucl_emitter_append_len ("{\n", 2, func->ud); + } + + while ((cur = ucl_hash_iterate (obj->value.ov, &it))) { + LL_FOREACH (cur, cur_obj) { + ucl_add_tabs (func, tabs + 1, is_top); + if (cur_obj->flags & UCL_OBJECT_NEED_KEY_ESCAPE) { + ucl_elt_string_write_json (cur_obj->key, cur_obj->keylen, func); + } + else { + func->ucl_emitter_append_len (cur_obj->key, cur_obj->keylen, func->ud); + } + if (cur_obj->type != UCL_OBJECT && cur_obj->type != UCL_ARRAY) { + func->ucl_emitter_append_len (" = ", 3, func->ud); + } + else { + func->ucl_emitter_append_character (' ', 1, func->ud); + } + ucl_elt_write_config (cur_obj, func, + is_top ? tabs : tabs + 1, + false, false, false); + if (cur_obj->type != UCL_OBJECT && cur_obj->type != UCL_ARRAY) { + func->ucl_emitter_append_len (";\n", 2, func->ud); + } + else { + func->ucl_emitter_append_character ('\n', 1, func->ud); + } + } + } + + ucl_add_tabs (func, tabs, is_top); + if (!is_top) { + func->ucl_emitter_append_character ('}', 1, func->ud); + } +} + +/** + * Write a single array to the buffer + * @param obj array to write + * @param buf target buffer + */ +static void +ucl_elt_array_write_config (ucl_object_t *obj, struct ucl_emitter_functions *func, + unsigned int tabs, bool start_tabs, bool is_top) +{ + ucl_object_t *cur = obj; + + if (start_tabs) { + ucl_add_tabs (func, tabs, false); + } + + func->ucl_emitter_append_len ("[\n", 2, func->ud); + while (cur) { + ucl_elt_write_config (cur, func, tabs + 1, true, false, false); + func->ucl_emitter_append_len (",\n", 2, func->ud); + cur = cur->next; + } + ucl_add_tabs (func, tabs, false); + func->ucl_emitter_append_character (']', 1, func->ud); +} + +/** + * Emit a single element + * @param obj object + * @param buf buffer + */ +static void +ucl_elt_write_config (ucl_object_t *obj, struct ucl_emitter_functions *func, + unsigned int tabs, bool start_tabs, bool is_top, bool expand_array) +{ + bool flag; + + if (expand_array && obj->next != NULL) { + ucl_elt_array_write_config (obj, func, tabs, start_tabs, is_top); + } + else { + switch (obj->type) { + case UCL_INT: + if (start_tabs) { + ucl_add_tabs (func, tabs, false); + } + func->ucl_emitter_append_int (ucl_object_toint (obj), func->ud); + break; + case UCL_FLOAT: + case UCL_TIME: + if (start_tabs) { + ucl_add_tabs (func, tabs, false); + } + func->ucl_emitter_append_double (ucl_object_todouble (obj), func->ud); + break; + case UCL_BOOLEAN: + if (start_tabs) { + ucl_add_tabs (func, tabs, false); + } + flag = ucl_object_toboolean (obj); + if (flag) { + func->ucl_emitter_append_len ("true", 4, func->ud); + } + else { + func->ucl_emitter_append_len ("false", 5, func->ud); + } + break; + case UCL_STRING: + if (start_tabs) { + ucl_add_tabs (func, tabs, false); + } + ucl_elt_string_write_json (obj->value.sv, obj->len, func); + break; + case UCL_NULL: + if (start_tabs) { + ucl_add_tabs (func, tabs, false); + } + func->ucl_emitter_append_len ("null", 4, func->ud); + break; + case UCL_OBJECT: + ucl_elt_obj_write_config (obj, func, tabs, start_tabs, is_top); + break; + case UCL_ARRAY: + ucl_elt_array_write_config (obj->value.av, func, tabs, start_tabs, is_top); + break; + case UCL_USERDATA: + break; + } + } +} + +/** + * Emit an object to rcl + * @param obj object + * @return rcl output (should be freed after using) + */ +static void +ucl_object_emit_config (ucl_object_t *obj, struct ucl_emitter_functions *func) +{ + ucl_elt_write_config (obj, func, 0, false, true, true); +} + + +static void +ucl_obj_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func, + unsigned int tabs, bool start_tabs) +{ + bool is_array = (obj->next != NULL); + + if (is_array) { + ucl_elt_array_write_yaml (obj, func, tabs, start_tabs, false); + } + else { + ucl_elt_write_yaml (obj, func, tabs, start_tabs, false, true); + } +} + +/** + * Write a single object to the buffer + * @param obj object to write + * @param buf target buffer + */ +static void +ucl_elt_obj_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func, + unsigned int tabs, bool start_tabs, bool is_top) +{ + ucl_object_t *cur; + ucl_hash_iter_t it = NULL; + + if (start_tabs) { + ucl_add_tabs (func, tabs, is_top); + } + if (!is_top) { + func->ucl_emitter_append_len ("{\n", 2, func->ud); + } + + while ((cur = ucl_hash_iterate (obj->value.ov, &it))) { + ucl_add_tabs (func, tabs + 1, is_top); + if (cur->keylen > 0) { + ucl_elt_string_write_json (cur->key, cur->keylen, func); + } + else { + func->ucl_emitter_append_len ("null", 4, func->ud); + } + func->ucl_emitter_append_len (": ", 2, func->ud); + ucl_obj_write_yaml (cur, func, is_top ? tabs : tabs + 1, false); + if (ucl_hash_iter_has_next(it)) { + if (!is_top) { + func->ucl_emitter_append_len (",\n", 2, func->ud); + } + else { + func->ucl_emitter_append_character ('\n', 1, func->ud); + } + } + else { + func->ucl_emitter_append_character ('\n', 1, func->ud); + } + } + + ucl_add_tabs (func, tabs, is_top); + if (!is_top) { + func->ucl_emitter_append_character ('}', 1, func->ud); + } +} + +/** + * Write a single array to the buffer + * @param obj array to write + * @param buf target buffer + */ +static void +ucl_elt_array_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func, + unsigned int tabs, bool start_tabs, bool is_top) +{ + ucl_object_t *cur = obj; + + if (start_tabs) { + ucl_add_tabs (func, tabs, false); + } + + func->ucl_emitter_append_len ("[\n", 2, func->ud); + while (cur) { + ucl_elt_write_yaml (cur, func, tabs + 1, true, false, false); + func->ucl_emitter_append_len (",\n", 2, func->ud); + cur = cur->next; + } + ucl_add_tabs (func, tabs, false); + func->ucl_emitter_append_character (']', 1, func->ud); +} + +/** + * Emit a single element + * @param obj object + * @param buf buffer + */ +static void +ucl_elt_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func, + unsigned int tabs, bool start_tabs, bool is_top, bool expand_array) +{ + bool flag; + + if (expand_array && obj->next != NULL ) { + ucl_elt_array_write_yaml (obj, func, tabs, start_tabs, is_top); + } + else { + switch (obj->type) { + case UCL_INT: + if (start_tabs) { + ucl_add_tabs (func, tabs, false); + } + func->ucl_emitter_append_int (ucl_object_toint (obj), func->ud); + break; + case UCL_FLOAT: + case UCL_TIME: + if (start_tabs) { + ucl_add_tabs (func, tabs, false); + } + func->ucl_emitter_append_double (ucl_object_todouble (obj), func->ud); + break; + case UCL_BOOLEAN: + if (start_tabs) { + ucl_add_tabs (func, tabs, false); + } + flag = ucl_object_toboolean (obj); + if (flag) { + func->ucl_emitter_append_len ("true", 4, func->ud); + } + else { + func->ucl_emitter_append_len ("false", 5, func->ud); + } + break; + case UCL_STRING: + if (start_tabs) { + ucl_add_tabs (func, tabs, false); + } + ucl_elt_string_write_json (obj->value.sv, obj->len, func); + break; + case UCL_NULL: + if (start_tabs) { + ucl_add_tabs (func, tabs, false); + } + func->ucl_emitter_append_len ("null", 4, func->ud); + break; + case UCL_OBJECT: + ucl_elt_obj_write_yaml (obj, func, tabs, start_tabs, is_top); + break; + case UCL_ARRAY: + ucl_elt_array_write_yaml (obj->value.av, func, tabs, start_tabs, is_top); + break; + case UCL_USERDATA: + break; + } + } +} + +/** + * Emit an object to rcl + * @param obj object + * @return rcl output (should be freed after using) + */ +static void +ucl_object_emit_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func) +{ + ucl_elt_write_yaml (obj, func, 0, false, true, true); +} + +/* + * Generic utstring output + */ +static int +ucl_utstring_append_character (unsigned char c, size_t len, void *ud) +{ + UT_string *buf = ud; + + if (len == 1) { + utstring_append_c (buf, c); + } + else { + utstring_reserve (buf, len); + memset (&buf->d[buf->i], c, len); + buf->i += len; + buf->d[buf->i] = '\0'; + } + + return 0; +} + +static int +ucl_utstring_append_len (const unsigned char *str, size_t len, void *ud) +{ + UT_string *buf = ud; + + utstring_append_len (buf, str, len); + + return 0; +} + +static int +ucl_utstring_append_int (int64_t val, void *ud) +{ + UT_string *buf = ud; + + utstring_printf (buf, "%jd", (intmax_t)val); + return 0; +} + +static int +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); + } + else if (fabs (val - (double)(int)val) < delta) { + /* Write at maximum precision */ + utstring_printf (buf, "%.*lg", DBL_DIG, val); + } + else { + utstring_printf (buf, "%lf", val); + } + + return 0; +} + + +unsigned char * +ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type) +{ + UT_string *buf = NULL; + unsigned char *res = NULL; + struct ucl_emitter_functions func = { + .ucl_emitter_append_character = ucl_utstring_append_character, + .ucl_emitter_append_len = ucl_utstring_append_len, + .ucl_emitter_append_int = ucl_utstring_append_int, + .ucl_emitter_append_double = ucl_utstring_append_double + }; + + if (obj == NULL) { + return NULL; + } + + utstring_new (buf); + func.ud = buf; + + if (buf != NULL) { + if (emit_type == UCL_EMIT_JSON) { + ucl_object_emit_json (obj, false, &func); + } + else if (emit_type == UCL_EMIT_JSON_COMPACT) { + ucl_object_emit_json (obj, true, &func); + } + else if (emit_type == UCL_EMIT_YAML) { + ucl_object_emit_yaml (obj, &func); + } + else { + ucl_object_emit_config (obj, &func); + } + + res = utstring_body (buf); + free (buf); + } + + return res; +} + +bool +ucl_object_emit_full (ucl_object_t *obj, enum ucl_emitter emit_type, + struct ucl_emitter_functions *emitter) +{ + if (emit_type == UCL_EMIT_JSON) { + ucl_object_emit_json (obj, false, emitter); + } + else if (emit_type == UCL_EMIT_JSON_COMPACT) { + ucl_object_emit_json (obj, true, emitter); + } + else if (emit_type == UCL_EMIT_YAML) { + ucl_object_emit_yaml (obj, emitter); + } + else { + ucl_object_emit_config (obj, emitter); + } + + /* XXX: need some error checks here */ + return true; +} Property changes on: contrib/libucl/src/ucl_emitter.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: contrib/libucl/src/ucl_hash.c =================================================================== --- contrib/libucl/src/ucl_hash.c (revision 0) +++ contrib/libucl/src/ucl_hash.c (working copy) @@ -0,0 +1,120 @@ +/* Copyright (c) 2013, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ucl_hash.h" +#include "utlist.h" + +ucl_hash_t* +ucl_hash_create (void) +{ + ucl_hash_t *new; + + new = UCL_ALLOC (sizeof (ucl_hash_t)); + if (new != NULL) { + new->buckets = NULL; + } + return new; +} + +void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func *func) +{ + ucl_hash_node_t *elt, *tmp; + + HASH_ITER (hh, hashlin->buckets, elt, tmp) { + HASH_DELETE (hh, hashlin->buckets, elt); + if (func) { + func (elt->data); + } + UCL_FREE (sizeof (ucl_hash_node_t), elt); + } + UCL_FREE (sizeof (ucl_hash_t), hashlin); +} + +void +ucl_hash_insert (ucl_hash_t* hashlin, ucl_object_t *obj, const char *key, unsigned keylen) +{ + ucl_hash_node_t *node; + + node = UCL_ALLOC (sizeof (ucl_hash_node_t)); + node->data = obj; + HASH_ADD_KEYPTR (hh, hashlin->buckets, key, keylen, node); +} + +void* +ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter) +{ + ucl_hash_node_t *elt = *iter; + + if (elt == NULL) { + if (hashlin == NULL || hashlin->buckets == NULL) { + return NULL; + } + elt = hashlin->buckets; + if (elt == NULL) { + return NULL; + } + } + else if (elt == hashlin->buckets) { + return NULL; + } + + *iter = elt->hh.next ? elt->hh.next : hashlin->buckets; + return elt->data; +} + +bool +ucl_hash_iter_has_next (ucl_hash_iter_t iter) +{ + ucl_hash_node_t *elt = iter; + + return (elt == NULL || elt->hh.prev != NULL); +} + + +ucl_object_t* +ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen) +{ + ucl_hash_node_t *found; + + if (hashlin == NULL) { + return NULL; + } + HASH_FIND (hh, hashlin->buckets, key, keylen, found); + + if (found) { + return found->data; + } + return NULL; +} + +void +ucl_hash_delete (ucl_hash_t* hashlin, ucl_object_t *obj) +{ + ucl_hash_node_t *found; + + HASH_FIND (hh, hashlin->buckets, obj->key, obj->keylen, found); + + if (found) { + HASH_DELETE (hh, hashlin->buckets, found); + } +} Property changes on: contrib/libucl/src/ucl_hash.c ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/src/ucl_hash.h =================================================================== --- contrib/libucl/src/ucl_hash.h (revision 0) +++ contrib/libucl/src/ucl_hash.h (working copy) @@ -0,0 +1,91 @@ +/* Copyright (c) 2013, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __UCL_HASH_H +#define __UCL_HASH_H + +#include "ucl.h" +#include "uthash.h" + +/******************************************************************************/ + +typedef struct ucl_hash_node_s +{ + ucl_object_t *data; + UT_hash_handle hh; +} 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; + + +/** + * Linear chained hashtable. + */ +typedef struct ucl_hash_struct +{ + ucl_hash_node_t *buckets; /**< array of hash buckets. One list for each hash modulus. */ +} ucl_hash_t; + + +/** + * Initializes the hashtable. + */ +ucl_hash_t* ucl_hash_create (void); + +/** + * Deinitializes the hashtable. + */ +void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func *func); + +/** + * Inserts an element in the the hashtable. + */ +void ucl_hash_insert (ucl_hash_t* hashlin, ucl_object_t *obj, const char *key, unsigned keylen); + +/** + * Delete an element from the the hashtable. + */ +void ucl_hash_delete (ucl_hash_t* hashlin, ucl_object_t *obj); + +/** + * Searches an element in the hashtable. + */ +ucl_object_t* ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen); + + +/** + * Iterate over hash table + * @param hashlin hash + * @param iter iterator (must be NULL on first iteration) + * @return the next object + */ +void* ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter); + +/** + * Check whether an iterator has next element + */ +bool ucl_hash_iter_has_next (ucl_hash_iter_t iter); + +#endif Property changes on: contrib/libucl/src/ucl_hash.h ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/src/ucl_internal.h =================================================================== --- contrib/libucl/src/ucl_internal.h (revision 0) +++ contrib/libucl/src/ucl_internal.h (working copy) @@ -0,0 +1,284 @@ +/* Copyright (c) 2013, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef UCL_INTERNAL_H_ +#define UCL_INTERNAL_H_ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "utlist.h" +#include "utstring.h" +#include "uthash.h" +#include "ucl.h" +#include "ucl_hash.h" +#include "xxhash.h" + +#ifdef HAVE_OPENSSL +#include +#endif + +/** + * @file rcl_internal.h + * Internal structures and functions of UCL library + */ + +#define UCL_MAX_RECURSION 16 +#define UCL_TRASH_KEY 0 +#define UCL_TRASH_VALUE 1 + +enum ucl_parser_state { + UCL_STATE_INIT = 0, + UCL_STATE_OBJECT, + UCL_STATE_ARRAY, + UCL_STATE_KEY, + UCL_STATE_VALUE, + UCL_STATE_AFTER_VALUE, + UCL_STATE_ARRAY_VALUE, + UCL_STATE_SCOMMENT, + UCL_STATE_MCOMMENT, + UCL_STATE_MACRO_NAME, + UCL_STATE_MACRO, + UCL_STATE_ERROR +}; + +enum ucl_character_type { + UCL_CHARACTER_DENIED = 0, + UCL_CHARACTER_KEY = 1, + UCL_CHARACTER_KEY_START = 1 << 1, + UCL_CHARACTER_WHITESPACE = 1 << 2, + UCL_CHARACTER_WHITESPACE_UNSAFE = 1 << 3, + UCL_CHARACTER_VALUE_END = 1 << 4, + UCL_CHARACTER_VALUE_STR = 1 << 5, + UCL_CHARACTER_VALUE_DIGIT = 1 << 6, + UCL_CHARACTER_VALUE_DIGIT_START = 1 << 7, + UCL_CHARACTER_ESCAPE = 1 << 8, + UCL_CHARACTER_KEY_SEP = 1 << 9, + UCL_CHARACTER_JSON_UNSAFE = 1 << 10, + UCL_CHARACTER_UCL_UNSAFE = 1 << 11 +}; + +struct ucl_macro { + char *name; + ucl_macro_handler handler; + void* ud; + UT_hash_handle hh; +}; + +struct ucl_stack { + ucl_object_t *obj; + struct ucl_stack *next; + int level; +}; + +struct ucl_chunk { + const unsigned char *begin; + const unsigned char *end; + const unsigned char *pos; + size_t remain; + unsigned int line; + unsigned int column; + struct ucl_chunk *next; +}; + +#ifdef HAVE_OPENSSL +struct ucl_pubkey { + EVP_PKEY *key; + struct ucl_pubkey *next; +}; +#else +struct ucl_pubkey { + struct ucl_pubkey *next; +}; +#endif + +struct ucl_variable { + char *var; + char *value; + size_t var_len; + size_t value_len; + struct ucl_variable *next; +}; + +struct ucl_parser { + enum ucl_parser_state state; + enum ucl_parser_state prev_state; + unsigned int recursion; + int flags; + ucl_object_t *top_obj; + ucl_object_t *cur_obj; + struct ucl_macro *macroes; + struct ucl_stack *stack; + struct ucl_chunk *chunks; + struct ucl_pubkey *keys; + struct ucl_variable *variables; + UT_string *err; +}; + +/** + * Unescape json string inplace + * @param str + */ +size_t ucl_unescape_json_string (char *str, size_t len); + +/** + * Handle include macro + * @param data include data + * @param len length of data + * @param ud user data + * @param err error ptr + * @return + */ +bool ucl_include_handler (const unsigned char *data, size_t len, void* ud); + +/** + * Handle includes macro + * @param data include data + * @param len length of data + * @param ud user data + * @param err error ptr + * @return + */ +bool ucl_includes_handler (const unsigned char *data, size_t len, 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); + + +#ifdef __GNUC__ +static inline void +ucl_create_err (UT_string **err, const char *fmt, ...) +__attribute__ (( format( printf, 2, 3) )); +#endif + +static inline void +ucl_create_err (UT_string **err, const char *fmt, ...) + +{ + if (*err == NULL) { + utstring_new (*err); + va_list ap; + va_start (ap, fmt); + utstring_printf_va (*err, fmt, ap); + va_end (ap); + } +} + +/** + * Check whether a given string contains a boolean value + * @param obj object to set + * @param start start of a string + * @param len length of a string + * @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) +{ + const unsigned char *p = start; + bool ret = false, val = false; + + if (len == 5) { + 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) { + ret = true; + val = true; + } + } + else if (len == 3) { + 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) { + ret = true; + val = false; + } + } + else if (len == 2) { + 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) { + ret = true; + val = true; + } + } + + if (ret) { + obj->type = UCL_BOOLEAN; + obj->value.iv = val; + } + + return ret; +} + +/** + * Check numeric string + * @param obj object to set if a string is numeric + * @param start start of string + * @param end end of string + * @param pos position where parsing has stopped + * @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); + + +static inline ucl_object_t * +ucl_hash_search_obj (ucl_hash_t* hashlin, ucl_object_t *obj) +{ + return (ucl_object_t *)ucl_hash_search (hashlin, obj->key, obj->keylen); +} + +static inline ucl_hash_t * +ucl_hash_insert_object (ucl_hash_t *hashlin, ucl_object_t *obj) UCL_WARN_UNUSED_RESULT; + +static inline ucl_hash_t * +ucl_hash_insert_object (ucl_hash_t *hashlin, ucl_object_t *obj) +{ + if (hashlin == NULL) { + hashlin = ucl_hash_create (); + } + ucl_hash_insert (hashlin, obj, obj->key, obj->keylen); + + return hashlin; +} + + +#endif /* UCL_INTERNAL_H_ */ Property changes on: contrib/libucl/src/ucl_internal.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: contrib/libucl/src/ucl_parser.c =================================================================== --- contrib/libucl/src/ucl_parser.c (revision 0) +++ contrib/libucl/src/ucl_parser.c (working copy) @@ -0,0 +1,1830 @@ +/* Copyright (c) 2013, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ucl.h" +#include "ucl_internal.h" +#include "ucl_chartable.h" + +/** + * @file rcl_parser.c + * The implementation of rcl parser + */ + +struct ucl_parser_saved_state { + unsigned int line; + unsigned int column; + size_t remain; + const unsigned char *pos; +}; + +/** + * Move up to len characters + * @param parser + * @param begin + * @param len + * @return new position in chunk + */ +#define ucl_chunk_skipc(chunk, p) do{ \ + if (*(p) == '\n') { \ + (chunk)->line ++; \ + (chunk)->column = 0; \ + } \ + else (chunk)->column ++; \ + (p++); \ + (chunk)->pos ++; \ + (chunk)->remain --; \ + } while (0) + +/** + * Save parser state + * @param chunk + * @param s + */ +static inline void +ucl_chunk_save_state (struct ucl_chunk *chunk, struct ucl_parser_saved_state *s) +{ + s->column = chunk->column; + s->pos = chunk->pos; + s->line = chunk->line; + s->remain = chunk->remain; +} + +/** + * Restore parser state + * @param chunk + * @param s + */ +static inline void +ucl_chunk_restore_state (struct ucl_chunk *chunk, struct ucl_parser_saved_state *s) +{ + chunk->column = s->column; + chunk->pos = s->pos; + chunk->line = s->line; + chunk->remain = s->remain; +} + +static inline void +ucl_set_err (struct ucl_chunk *chunk, int code, const char *str, UT_string **err) +{ + if (isgraph (*chunk->pos)) { + ucl_create_err (err, "error on line %d at column %d: '%s', character: '%c'", + chunk->line, chunk->column, str, *chunk->pos); + } + else { + ucl_create_err (err, "error on line %d at column %d: '%s', character: '0x%02x'", + chunk->line, chunk->column, str, (int)*chunk->pos); + } +} + +/** + * Skip all comments from the current pos resolving nested and multiline comments + * @param parser + * @return + */ +static bool +ucl_skip_comments (struct ucl_parser *parser) +{ + struct ucl_chunk *chunk = parser->chunks; + const unsigned char *p; + int comments_nested = 0; + + p = chunk->pos; + +start: + if (*p == '#') { + if (parser->state != UCL_STATE_SCOMMENT && + parser->state != UCL_STATE_MCOMMENT) { + while (p < chunk->end) { + if (*p == '\n') { + ucl_chunk_skipc (chunk, p); + goto start; + } + ucl_chunk_skipc (chunk, p); + } + } + } + else if (*p == '/' && chunk->remain >= 2) { + if (p[1] == '*') { + ucl_chunk_skipc (chunk, p); + comments_nested ++; + ucl_chunk_skipc (chunk, p); + + while (p < chunk->end) { + if (*p == '*') { + ucl_chunk_skipc (chunk, p); + if (*p == '/') { + comments_nested --; + if (comments_nested == 0) { + ucl_chunk_skipc (chunk, p); + goto start; + } + } + ucl_chunk_skipc (chunk, p); + } + else if (p[0] == '/' && chunk->remain >= 2 && p[1] == '*') { + comments_nested ++; + ucl_chunk_skipc (chunk, p); + ucl_chunk_skipc (chunk, p); + continue; + } + ucl_chunk_skipc (chunk, p); + } + if (comments_nested != 0) { + ucl_set_err (chunk, UCL_ENESTED, "comments nesting is invalid", &parser->err); + return false; + } + } + } + + return true; +} + +/** + * Return multiplier for a character + * @param c multiplier character + * @param is_bytes if true use 1024 multiplier + * @return multiplier + */ +static inline unsigned long +ucl_lex_num_multiplier (const unsigned char c, bool is_bytes) { + const struct { + char c; + long mult_normal; + long mult_bytes; + } multipliers[] = { + {'m', 1000 * 1000, 1024 * 1024}, + {'k', 1000, 1024}, + {'g', 1000 * 1000 * 1000, 1024 * 1024 * 1024} + }; + int i; + + for (i = 0; i < 3; i ++) { + if (tolower (c) == multipliers[i].c) { + if (is_bytes) { + return multipliers[i].mult_bytes; + } + return multipliers[i].mult_normal; + } + } + + return 1; +} + + +/** + * Return multiplier for time scaling + * @param c + * @return + */ +static inline double +ucl_lex_time_multiplier (const unsigned char c) { + const struct { + char c; + double mult; + } multipliers[] = { + {'m', 60}, + {'h', 60 * 60}, + {'d', 60 * 60 * 24}, + {'w', 60 * 60 * 24 * 7}, + {'y', 60 * 60 * 24 * 7 * 365} + }; + int i; + + for (i = 0; i < 5; i ++) { + if (tolower (c) == multipliers[i].c) { + return multipliers[i].mult; + } + } + + return 1; +} + +/** + * Return true if a character is a end of an atom + * @param c + * @return + */ +static inline bool +ucl_lex_is_atom_end (const unsigned char c) +{ + return ucl_test_character (c, UCL_CHARACTER_VALUE_END); +} + +static inline bool +ucl_lex_is_comment (const unsigned char c1, const unsigned char c2) +{ + if (c1 == '/') { + if (c2 == '*') { + return true; + } + } + else if (c1 == '#') { + return true; + } + return false; +} + +/** + * Check variable found + * @param parser + * @param ptr + * @param remain + * @param out_len + * @param strict + * @param found + * @return + */ +static inline const char * +ucl_check_variable_safe (struct ucl_parser *parser, const char *ptr, size_t remain, + size_t *out_len, bool strict, bool *found) +{ + struct ucl_variable *var; + + LL_FOREACH (parser->variables, var) { + if (strict) { + if (remain == var->var_len) { + if (memcmp (ptr, var->var, var->var_len) == 0) { + *out_len += var->value_len; + *found = true; + return (ptr + var->var_len); + } + } + } + else { + if (remain >= var->var_len) { + if (memcmp (ptr, var->var, var->var_len) == 0) { + *out_len += var->value_len; + *found = true; + return (ptr + var->var_len); + } + } + } + } + + return ptr; +} + +/** + * Check for a variable in a given string + * @param parser + * @param ptr + * @param remain + * @param out_len + * @param vars_found + * @return + */ +static const char * +ucl_check_variable (struct ucl_parser *parser, const char *ptr, size_t remain, size_t *out_len, bool *vars_found) +{ + const char *p, *end, *ret = ptr; + bool found = false; + + if (*ptr == '{') { + /* We need to match the variable enclosed in braces */ + p = ptr + 1; + end = ptr + remain; + while (p < end) { + if (*p == '}') { + ret = ucl_check_variable_safe (parser, ptr + 1, p - ptr - 1, out_len, true, &found); + if (found) { + /* {} must be excluded actually */ + ret ++; + if (!*vars_found) { + *vars_found = true; + } + } + else { + *out_len += 2; + } + break; + } + p ++; + } + } + else if (*ptr != '$') { + /* Not count escaped dollar sign */ + ret = ucl_check_variable_safe (parser, ptr, remain, out_len, false, &found); + if (found && !*vars_found) { + *vars_found = true; + } + if (!found) { + (*out_len) ++; + } + } + else { + ret ++; + (*out_len) ++; + } + + return ret; +} + +/** + * Expand a single variable + * @param parser + * @param ptr + * @param remain + * @param dest + * @return + */ +static const char * +ucl_expand_single_variable (struct ucl_parser *parser, const char *ptr, + size_t remain, unsigned char **dest) +{ + unsigned char *d = *dest; + const char *p = ptr + 1, *ret; + struct ucl_variable *var; + bool found = false; + + ret = ptr + 1; + remain --; + + if (*p == '$') { + *d++ = *p++; + *dest = d; + return p; + } + else if (*p == '{') { + p ++; + ret += 2; + remain -= 2; + } + + LL_FOREACH (parser->variables, var) { + if (remain >= var->var_len) { + if (memcmp (p, var->var, var->var_len) == 0) { + memcpy (d, var->value, var->value_len); + ret += var->var_len; + d += var->value_len; + found = true; + break; + } + } + } + if (!found) { + memcpy (d, ptr, 2); + d += 2; + ret --; + } + + *dest = d; + return ret; +} + +/** + * Expand variables in string + * @param parser + * @param dst + * @param src + * @param in_len + * @return + */ +static ssize_t +ucl_expand_variable (struct ucl_parser *parser, unsigned char **dst, + const char *src, size_t in_len) +{ + const char *p, *end = src + in_len; + unsigned char *d; + size_t out_len = 0; + bool vars_found = false; + + p = src; + while (p != end) { + if (*p == '$') { + p = ucl_check_variable (parser, p + 1, end - p - 1, &out_len, &vars_found); + } + else { + p ++; + out_len ++; + } + } + + if (!vars_found) { + /* Trivial case */ + *dst = NULL; + return in_len; + } + + *dst = UCL_ALLOC (out_len + 1); + if (*dst == NULL) { + return in_len; + } + + d = *dst; + p = src; + while (p != end) { + if (*p == '$') { + p = ucl_expand_single_variable (parser, p, end - p, &d); + } + else { + *d++ = *p++; + } + } + + *d = '\0'; + + return out_len; +} + +/** + * Store or copy pointer to the trash stack + * @param parser parser object + * @param src src string + * @param dst destination buffer (trash stack pointer) + * @param dst_const const destination pointer (e.g. value of object) + * @param in_len input length + * @param need_unescape need to unescape source (and copy it) + * @param need_lowercase need to lowercase value (and copy) + * @param need_expand need to expand variables (and copy as well) + * @return output length (excluding \0 symbol) + */ +static inline ssize_t +ucl_copy_or_store_ptr (struct ucl_parser *parser, + const unsigned char *src, unsigned char **dst, + const char **dst_const, size_t in_len, + bool need_unescape, bool need_lowercase, bool need_expand) +{ + ssize_t ret = -1, tret; + unsigned char *tmp; + + if (need_unescape || need_lowercase || + (need_expand && parser->variables != NULL) || + !(parser->flags & UCL_PARSER_ZEROCOPY)) { + /* Copy string */ + *dst = UCL_ALLOC (in_len + 1); + if (*dst == NULL) { + ucl_set_err (parser->chunks, 0, "cannot allocate memory for a string", &parser->err); + return false; + } + if (need_lowercase) { + ret = ucl_strlcpy_tolower (*dst, src, in_len + 1); + } + else { + ret = ucl_strlcpy_unsafe (*dst, src, in_len + 1); + } + + if (need_unescape) { + ret = ucl_unescape_json_string (*dst, ret); + } + if (need_expand) { + tmp = *dst; + tret = ret; + ret = ucl_expand_variable (parser, dst, tmp, ret); + if (*dst == NULL) { + /* Nothing to expand */ + *dst = tmp; + ret = tret; + } + } + *dst_const = *dst; + } + else { + *dst_const = src; + ret = in_len; + } + + return ret; +} + +/** + * Create and append an object at the specified level + * @param parser + * @param is_array + * @param level + * @return + */ +static inline ucl_object_t * +ucl_add_parser_stack (ucl_object_t *obj, struct ucl_parser *parser, bool is_array, int level) +{ + struct ucl_stack *st; + + if (!is_array) { + if (obj == NULL) { + obj = ucl_object_typed_new (UCL_OBJECT); + } + else { + obj->type = UCL_OBJECT; + } + obj->value.ov = ucl_hash_create (); + parser->state = UCL_STATE_KEY; + } + else { + if (obj == NULL) { + obj = ucl_object_typed_new (UCL_ARRAY); + } + else { + obj->type = UCL_ARRAY; + } + parser->state = UCL_STATE_VALUE; + } + + st = UCL_ALLOC (sizeof (struct ucl_stack)); + st->obj = obj; + st->level = level; + LL_PREPEND (parser->stack, st); + parser->cur_obj = obj; + + return obj; +} + +int +ucl_maybe_parse_number (ucl_object_t *obj, + const char *start, const char *end, const char **pos, bool allow_double, bool number_bytes) +{ + const char *p = start, *c = start; + char *endptr; + bool got_dot = false, got_exp = false, need_double = false, is_date = false, valid_start = false; + double dv = 0; + int64_t lv = 0; + + if (*p == '-') { + p ++; + } + while (p < end) { + if (isdigit (*p)) { + valid_start = true; + p ++; + } + else if (allow_double) { + if (p == c) { + /* Empty digits sequence, not a number */ + *pos = start; + return EINVAL; + } + else if (*p == '.') { + if (got_dot) { + /* Double dots, not a number */ + *pos = start; + return EINVAL; + } + else { + got_dot = true; + need_double = true; + p ++; + } + } + else if (*p == 'e' || *p == 'E') { + if (got_exp) { + /* Double exp, not a number */ + *pos = start; + return EINVAL; + } + else { + got_exp = true; + need_double = true; + p ++; + if (p >= end) { + *pos = start; + return EINVAL; + } + if (!isdigit (*p) && *p != '+' && *p != '-') { + /* Wrong exponent sign */ + *pos = start; + return EINVAL; + } + else { + p ++; + } + } + } + else { + /* Got the end of the number, need to check */ + break; + } + } + else { + break; + } + } + + if (!valid_start) { + *pos = start; + return EINVAL; + } + + errno = 0; + if (need_double) { + dv = strtod (c, &endptr); + } + else { + lv = strtoimax (c, &endptr, 10); + } + if (errno == ERANGE) { + *pos = start; + return ERANGE; + } + + /* Now check endptr */ + if (endptr == NULL || ucl_lex_is_atom_end (*endptr) || *endptr == '\0') { + p = endptr; + goto set_obj; + } + + if (endptr < end && endptr != start) { + p = endptr; + switch (*p) { + case 'm': + case 'M': + case 'g': + case 'G': + case 'k': + case 'K': + if (end - p >= 2) { + if (p[1] == 's' || p[1] == 'S') { + /* Milliseconds */ + if (!need_double) { + need_double = true; + dv = lv; + } + is_date = true; + if (p[0] == 'm' || p[0] == 'M') { + dv /= 1000.; + } + else { + dv *= ucl_lex_num_multiplier (*p, false); + } + p += 2; + goto set_obj; + } + else if (number_bytes || (p[1] == 'b' || p[1] == 'B')) { + /* Bytes */ + if (need_double) { + need_double = false; + lv = dv; + } + lv *= ucl_lex_num_multiplier (*p, true); + p += 2; + goto set_obj; + } + else if (ucl_lex_is_atom_end (p[1])) { + if (need_double) { + dv *= ucl_lex_num_multiplier (*p, false); + } + else { + lv *= ucl_lex_num_multiplier (*p, number_bytes); + } + p ++; + goto set_obj; + } + else if (end - p >= 3) { + if (tolower (p[0]) == 'm' && + tolower (p[1]) == 'i' && + tolower (p[2]) == 'n') { + /* Minutes */ + if (!need_double) { + need_double = true; + dv = lv; + } + is_date = true; + dv *= 60.; + p += 3; + goto set_obj; + } + } + } + else { + if (need_double) { + dv *= ucl_lex_num_multiplier (*p, false); + } + else { + lv *= ucl_lex_num_multiplier (*p, number_bytes); + } + p ++; + goto set_obj; + } + break; + case 'S': + case 's': + if (p == end - 1 || ucl_lex_is_atom_end (p[1])) { + if (!need_double) { + need_double = true; + dv = lv; + } + p ++; + is_date = true; + goto set_obj; + } + break; + case 'h': + case 'H': + case 'd': + case 'D': + case 'w': + case 'W': + case 'Y': + case 'y': + if (p == end - 1 || ucl_lex_is_atom_end (p[1])) { + if (!need_double) { + need_double = true; + dv = lv; + } + is_date = true; + dv *= ucl_lex_time_multiplier (*p); + p ++; + goto set_obj; + } + break; + } + } + + *pos = c; + return EINVAL; + + set_obj: + if (allow_double && (need_double || is_date)) { + if (!is_date) { + obj->type = UCL_FLOAT; + } + else { + obj->type = UCL_TIME; + } + obj->value.dv = dv; + } + else { + obj->type = UCL_INT; + obj->value.iv = lv; + } + *pos = p; + return 0; +} + +/** + * Parse possible number + * @param parser + * @param chunk + * @return true if a number has been parsed + */ +static bool +ucl_lex_number (struct ucl_parser *parser, + struct ucl_chunk *chunk, ucl_object_t *obj) +{ + const unsigned char *pos; + int ret; + + ret = ucl_maybe_parse_number (obj, chunk->pos, chunk->end, (const char **)&pos, true, false); + + if (ret == 0) { + chunk->remain -= pos - chunk->pos; + chunk->column += pos - chunk->pos; + chunk->pos = pos; + return true; + } + else if (ret == ERANGE) { + ucl_set_err (chunk, ERANGE, "numeric value out of range", &parser->err); + } + + return false; +} + +/** + * Parse quoted string with possible escapes + * @param parser + * @param chunk + * @return true if a string has been parsed + */ +static bool +ucl_lex_json_string (struct ucl_parser *parser, + struct ucl_chunk *chunk, bool *need_unescape, bool *ucl_escape, bool *var_expand) +{ + const unsigned char *p = chunk->pos; + unsigned char c; + int i; + + while (p < chunk->end) { + c = *p; + if (c < 0x1F) { + /* Unmasked control character */ + if (c == '\n') { + ucl_set_err (chunk, UCL_ESYNTAX, "unexpected newline", &parser->err); + } + else { + ucl_set_err (chunk, UCL_ESYNTAX, "unexpected control character", &parser->err); + } + return false; + } + else if (c == '\\') { + ucl_chunk_skipc (chunk, p); + c = *p; + if (p >= chunk->end) { + ucl_set_err (chunk, UCL_ESYNTAX, "unfinished escape character", &parser->err); + return false; + } + else if (ucl_test_character (c, UCL_CHARACTER_ESCAPE)) { + if (c == 'u') { + ucl_chunk_skipc (chunk, p); + for (i = 0; i < 4 && p < chunk->end; i ++) { + if (!isxdigit (*p)) { + ucl_set_err (chunk, UCL_ESYNTAX, "invalid utf escape", &parser->err); + return false; + } + ucl_chunk_skipc (chunk, p); + } + if (p >= chunk->end) { + ucl_set_err (chunk, UCL_ESYNTAX, "unfinished escape character", &parser->err); + return false; + } + } + else { + ucl_chunk_skipc (chunk, p); + } + } + else { + ucl_set_err (chunk, UCL_ESYNTAX, "invalid escape character", &parser->err); + return false; + } + *need_unescape = true; + *ucl_escape = true; + continue; + } + else if (c == '"') { + ucl_chunk_skipc (chunk, p); + return true; + } + else if (ucl_test_character (c, UCL_CHARACTER_UCL_UNSAFE)) { + *ucl_escape = true; + } + else if (c == '$') { + *var_expand = true; + } + ucl_chunk_skipc (chunk, p); + } + + ucl_set_err (chunk, UCL_ESYNTAX, "no quote at the end of json string", &parser->err); + return false; +} + +/** + * Parse a key in an object + * @param parser + * @param chunk + * @return true if a key has been parsed + */ +static bool +ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_key, bool *end_of_object) +{ + const unsigned char *p, *c = NULL, *end, *t; + const char *key; + bool got_quote = false, got_eq = false, got_semicolon = false, + need_unescape = false, ucl_escape = false, var_expand = false, + got_content = false, got_sep = false; + ucl_object_t *nobj, *tobj; + ucl_hash_t *container; + ssize_t keylen; + + p = chunk->pos; + + if (*p == '.') { + /* It is macro actually */ + ucl_chunk_skipc (chunk, p); + parser->prev_state = parser->state; + parser->state = UCL_STATE_MACRO_NAME; + return true; + } + while (p < chunk->end) { + /* + * A key must start with alpha, number, '/' or '_' and end with space character + */ + if (c == NULL) { + if (chunk->remain >= 2 && ucl_lex_is_comment (p[0], p[1])) { + if (!ucl_skip_comments (parser)) { + return false; + } + p = chunk->pos; + } + else if (ucl_test_character (*p, UCL_CHARACTER_WHITESPACE_UNSAFE)) { + ucl_chunk_skipc (chunk, p); + } + else if (ucl_test_character (*p, UCL_CHARACTER_KEY_START)) { + /* The first symbol */ + c = p; + ucl_chunk_skipc (chunk, p); + got_content = true; + } + else if (*p == '"') { + /* JSON style key */ + c = p + 1; + got_quote = true; + got_content = true; + ucl_chunk_skipc (chunk, p); + } + else if (*p == '}') { + /* We have actually end of an object */ + *end_of_object = true; + return true; + } + else if (*p == '.') { + ucl_chunk_skipc (chunk, p); + parser->prev_state = parser->state; + parser->state = UCL_STATE_MACRO_NAME; + return true; + } + else { + /* Invalid identifier */ + ucl_set_err (chunk, UCL_ESYNTAX, "key must begin with a letter", &parser->err); + return false; + } + } + else { + /* Parse the body of a key */ + if (!got_quote) { + if (ucl_test_character (*p, UCL_CHARACTER_KEY)) { + got_content = true; + ucl_chunk_skipc (chunk, p); + } + else if (ucl_test_character (*p, UCL_CHARACTER_KEY_SEP)) { + end = p; + break; + } + else { + ucl_set_err (chunk, UCL_ESYNTAX, "invalid character in a key", &parser->err); + return false; + } + } + else { + /* We need to parse json like quoted string */ + if (!ucl_lex_json_string (parser, chunk, &need_unescape, &ucl_escape, &var_expand)) { + return false; + } + /* Always escape keys obtained via json */ + end = chunk->pos - 1; + p = chunk->pos; + break; + } + } + } + + if (p >= chunk->end && got_content) { + ucl_set_err (chunk, UCL_ESYNTAX, "unfinished key", &parser->err); + return false; + } + else if (!got_content) { + return true; + } + *end_of_object = false; + /* We are now at the end of the key, need to parse the rest */ + while (p < chunk->end) { + if (ucl_test_character (*p, UCL_CHARACTER_WHITESPACE)) { + ucl_chunk_skipc (chunk, p); + } + else if (*p == '=') { + if (!got_eq && !got_semicolon) { + ucl_chunk_skipc (chunk, p); + got_eq = true; + } + else { + ucl_set_err (chunk, UCL_ESYNTAX, "unexpected '=' character", &parser->err); + return false; + } + } + else if (*p == ':') { + if (!got_eq && !got_semicolon) { + ucl_chunk_skipc (chunk, p); + got_semicolon = true; + } + else { + ucl_set_err (chunk, UCL_ESYNTAX, "unexpected ':' character", &parser->err); + return false; + } + } + else if (chunk->remain >= 2 && ucl_lex_is_comment (p[0], p[1])) { + /* Check for comment */ + if (!ucl_skip_comments (parser)) { + return false; + } + p = chunk->pos; + } + else { + /* Start value */ + break; + } + } + + if (p >= chunk->end && got_content) { + ucl_set_err (chunk, UCL_ESYNTAX, "unfinished key", &parser->err); + return false; + } + + got_sep = got_semicolon || got_eq; + + if (!got_sep) { + /* + * Maybe we have more keys nested, so search for termination character. + * Possible choices: + * 1) key1 key2 ... keyN [:=] value <- we treat that as error + * 2) key1 ... keyN {} or [] <- we treat that as nested objects + * 3) key1 value[;,\n] <- we treat that as linear object + */ + t = p; + *next_key = false; + while (ucl_test_character (*t, UCL_CHARACTER_WHITESPACE)) { + t ++; + } + /* Check first non-space character after a key */ + if (*t != '{' && *t != '[') { + while (t < chunk->end) { + if (*t == ',' || *t == ';' || *t == '\n' || *t == '\r') { + break; + } + else if (*t == '{' || *t == '[') { + *next_key = true; + break; + } + t ++; + } + } + } + + /* Create a new object */ + nobj = ucl_object_new (); + keylen = ucl_copy_or_store_ptr (parser, c, &nobj->trash_stack[UCL_TRASH_KEY], + &key, end - c, need_unescape, parser->flags & UCL_PARSER_KEY_LOWERCASE, false); + if (keylen == -1) { + return false; + } + else if (keylen == 0) { + ucl_set_err (chunk, UCL_ESYNTAX, "empty keys are not allowed", &parser->err); + return false; + } + + container = parser->stack->obj->value.ov; + nobj->key = key; + nobj->keylen = keylen; + tobj = ucl_hash_search_obj (container, nobj); + if (tobj == NULL) { + container = ucl_hash_insert_object (container, nobj); + nobj->prev = nobj; + nobj->next = NULL; + } + else { + DL_APPEND (tobj, nobj); + } + + if (ucl_escape) { + nobj->flags |= UCL_OBJECT_NEED_KEY_ESCAPE; + } + parser->stack->obj->value.ov = container; + + parser->cur_obj = nobj; + + return true; +} + +/** + * Parse a cl string + * @param parser + * @param chunk + * @return true if a key has been parsed + */ +static bool +ucl_parse_string_value (struct ucl_parser *parser, + struct ucl_chunk *chunk, bool *var_expand) +{ + const unsigned char *p; + enum { + UCL_BRACE_ROUND = 0, + UCL_BRACE_SQUARE, + UCL_BRACE_FIGURE + }; + int braces[3][2] = {{0, 0}, {0, 0}, {0, 0}}; + + p = chunk->pos; + + while (p < chunk->end) { + + /* Skip pairs of figure braces */ + if (*p == '{') { + braces[UCL_BRACE_FIGURE][0] ++; + } + else if (*p == '}') { + braces[UCL_BRACE_FIGURE][1] ++; + if (braces[UCL_BRACE_FIGURE][1] == braces[UCL_BRACE_FIGURE][0]) { + /* This is not a termination symbol, continue */ + ucl_chunk_skipc (chunk, p); + continue; + } + } + /* Skip pairs of square braces */ + else if (*p == '[') { + braces[UCL_BRACE_SQUARE][0] ++; + } + else if (*p == ']') { + braces[UCL_BRACE_SQUARE][1] ++; + if (braces[UCL_BRACE_SQUARE][1] == braces[UCL_BRACE_SQUARE][0]) { + /* This is not a termination symbol, continue */ + ucl_chunk_skipc (chunk, p); + continue; + } + } + else if (*p == '$') { + *var_expand = true; + } + + if (ucl_lex_is_atom_end (*p) || (chunk->remain >= 2 && ucl_lex_is_comment (p[0], p[1]))) { + break; + } + ucl_chunk_skipc (chunk, p); + } + + if (p >= chunk->end) { + ucl_set_err (chunk, UCL_ESYNTAX, "unfinished value", &parser->err); + return false; + } + + return true; +} + +/** + * Parse multiline string ending with \n{term}\n + * @param parser + * @param chunk + * @param term + * @param term_len + * @return size of multiline string or 0 in case of error + */ +static int +ucl_parse_multiline_string (struct ucl_parser *parser, + struct ucl_chunk *chunk, const unsigned char *term, + int term_len, unsigned char const **beg, + bool *var_expand) +{ + const unsigned char *p, *c; + bool newline = false; + int len = 0; + + p = chunk->pos; + + c = p; + + while (p < chunk->end) { + if (newline) { + if (chunk->end - p < term_len) { + return 0; + } + else if (memcmp (p, term, term_len) == 0 && (p[term_len] == '\n' || p[term_len] == '\r')) { + len = p - c; + chunk->remain -= term_len; + chunk->pos = p + term_len; + chunk->column = term_len; + *beg = c; + break; + } + } + if (*p == '\n') { + newline = true; + } + else { + if (*p == '$') { + *var_expand = true; + } + newline = false; + } + ucl_chunk_skipc (chunk, p); + } + + return len; +} + +/** + * Handle value data + * @param parser + * @param chunk + * @return + */ +static bool +ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk) +{ + const unsigned char *p, *c; + ucl_object_t *obj = NULL, *t; + unsigned int stripped_spaces; + int str_len; + bool need_unescape = false, ucl_escape = false, var_expand = false; + + p = chunk->pos; + + while (p < chunk->end) { + if (obj == NULL) { + if (parser->stack->obj->type == UCL_ARRAY) { + /* Object must be allocated */ + obj = ucl_object_new (); + t = parser->stack->obj->value.av; + DL_APPEND (t, obj); + parser->cur_obj = obj; + parser->stack->obj->value.av = t; + } + else { + /* Object has been already allocated */ + obj = parser->cur_obj; + } + } + c = p; + switch (*p) { + case '"': + ucl_chunk_skipc (chunk, p); + if (!ucl_lex_json_string (parser, chunk, &need_unescape, &ucl_escape, &var_expand)) { + return false; + } + str_len = chunk->pos - c - 2; + obj->type = UCL_STRING; + if ((str_len = ucl_copy_or_store_ptr (parser, c + 1, &obj->trash_stack[UCL_TRASH_VALUE], + &obj->value.sv, str_len, need_unescape, false, var_expand)) == -1) { + return false; + } + obj->len = str_len; + parser->state = UCL_STATE_AFTER_VALUE; + p = chunk->pos; + return true; + break; + case '{': + /* We have a new object */ + obj = ucl_add_parser_stack (obj, parser, false, parser->stack->level); + + ucl_chunk_skipc (chunk, p); + return true; + break; + case '[': + /* We have a new array */ + obj = ucl_add_parser_stack (obj, parser, true, parser->stack->level); + + ucl_chunk_skipc (chunk, p); + return true; + break; + case '<': + /* We have something like multiline value, which must be <<[A-Z]+\n */ + if (chunk->end - p > 3) { + if (memcmp (p, "<<", 2) == 0) { + p += 2; + /* We allow only uppercase characters in multiline definitions */ + while (p < chunk->end && *p >= 'A' && *p <= 'Z') { + p ++; + } + if (*p =='\n') { + /* Set chunk positions and start multiline parsing */ + c += 2; + chunk->remain -= p - c; + chunk->pos = p + 1; + chunk->column = 0; + chunk->line ++; + if ((str_len = ucl_parse_multiline_string (parser, chunk, c, + p - c, &c, &var_expand)) == 0) { + ucl_set_err (chunk, UCL_ESYNTAX, "unterminated multiline value", &parser->err); + return false; + } + obj->type = UCL_STRING; + if ((str_len = ucl_copy_or_store_ptr (parser, c, &obj->trash_stack[UCL_TRASH_VALUE], + &obj->value.sv, str_len - 1, false, false, var_expand)) == -1) { + return false; + } + obj->len = str_len; + parser->state = UCL_STATE_AFTER_VALUE; + return true; + } + } + } + /* Fallback to ordinary strings */ + default: + /* Skip any spaces and comments */ + if (ucl_test_character (*p, UCL_CHARACTER_WHITESPACE_UNSAFE) || + (chunk->remain >= 2 && ucl_lex_is_comment (p[0], p[1]))) { + while (p < chunk->end && ucl_test_character (*p, UCL_CHARACTER_WHITESPACE_UNSAFE)) { + ucl_chunk_skipc (chunk, p); + } + if (!ucl_skip_comments (parser)) { + return false; + } + p = chunk->pos; + continue; + } + /* Parse atom */ + if (ucl_test_character (*p, UCL_CHARACTER_VALUE_DIGIT_START)) { + if (!ucl_lex_number (parser, chunk, obj)) { + if (parser->state == UCL_STATE_ERROR) { + return false; + } + } + else { + parser->state = UCL_STATE_AFTER_VALUE; + return true; + } + /* Fallback to normal string */ + } + + if (!ucl_parse_string_value (parser, chunk, &var_expand)) { + return false; + } + /* Cut trailing spaces */ + stripped_spaces = 0; + while (ucl_test_character (*(chunk->pos - 1 - stripped_spaces), + UCL_CHARACTER_WHITESPACE)) { + stripped_spaces ++; + } + str_len = chunk->pos - c - stripped_spaces; + if (str_len <= 0) { + ucl_set_err (chunk, 0, "string value must not be empty", &parser->err); + return false; + } + else if (str_len == 4 && memcmp (c, "null", 4) == 0) { + obj->len = 0; + obj->type = UCL_NULL; + } + else if (!ucl_maybe_parse_boolean (obj, c, str_len)) { + obj->type = UCL_STRING; + if ((str_len = ucl_copy_or_store_ptr (parser, c, &obj->trash_stack[UCL_TRASH_VALUE], + &obj->value.sv, str_len, false, false, var_expand)) == -1) { + return false; + } + obj->len = str_len; + } + parser->state = UCL_STATE_AFTER_VALUE; + p = chunk->pos; + + return true; + break; + } + } + + return true; +} + +/** + * Handle after value data + * @param parser + * @param chunk + * @return + */ +static bool +ucl_parse_after_value (struct ucl_parser *parser, struct ucl_chunk *chunk) +{ + const unsigned char *p; + bool got_sep = false; + struct ucl_stack *st; + int last_level; + + p = chunk->pos; + + while (p < chunk->end) { + if (ucl_test_character (*p, UCL_CHARACTER_WHITESPACE)) { + /* Skip whitespaces */ + ucl_chunk_skipc (chunk, p); + } + else if (chunk->remain >= 2 && ucl_lex_is_comment (p[0], p[1])) { + /* Skip comment */ + if (!ucl_skip_comments (parser)) { + return false; + } + /* Treat comment as a separator */ + got_sep = true; + p = chunk->pos; + } + else if (ucl_test_character (*p, UCL_CHARACTER_VALUE_END)) { + if (*p == '}' || *p == ']') { + if (parser->stack == NULL) { + ucl_set_err (chunk, UCL_ESYNTAX, "end of array or object detected without corresponding start", &parser->err); + return false; + } + if ((*p == '}' && parser->stack->obj->type == UCL_OBJECT) || + (*p == ']' && parser->stack->obj->type == UCL_ARRAY)) { + + /* Pop all nested objects from a stack */ + st = parser->stack; + last_level = st->level; + parser->stack = st->next; + UCL_FREE (sizeof (struct ucl_stack), st); + + while (parser->stack != NULL && last_level > 0 && parser->stack->level == last_level) { + st = parser->stack; + parser->stack = st->next; + last_level = st->level; + UCL_FREE (sizeof (struct ucl_stack), st); + } + } + else { + ucl_set_err (chunk, UCL_ESYNTAX, "unexpected terminating symbol detected", &parser->err); + return false; + } + + if (parser->stack == NULL) { + /* Ignore everything after a top object */ + return true; + } + else { + ucl_chunk_skipc (chunk, p); + } + got_sep = true; + } + else { + /* Got a separator */ + got_sep = true; + ucl_chunk_skipc (chunk, p); + } + } + else { + /* Anything else */ + if (!got_sep) { + ucl_set_err (chunk, UCL_ESYNTAX, "delimiter is missing", &parser->err); + return false; + } + return true; + } + } + + return true; +} + +/** + * Handle macro data + * @param parser + * @param chunk + * @return + */ +static bool +ucl_parse_macro_value (struct ucl_parser *parser, + struct ucl_chunk *chunk, struct ucl_macro *macro, + unsigned char const **macro_start, size_t *macro_len) +{ + const unsigned char *p, *c; + bool need_unescape = false, ucl_escape = false, var_expand = false; + + p = chunk->pos; + + switch (*p) { + case '"': + /* We have macro value encoded in quotes */ + c = p; + ucl_chunk_skipc (chunk, p); + if (!ucl_lex_json_string (parser, chunk, &need_unescape, &ucl_escape, &var_expand)) { + return false; + } + + *macro_start = c + 1; + *macro_len = chunk->pos - c - 2; + p = chunk->pos; + break; + case '{': + /* We got a multiline macro body */ + ucl_chunk_skipc (chunk, p); + /* Skip spaces at the beginning */ + while (p < chunk->end) { + if (ucl_test_character (*p, UCL_CHARACTER_WHITESPACE_UNSAFE)) { + ucl_chunk_skipc (chunk, p); + } + else { + break; + } + } + c = p; + while (p < chunk->end) { + if (*p == '}') { + break; + } + ucl_chunk_skipc (chunk, p); + } + *macro_start = c; + *macro_len = p - c; + ucl_chunk_skipc (chunk, p); + break; + default: + /* Macro is not enclosed in quotes or braces */ + c = p; + while (p < chunk->end) { + if (ucl_lex_is_atom_end (*p)) { + break; + } + ucl_chunk_skipc (chunk, p); + } + *macro_start = c; + *macro_len = p - c; + break; + } + + /* We are at the end of a macro */ + /* Skip ';' and space characters and return to previous state */ + while (p < chunk->end) { + if (!ucl_test_character (*p, UCL_CHARACTER_WHITESPACE_UNSAFE) && *p != ';') { + break; + } + ucl_chunk_skipc (chunk, p); + } + return true; +} + +/** + * Handle the main states of rcl parser + * @param parser parser structure + * @param data the pointer to the beginning of a chunk + * @param len the length of a chunk + * @return true if chunk has been parsed and false in case of error + */ +static bool +ucl_state_machine (struct ucl_parser *parser) +{ + ucl_object_t *obj; + struct ucl_chunk *chunk = parser->chunks; + const unsigned char *p, *c = NULL, *macro_start = NULL; + unsigned char *macro_escaped; + size_t macro_len = 0; + struct ucl_macro *macro = NULL; + bool next_key = false, end_of_object = false; + + if (parser->top_obj == NULL) { + if (*chunk->pos == '[') { + obj = ucl_add_parser_stack (NULL, parser, true, 0); + } + else { + obj = ucl_add_parser_stack (NULL, parser, false, 0); + } + parser->top_obj = obj; + parser->cur_obj = obj; + parser->state = UCL_STATE_INIT; + } + + p = chunk->pos; + while (chunk->pos < chunk->end) { + switch (parser->state) { + case UCL_STATE_INIT: + /* + * At the init state we can either go to the parse array or object + * if we got [ or { correspondingly or can just treat new data as + * a key of newly created object + */ + obj = parser->cur_obj; + if (!ucl_skip_comments (parser)) { + parser->prev_state = parser->state; + parser->state = UCL_STATE_ERROR; + return false; + } + else { + p = chunk->pos; + if (*p == '[') { + parser->state = UCL_STATE_VALUE; + ucl_chunk_skipc (chunk, p); + } + else { + parser->state = UCL_STATE_KEY; + if (*p == '{') { + ucl_chunk_skipc (chunk, p); + } + } + } + break; + case UCL_STATE_KEY: + /* Skip any spaces */ + while (p < chunk->end && ucl_test_character (*p, UCL_CHARACTER_WHITESPACE_UNSAFE)) { + ucl_chunk_skipc (chunk, p); + } + if (*p == '}') { + /* We have the end of an object */ + parser->state = UCL_STATE_AFTER_VALUE; + continue; + } + if (!ucl_parse_key (parser, chunk, &next_key, &end_of_object)) { + parser->prev_state = parser->state; + parser->state = UCL_STATE_ERROR; + return false; + } + if (end_of_object) { + p = chunk->pos; + parser->state = UCL_STATE_AFTER_VALUE; + continue; + } + else if (parser->state != UCL_STATE_MACRO_NAME) { + if (next_key && parser->stack->obj->type == UCL_OBJECT) { + /* Parse more keys and nest objects accordingly */ + obj = ucl_add_parser_stack (parser->cur_obj, parser, false, parser->stack->level + 1); + } + else { + parser->state = UCL_STATE_VALUE; + } + } + else { + c = chunk->pos; + } + p = chunk->pos; + break; + case UCL_STATE_VALUE: + /* We need to check what we do have */ + if (!ucl_parse_value (parser, chunk)) { + parser->prev_state = parser->state; + parser->state = UCL_STATE_ERROR; + return false; + } + /* State is set in ucl_parse_value call */ + p = chunk->pos; + break; + case UCL_STATE_AFTER_VALUE: + if (!ucl_parse_after_value (parser, chunk)) { + parser->prev_state = parser->state; + parser->state = UCL_STATE_ERROR; + return false; + } + if (parser->stack != NULL) { + if (parser->stack->obj->type == UCL_OBJECT) { + parser->state = UCL_STATE_KEY; + } + else { + /* Array */ + parser->state = UCL_STATE_VALUE; + } + } + else { + /* Skip everything at the end */ + return true; + } + p = chunk->pos; + break; + case UCL_STATE_MACRO_NAME: + if (!ucl_test_character (*p, UCL_CHARACTER_WHITESPACE_UNSAFE)) { + ucl_chunk_skipc (chunk, p); + } + else if (p - c > 0) { + /* We got macro name */ + HASH_FIND (hh, parser->macroes, c, (p - c), macro); + if (macro == NULL) { + ucl_create_err (&parser->err, "error on line %d at column %d: unknown macro: '%.*s', character: '%c'", + chunk->line, chunk->column, (int)(p - c), c, *chunk->pos); + parser->state = UCL_STATE_ERROR; + return false; + } + /* Now we need to skip all spaces */ + while (p < chunk->end) { + if (!ucl_test_character (*p, UCL_CHARACTER_WHITESPACE_UNSAFE)) { + if (chunk->remain >= 2 && ucl_lex_is_comment (p[0], p[1])) { + /* Skip comment */ + if (!ucl_skip_comments (parser)) { + return false; + } + p = chunk->pos; + } + break; + } + ucl_chunk_skipc (chunk, p); + } + parser->state = UCL_STATE_MACRO; + } + break; + case UCL_STATE_MACRO: + if (!ucl_parse_macro_value (parser, chunk, macro, + ¯o_start, ¯o_len)) { + parser->prev_state = parser->state; + parser->state = UCL_STATE_ERROR; + return false; + } + macro_len = ucl_expand_variable (parser, ¯o_escaped, macro_start, macro_len); + parser->state = parser->prev_state; + if (macro_escaped == NULL) { + if (!macro->handler (macro_start, macro_len, macro->ud)) { + return false; + } + } + else { + if (!macro->handler (macro_escaped, macro_len, macro->ud)) { + UCL_FREE (macro_len + 1, macro_escaped); + return false; + } + UCL_FREE (macro_len + 1, macro_escaped); + } + p = chunk->pos; + break; + default: + /* TODO: add all states */ + ucl_set_err (chunk, UCL_EMACRO, "internal error: parser is in an unknown state", &parser->err); + parser->state = UCL_STATE_ERROR; + return false; + } + } + + return true; +} + +struct ucl_parser* +ucl_parser_new (int flags) +{ + struct ucl_parser *new; + + new = UCL_ALLOC (sizeof (struct ucl_parser)); + memset (new, 0, sizeof (struct ucl_parser)); + + ucl_parser_register_macro (new, "include", ucl_include_handler, new); + ucl_parser_register_macro (new, "includes", ucl_includes_handler, new); + + new->flags = flags; + + /* Initial assumption about filevars */ + ucl_parser_set_filevars (new, NULL, false); + + return new; +} + + +void +ucl_parser_register_macro (struct ucl_parser *parser, const char *macro, + ucl_macro_handler handler, void* ud) +{ + struct ucl_macro *new; + + new = UCL_ALLOC (sizeof (struct ucl_macro)); + memset (new, 0, sizeof (struct ucl_macro)); + new->handler = handler; + new->name = strdup (macro); + new->ud = ud; + HASH_ADD_KEYPTR (hh, parser->macroes, new->name, strlen (new->name), new); +} + +void +ucl_parser_register_variable (struct ucl_parser *parser, const char *var, + const char *value) +{ + struct ucl_variable *new = NULL, *cur; + + if (var == NULL) { + return; + } + + /* Find whether a variable already exists */ + LL_FOREACH (parser->variables, cur) { + if (strcmp (cur->var, var) == 0) { + new = cur; + break; + } + } + + if (value == NULL) { + + if (new != NULL) { + /* Remove variable */ + LL_DELETE (parser->variables, new); + free (new->var); + free (new->value); + UCL_FREE (sizeof (struct ucl_variable), new); + } + else { + /* Do nothing */ + return; + } + } + else { + if (new == NULL) { + new = UCL_ALLOC (sizeof (struct ucl_variable)); + memset (new, 0, sizeof (struct ucl_variable)); + new->var = strdup (var); + new->var_len = strlen (var); + new->value = strdup (value); + new->value_len = strlen (value); + + LL_PREPEND (parser->variables, new); + } + else { + free (new->value); + new->value = strdup (value); + new->value_len = strlen (value); + } + } +} + +bool +ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, + size_t len) +{ + struct ucl_chunk *chunk; + + if (parser->state != UCL_STATE_ERROR) { + chunk = UCL_ALLOC (sizeof (struct ucl_chunk)); + chunk->begin = data; + chunk->remain = len; + chunk->pos = chunk->begin; + chunk->end = chunk->begin + len; + chunk->line = 1; + chunk->column = 0; + LL_PREPEND (parser->chunks, chunk); + parser->recursion ++; + if (parser->recursion > UCL_MAX_RECURSION) { + ucl_create_err (&parser->err, "maximum include nesting limit is reached: %d", + parser->recursion); + return false; + } + return ucl_state_machine (parser); + } + + ucl_create_err (&parser->err, "a parser is in an invalid state"); + + return false; +} Property changes on: contrib/libucl/src/ucl_parser.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: contrib/libucl/src/ucl_util.c =================================================================== --- contrib/libucl/src/ucl_util.c (revision 0) +++ contrib/libucl/src/ucl_util.c (working copy) @@ -0,0 +1,1133 @@ +/* Copyright (c) 2013, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ucl.h" +#include "ucl_internal.h" +#include "ucl_chartable.h" + +#include /* For dirname */ + +#ifdef HAVE_OPENSSL +#include +#include +#include +#include +#include +#endif + +/** + * @file rcl_util.c + * Utilities for rcl parsing + */ + + +static void +ucl_object_free_internal (ucl_object_t *obj, bool allow_rec) +{ + ucl_object_t *sub, *tmp; + + while (obj != NULL) { + if (obj->trash_stack[UCL_TRASH_KEY] != NULL) { + UCL_FREE (obj->hh.keylen, obj->trash_stack[UCL_TRASH_KEY]); + } + if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) { + UCL_FREE (obj->len, obj->trash_stack[UCL_TRASH_VALUE]); + } + + if (obj->type == UCL_ARRAY) { + sub = obj->value.av; + while (sub != NULL) { + tmp = sub->next; + ucl_object_free_internal (sub, false); + sub = tmp; + } + } + else if (obj->type == UCL_OBJECT) { + if (obj->value.ov != NULL) { + ucl_hash_destroy (obj->value.ov, (ucl_hash_free_func *)ucl_object_unref); + } + } + tmp = obj->next; + UCL_FREE (sizeof (ucl_object_t), obj); + obj = tmp; + + if (!allow_rec) { + break; + } + } +} + +void +ucl_object_free (ucl_object_t *obj) +{ + ucl_object_free_internal (obj, true); +} + +size_t +ucl_unescape_json_string (char *str, size_t len) +{ + char *t = str, *h = str; + int i, uval; + + /* t is target (tortoise), h is source (hare) */ + + while (len) { + if (*h == '\\') { + h ++; + switch (*h) { + case 'n': + *t++ = '\n'; + break; + case 'r': + *t++ = '\r'; + break; + case 'b': + *t++ = '\b'; + break; + case 't': + *t++ = '\t'; + break; + case 'f': + *t++ = '\f'; + break; + case '\\': + *t++ = '\\'; + break; + case '"': + *t++ = '"'; + break; + case 'u': + /* Unicode escape */ + uval = 0; + for (i = 0; i < 4; i++) { + uval <<= 4; + if (isdigit (h[i])) { + uval += h[i] - '0'; + } + else if (h[i] >= 'a' && h[i] <= 'f') { + uval += h[i] - 'a' + 10; + } + else if (h[i] >= 'A' && h[i] <= 'F') { + uval += h[i] - 'A' + 10; + } + } + h += 3; + len -= 3; + /* Encode */ + if(uval < 0x80) { + t[0] = (char)uval; + t ++; + } + else if(uval < 0x800) { + t[0] = 0xC0 + ((uval & 0x7C0) >> 6); + t[1] = 0x80 + ((uval & 0x03F)); + t += 2; + } + else if(uval < 0x10000) { + t[0] = 0xE0 + ((uval & 0xF000) >> 12); + t[1] = 0x80 + ((uval & 0x0FC0) >> 6); + t[2] = 0x80 + ((uval & 0x003F)); + t += 3; + } + else if(uval <= 0x10FFFF) { + t[0] = 0xF0 + ((uval & 0x1C0000) >> 18); + t[1] = 0x80 + ((uval & 0x03F000) >> 12); + t[2] = 0x80 + ((uval & 0x000FC0) >> 6); + t[3] = 0x80 + ((uval & 0x00003F)); + t += 4; + } + else { + *t++ = '?'; + } + break; + default: + *t++ = '?'; + break; + } + h ++; + len --; + } + else { + *t++ = *h++; + } + len --; + } + *t = '\0'; + + return (t - str); +} + +char * +ucl_copy_key_trash (ucl_object_t *obj) +{ + if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->key != NULL) { + obj->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1); + if (obj->trash_stack[UCL_TRASH_KEY] != NULL) { + memcpy (obj->trash_stack[UCL_TRASH_KEY], obj->key, obj->keylen); + obj->trash_stack[UCL_TRASH_KEY][obj->keylen] = '\0'; + } + obj->key = obj->trash_stack[UCL_TRASH_KEY]; + obj->flags |= UCL_OBJECT_ALLOCATED_KEY; + } + + return obj->trash_stack[UCL_TRASH_KEY]; +} + +char * +ucl_copy_value_trash (ucl_object_t *obj) +{ + if (obj->trash_stack[UCL_TRASH_VALUE] == NULL) { + if (obj->type == UCL_STRING) { + /* Special case for strings */ + obj->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1); + if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) { + memcpy (obj->trash_stack[UCL_TRASH_VALUE], obj->value.sv, obj->len); + obj->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0'; + obj->value.sv = obj->trash_stack[UCL_TRASH_VALUE]; + } + } + else { + /* Just emit value in json notation */ + obj->trash_stack[UCL_TRASH_VALUE] = ucl_object_emit (obj, + UCL_EMIT_JSON_COMPACT); + obj->len = strlen (obj->trash_stack[UCL_TRASH_VALUE]); + } + obj->flags |= UCL_OBJECT_ALLOCATED_VALUE; + } + return obj->trash_stack[UCL_TRASH_VALUE]; +} + +ucl_object_t* +ucl_parser_get_object (struct ucl_parser *parser) +{ + if (parser->state != UCL_STATE_ERROR) { + return ucl_object_ref (parser->top_obj); + } + + return NULL; +} + +void +ucl_parser_free (struct ucl_parser *parser) +{ + struct ucl_stack *stack, *stmp; + struct ucl_macro *macro, *mtmp; + struct ucl_chunk *chunk, *ctmp; + struct ucl_pubkey *key, *ktmp; + struct ucl_variable *var, *vtmp; + + if (parser->top_obj != NULL) { + ucl_object_unref (parser->top_obj); + } + + LL_FOREACH_SAFE (parser->stack, stack, stmp) { + free (stack); + } + HASH_ITER (hh, parser->macroes, macro, mtmp) { + free (macro->name); + HASH_DEL (parser->macroes, macro); + UCL_FREE (sizeof (struct ucl_macro), macro); + } + LL_FOREACH_SAFE (parser->chunks, chunk, ctmp) { + UCL_FREE (sizeof (struct ucl_chunk), chunk); + } + LL_FOREACH_SAFE (parser->keys, key, ktmp) { + UCL_FREE (sizeof (struct ucl_pubkey), key); + } + LL_FOREACH_SAFE (parser->variables, var, vtmp) { + free (var->value); + free (var->var); + UCL_FREE (sizeof (struct ucl_variable), var); + } + + if (parser->err != NULL) { + utstring_free(parser->err); + } + + UCL_FREE (sizeof (struct ucl_parser), parser); +} + +const char * +ucl_parser_get_error(struct ucl_parser *parser) +{ + if (parser->err == NULL) + return NULL; + + return utstring_body(parser->err); +} + +bool +ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len) +{ +#ifndef HAVE_OPENSSL + ucl_create_err (&parser->err, "cannot check signatures without openssl"); + return false; +#else +# if (OPENSSL_VERSION_NUMBER < 0x10000000L) + ucl_create_err (&parser->err, "cannot check signatures, openssl version is unsupported"); + return EXIT_FAILURE; +# else + struct ucl_pubkey *nkey; + BIO *mem; + + mem = BIO_new_mem_buf ((void *)key, len); + nkey = UCL_ALLOC (sizeof (struct ucl_pubkey)); + nkey->key = PEM_read_bio_PUBKEY (mem, &nkey->key, NULL, NULL); + BIO_free (mem); + if (nkey->key == NULL) { + UCL_FREE (sizeof (struct ucl_pubkey), nkey); + ucl_create_err (&parser->err, "%s", + ERR_error_string (ERR_get_error (), NULL)); + return false; + } + LL_PREPEND (parser->keys, nkey); +# endif +#endif + return true; +} + +#ifdef CURL_FOUND +struct ucl_curl_cbdata { + unsigned char *buf; + size_t buflen; +}; + +static size_t +ucl_curl_write_callback (void* contents, size_t size, size_t nmemb, void* ud) +{ + struct ucl_curl_cbdata *cbdata = ud; + size_t realsize = size * nmemb; + + cbdata->buf = realloc (cbdata->buf, cbdata->buflen + realsize + 1); + if (cbdata->buf == NULL) { + return 0; + } + + memcpy (&(cbdata->buf[cbdata->buflen]), contents, realsize); + cbdata->buflen += realsize; + cbdata->buf[cbdata->buflen] = 0; + + return realsize; +} +#endif + +/** + * Fetch a url and save results to the memory buffer + * @param url url to fetch + * @param len length of url + * @param buf target buffer + * @param buflen target length + * @return + */ +static bool +ucl_fetch_url (const unsigned char *url, unsigned char **buf, size_t *buflen, UT_string **err) +{ + +#ifdef HAVE_FETCH_H + struct url *fetch_url; + struct url_stat us; + FILE *in; + + fetch_url = fetchParseURL (url); + if (fetch_url == NULL) { + ucl_create_err (err, "invalid URL %s: %s", + url, strerror (errno)); + return false; + } + if ((in = fetchXGet (fetch_url, &us, "")) == NULL) { + ucl_create_err (err, "cannot fetch URL %s: %s", + url, strerror (errno)); + fetchFreeURL (fetch_url); + return false; + } + + *buflen = us.size; + *buf = malloc (*buflen); + if (*buf == NULL) { + ucl_create_err (err, "cannot allocate buffer for URL %s: %s", + url, strerror (errno)); + fclose (in); + fetchFreeURL (fetch_url); + return false; + } + + if (fread (*buf, *buflen, 1, in) != 1) { + ucl_create_err (err, "cannot read URL %s: %s", + url, strerror (errno)); + fclose (in); + fetchFreeURL (fetch_url); + return false; + } + + fetchFreeURL (fetch_url); + return true; +#elif defined(CURL_FOUND) + CURL *curl; + int r; + struct ucl_curl_cbdata cbdata; + + curl = curl_easy_init (); + if (curl == NULL) { + ucl_create_err (err, "CURL interface is broken"); + return false; + } + if ((r = curl_easy_setopt (curl, CURLOPT_URL, url)) != CURLE_OK) { + ucl_create_err (err, "invalid URL %s: %s", + url, curl_easy_strerror (r)); + curl_easy_cleanup (curl); + return false; + } + curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ucl_curl_write_callback); + cbdata.buf = *buf; + cbdata.buflen = *buflen; + curl_easy_setopt (curl, CURLOPT_WRITEDATA, &cbdata); + + if ((r = curl_easy_perform (curl)) != CURLE_OK) { + ucl_create_err (err, "error fetching URL %s: %s", + url, curl_easy_strerror (r)); + curl_easy_cleanup (curl); + if (cbdata.buf) { + free (cbdata.buf); + } + return false; + } + *buf = cbdata.buf; + *buflen = cbdata.buflen; + + return true; +#else + ucl_create_err (err, "URL support is disabled"); + return false; +#endif +} + +/** + * Fetch a file and save results to the memory buffer + * @param filename filename to fetch + * @param len length of filename + * @param buf target buffer + * @param buflen target length + * @return + */ +static bool +ucl_fetch_file (const unsigned char *filename, unsigned char **buf, size_t *buflen, UT_string **err) +{ + int fd; + struct stat st; + + if (stat (filename, &st) == -1 || !S_ISREG (st.st_mode)) { + ucl_create_err (err, "cannot stat file %s: %s", + filename, strerror (errno)); + return false; + } + if (st.st_size == 0) { + /* Do not map empty files */ + *buf = ""; + *buflen = 0; + } + else { + if ((fd = open (filename, O_RDONLY)) == -1) { + ucl_create_err (err, "cannot open file %s: %s", + filename, strerror (errno)); + return false; + } + if ((*buf = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { + close (fd); + ucl_create_err (err, "cannot mmap file %s: %s", + filename, strerror (errno)); + return false; + } + *buflen = st.st_size; + close (fd); + } + + return true; +} + + +#if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L) +static inline bool +ucl_sig_check (const unsigned char *data, size_t datalen, + const unsigned char *sig, size_t siglen, struct ucl_parser *parser) +{ + struct ucl_pubkey *key; + char dig[EVP_MAX_MD_SIZE]; + unsigned int diglen; + EVP_PKEY_CTX *key_ctx; + EVP_MD_CTX *sign_ctx = NULL; + + sign_ctx = EVP_MD_CTX_create (); + + LL_FOREACH (parser->keys, key) { + key_ctx = EVP_PKEY_CTX_new (key->key, NULL); + if (key_ctx != NULL) { + if (EVP_PKEY_verify_init (key_ctx) <= 0) { + EVP_PKEY_CTX_free (key_ctx); + continue; + } + if (EVP_PKEY_CTX_set_rsa_padding (key_ctx, RSA_PKCS1_PADDING) <= 0) { + EVP_PKEY_CTX_free (key_ctx); + continue; + } + if (EVP_PKEY_CTX_set_signature_md (key_ctx, EVP_sha256 ()) <= 0) { + EVP_PKEY_CTX_free (key_ctx); + continue; + } + EVP_DigestInit (sign_ctx, EVP_sha256 ()); + EVP_DigestUpdate (sign_ctx, data, datalen); + EVP_DigestFinal (sign_ctx, dig, &diglen); + + if (EVP_PKEY_verify (key_ctx, sig, siglen, dig, diglen) == 1) { + EVP_MD_CTX_destroy (sign_ctx); + EVP_PKEY_CTX_free (key_ctx); + return true; + } + + EVP_PKEY_CTX_free (key_ctx); + } + } + + EVP_MD_CTX_destroy (sign_ctx); + + return false; +} +#endif + +/** + * Include an url to configuration + * @param data + * @param len + * @param parser + * @param err + * @return + */ +static bool +ucl_include_url (const unsigned char *data, size_t len, + struct ucl_parser *parser, bool check_signature) +{ + + bool res; + unsigned char *buf = NULL; + size_t buflen = 0; + struct ucl_chunk *chunk; + char urlbuf[PATH_MAX]; + int prev_state; + + snprintf (urlbuf, sizeof (urlbuf), "%.*s", (int)len, data); + + if (!ucl_fetch_url (urlbuf, &buf, &buflen, &parser->err)) { + return false; + } + + if (check_signature) { +#if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L) + unsigned char *sigbuf = NULL; + size_t siglen = 0; + /* We need to check signature first */ + snprintf (urlbuf, sizeof (urlbuf), "%.*s.sig", (int)len, data); + if (!ucl_fetch_file (urlbuf, &sigbuf, &siglen, &parser->err)) { + return false; + } + if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) { + ucl_create_err (&parser->err, "cannot verify url %s: %s", + urlbuf, + ERR_error_string (ERR_get_error (), NULL)); + if (siglen > 0) { + munmap (sigbuf, siglen); + } + return false; + } + if (siglen > 0) { + munmap (sigbuf, siglen); + } +#endif + } + + prev_state = parser->state; + parser->state = UCL_STATE_INIT; + + res = ucl_parser_add_chunk (parser, buf, buflen); + if (res == true) { + /* Remove chunk from the stack */ + chunk = parser->chunks; + if (chunk != NULL) { + parser->chunks = chunk->next; + UCL_FREE (sizeof (struct ucl_chunk), chunk); + } + } + + parser->state = prev_state; + free (buf); + + return res; +} + +/** + * Include a file to configuration + * @param data + * @param len + * @param parser + * @param err + * @return + */ +static bool +ucl_include_file (const unsigned char *data, size_t len, + struct ucl_parser *parser, bool check_signature) +{ + bool res; + struct ucl_chunk *chunk; + unsigned char *buf = NULL; + size_t buflen; + char filebuf[PATH_MAX], realbuf[PATH_MAX]; + int prev_state; + + snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data); + if (realpath (filebuf, realbuf) == NULL) { + ucl_create_err (&parser->err, "cannot open file %s: %s", + filebuf, + strerror (errno)); + return false; + } + + if (!ucl_fetch_file (realbuf, &buf, &buflen, &parser->err)) { + return false; + } + + if (check_signature) { +#if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L) + unsigned char *sigbuf = NULL; + size_t siglen = 0; + /* We need to check signature first */ + snprintf (filebuf, sizeof (filebuf), "%s.sig", realbuf); + if (!ucl_fetch_file (filebuf, &sigbuf, &siglen, &parser->err)) { + return false; + } + if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) { + ucl_create_err (&parser->err, "cannot verify file %s: %s", + filebuf, + ERR_error_string (ERR_get_error (), NULL)); + if (siglen > 0) { + munmap (sigbuf, siglen); + } + return false; + } + if (siglen > 0) { + munmap (sigbuf, siglen); + } +#endif + } + + ucl_parser_set_filevars (parser, realbuf, false); + + prev_state = parser->state; + parser->state = UCL_STATE_INIT; + + res = ucl_parser_add_chunk (parser, buf, buflen); + if (res == true) { + /* Remove chunk from the stack */ + chunk = parser->chunks; + if (chunk != NULL) { + parser->chunks = chunk->next; + UCL_FREE (sizeof (struct ucl_chunk), chunk); + } + } + + parser->state = prev_state; + + if (buflen > 0) { + munmap (buf, buflen); + } + + return res; +} + +/** + * Handle include macro + * @param data include data + * @param len length of data + * @param ud user data + * @param err error ptr + * @return + */ +bool +ucl_include_handler (const unsigned char *data, size_t len, void* ud) +{ + struct ucl_parser *parser = ud; + + if (*data == '/' || *data == '.') { + /* Try to load a file */ + return ucl_include_file (data, len, parser, false); + } + + return ucl_include_url (data, len, parser, false); +} + +/** + * Handle includes macro + * @param data include data + * @param len length of data + * @param ud user data + * @param err error ptr + * @return + */ +bool +ucl_includes_handler (const unsigned char *data, size_t len, void* ud) +{ + struct ucl_parser *parser = ud; + + if (*data == '/' || *data == '.') { + /* Try to load a file */ + return ucl_include_file (data, len, parser, true); + } + + return ucl_include_url (data, len, parser, true); +} + +bool +ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand) +{ + char realbuf[PATH_MAX], *curdir; + + if (filename != NULL) { + if (need_expand) { + if (realpath (filename, realbuf) == NULL) { + return false; + } + } + else { + ucl_strlcpy (realbuf, filename, sizeof (realbuf)); + } + + /* Define variables */ + ucl_parser_register_variable (parser, "FILENAME", realbuf); + curdir = dirname (realbuf); + ucl_parser_register_variable (parser, "CURDIR", curdir); + } + else { + /* Set everything from the current dir */ + curdir = getcwd (realbuf, sizeof (realbuf)); + ucl_parser_register_variable (parser, "FILENAME", "undef"); + ucl_parser_register_variable (parser, "CURDIR", curdir); + } + + return true; +} + +bool +ucl_parser_add_file (struct ucl_parser *parser, const char *filename) +{ + unsigned char *buf; + size_t len; + bool ret; + char realbuf[PATH_MAX]; + + if (realpath (filename, realbuf) == NULL) { + ucl_create_err (&parser->err, "cannot open file %s: %s", + filename, + strerror (errno)); + return false; + } + + if (!ucl_fetch_file (realbuf, &buf, &len, &parser->err)) { + return false; + } + + ucl_parser_set_filevars (parser, realbuf, false); + ret = ucl_parser_add_chunk (parser, buf, len); + + if (len > 0) { + munmap (buf, len); + } + + return ret; +} + +size_t +ucl_strlcpy (char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0) { + while (--n != 0) { + if ((*d++ = *s++) == '\0') { + break; + } + } + } + + if (n == 0 && siz != 0) { + *d = '\0'; + } + + return (s - src - 1); /* count does not include NUL */ +} + +size_t +ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz) +{ + memcpy (dst, src, siz - 1); + dst[siz - 1] = '\0'; + + return siz - 1; +} + +size_t +ucl_strlcpy_tolower (char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0) { + while (--n != 0) { + if ((*d++ = tolower (*s++)) == '\0') { + break; + } + } + } + + if (n == 0 && siz != 0) { + *d = '\0'; + } + + return (s - src); /* count does not include NUL */ +} + +ucl_object_t * +ucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags flags) +{ + ucl_object_t *obj; + const char *start, *end, *p, *pos; + char *dst, *d; + size_t escaped_len; + + if (str == NULL) { + return NULL; + } + + obj = ucl_object_new (); + if (obj) { + if (len == 0) { + len = strlen (str); + } + if (flags & UCL_STRING_TRIM) { + /* Skip leading spaces */ + for (start = str; (size_t)(start - str) < len; start ++) { + if (!ucl_test_character (*start, UCL_CHARACTER_WHITESPACE_UNSAFE)) { + break; + } + } + /* Skip trailing spaces */ + for (end = str + len - 1; end > start; end --) { + if (!ucl_test_character (*end, UCL_CHARACTER_WHITESPACE_UNSAFE)) { + break; + } + } + end ++; + } + else { + start = str; + end = str + len; + } + + obj->type = UCL_STRING; + if (flags & UCL_STRING_ESCAPE) { + for (p = start, escaped_len = 0; p < end; p ++, escaped_len ++) { + if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) { + escaped_len ++; + } + } + dst = malloc (escaped_len + 1); + if (dst != NULL) { + for (p = start, d = dst; p < end; p ++, d ++) { + if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) { + switch (*p) { + case '\n': + *d++ = '\\'; + *d = 'n'; + break; + case '\r': + *d++ = '\\'; + *d = 'r'; + break; + case '\b': + *d++ = '\\'; + *d = 'b'; + break; + case '\t': + *d++ = '\\'; + *d = 't'; + break; + case '\f': + *d++ = '\\'; + *d = 'f'; + break; + case '\\': + *d++ = '\\'; + *d = '\\'; + break; + case '"': + *d++ = '\\'; + *d = '"'; + break; + } + } + else { + *d = *p; + } + } + *d = '\0'; + obj->value.sv = dst; + obj->trash_stack[UCL_TRASH_VALUE] = dst; + obj->len = escaped_len; + } + } + else { + dst = malloc (end - start + 1); + if (dst != NULL) { + ucl_strlcpy_unsafe (dst, start, end - start + 1); + obj->value.sv = dst; + obj->trash_stack[UCL_TRASH_VALUE] = dst; + obj->len = end - start; + } + } + if ((flags & UCL_STRING_PARSE) && dst != NULL) { + /* Parse what we have */ + if (flags & UCL_STRING_PARSE_BOOLEAN) { + if (!ucl_maybe_parse_boolean (obj, dst, obj->len) && (flags & UCL_STRING_PARSE_NUMBER)) { + ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos, + flags & UCL_STRING_PARSE_DOUBLE, + flags & UCL_STRING_PARSE_BYTES); + } + } + else { + ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos, + flags & UCL_STRING_PARSE_DOUBLE, + flags & UCL_STRING_PARSE_BYTES); + } + } + } + + return obj; +} + +static ucl_object_t * +ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt, + const char *key, size_t keylen, bool copy_key, bool merge, bool replace) +{ + ucl_object_t *found, *cur; + ucl_object_iter_t it = NULL; + const char *p; + + if (elt == NULL || key == NULL) { + return NULL; + } + + if (top == NULL) { + top = ucl_object_new (); + top->type = UCL_OBJECT; + } + + if (top->type != UCL_OBJECT) { + /* It is possible to convert NULL type to an object */ + if (top->type == UCL_NULL) { + top->type = UCL_OBJECT; + } + else { + /* Refuse converting of other object types */ + return top; + } + } + + if (top->value.ov == NULL) { + top->value.ov = ucl_hash_create (); + } + + if (keylen == 0) { + keylen = strlen (key); + } + + for (p = key; p < key + keylen; p ++) { + if (ucl_test_character (*p, UCL_CHARACTER_UCL_UNSAFE)) { + elt->flags |= UCL_OBJECT_NEED_KEY_ESCAPE; + break; + } + } + + elt->key = key; + elt->keylen = keylen; + + if (copy_key) { + ucl_copy_key_trash (elt); + } + + found = ucl_hash_search_obj (top->value.ov, elt); + + if (!found) { + top->value.ov = ucl_hash_insert_object (top->value.ov, elt); + DL_APPEND (found, elt); + } + else { + if (replace) { + ucl_hash_delete (top->value.ov, found); + ucl_object_unref (found); + top->value.ov = ucl_hash_insert_object (top->value.ov, elt); + found = NULL; + DL_APPEND (found, elt); + } + else if (merge) { + if (found->type != UCL_OBJECT && elt->type == UCL_OBJECT) { + /* Insert old elt to new one */ + elt = ucl_object_insert_key_common (elt, found, found->key, found->keylen, copy_key, false, false); + ucl_hash_delete (top->value.ov, found); + top->value.ov = ucl_hash_insert_object (top->value.ov, elt); + } + else if (found->type == UCL_OBJECT && elt->type != UCL_OBJECT) { + /* Insert new to old */ + found = ucl_object_insert_key_common (found, elt, elt->key, elt->keylen, copy_key, false, false); + } + else if (found->type == UCL_OBJECT && elt->type == UCL_OBJECT) { + /* Mix two hashes */ + while ((cur = ucl_iterate_object (elt, &it, true)) != NULL) { + ucl_object_ref (cur); + found = ucl_object_insert_key_common (found, cur, cur->key, cur->keylen, copy_key, false, false); + } + ucl_object_unref (elt); + } + else { + /* Just make a list of scalars */ + DL_APPEND (found, elt); + } + } + else { + DL_APPEND (found, elt); + } + } + + return top; +} + +ucl_object_t * +ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, + const char *key, size_t keylen, bool copy_key) +{ + return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, false); +} + +ucl_object_t * +ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt, + const char *key, size_t keylen, bool copy_key) +{ + return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, true, false); +} + +ucl_object_t * +ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt, + const char *key, size_t keylen, bool copy_key) +{ + return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, true); +} + +ucl_object_t * +ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen) +{ + ucl_object_t *ret, srch; + + if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) { + return NULL; + } + + srch.key = key; + srch.keylen = klen; + ret = ucl_hash_search_obj (obj->value.ov, &srch); + + return ret; +} + +ucl_object_t * +ucl_object_find_key (ucl_object_t *obj, const char *key) +{ + size_t klen; + ucl_object_t *ret, srch; + + if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) { + return NULL; + } + + klen = strlen (key); + srch.key = key; + srch.keylen = klen; + ret = ucl_hash_search_obj (obj->value.ov, &srch); + + return ret; +} + +ucl_object_t* +ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values) +{ + ucl_object_t *elt; + + if (expand_values) { + switch (obj->type) { + case UCL_OBJECT: + return (ucl_object_t*)ucl_hash_iterate (obj->value.ov, iter); + break; + case UCL_ARRAY: + elt = *iter; + if (elt == NULL) { + elt = obj->value.av; + if (elt == NULL) { + return NULL; + } + } + else if (elt == obj->value.av) { + return NULL; + } + *iter = elt->next ? elt->next : obj->value.av; + return elt; + default: + /* Go to linear iteration */ + break; + } + } + /* Treat everything as a linear list */ + elt = *iter; + if (elt == NULL) { + elt = obj; + if (elt == NULL) { + return NULL; + } + } + else if (elt == obj) { + return NULL; + } + *iter = elt->next ? elt->next : obj; + return elt; + + /* Not reached */ + return NULL; +} Property changes on: contrib/libucl/src/ucl_util.c ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/src/xxhash.c =================================================================== --- contrib/libucl/src/xxhash.c (revision 0) +++ contrib/libucl/src/xxhash.c (working copy) @@ -0,0 +1,475 @@ +/* +xxHash - Fast Hash algorithm +Copyright (C) 2012-2013, Yann Collet. +BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +You can contact the author at : +- xxHash source repository : http://code.google.com/p/xxhash/ +*/ + + +//************************************** +// Tuning parameters +//************************************** +// Unaligned memory access is automatically enabled for "common" CPU, such as x86. +// For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected. +// If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance. +// You can also enable this parameter if you know your input data will always be aligned (boundaries of 4, for U32). +#if defined(__ARM_FEATURE_UNALIGNED) || defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) +# define XXH_USE_UNALIGNED_ACCESS 1 +#endif + +// XXH_ACCEPT_NULL_INPUT_POINTER : +// If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer. +// When this option is enabled, xxHash output for null input pointers will be the same as a null-length input. +// This option has a very small performance cost (only measurable on small inputs). +// By default, this option is disabled. To enable it, uncomment below define : +//#define XXH_ACCEPT_NULL_INPUT_POINTER 1 + +// XXH_FORCE_NATIVE_FORMAT : +// By default, xxHash library provides endian-independant Hash values, based on little-endian convention. +// Results are therefore identical for little-endian and big-endian CPU. +// This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format. +// Should endian-independance be of no importance for your application, you may set the #define below to 1. +// It will improve speed for Big-endian CPU. +// This option has no impact on Little_Endian CPU. +#define XXH_FORCE_NATIVE_FORMAT 0 + + +//************************************** +// Compiler Specific Options +//************************************** +// Disable some Visual warning messages +#ifdef _MSC_VER // Visual Studio +# pragma warning(disable : 4127) // disable: C4127: conditional expression is constant +#endif + +#ifdef _MSC_VER // Visual Studio +# define forceinline static __forceinline +#else +# ifdef __GNUC__ +# define forceinline static inline __attribute__((always_inline)) +# else +# define forceinline static inline +# endif +#endif + + +//************************************** +// Includes & Memory related functions +//************************************** +#include "xxhash.h" +// Modify the local functions below should you wish to use some other memory related routines +// for malloc(), free() +#include +forceinline void* XXH_malloc(size_t s) { return malloc(s); } +forceinline void XXH_free (void* p) { free(p); } +// for memcpy() +#include +forceinline void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); } + + +//************************************** +// Basic Types +//************************************** +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L // C99 +# include + typedef uint8_t BYTE; + typedef uint16_t U16; + typedef uint32_t U32; + typedef int32_t S32; + typedef uint64_t U64; +#else + typedef unsigned char BYTE; + typedef unsigned short U16; + typedef unsigned int U32; + typedef signed int S32; + typedef unsigned long long U64; +#endif + +#if defined(__GNUC__) && !defined(XXH_USE_UNALIGNED_ACCESS) +# define _PACKED __attribute__ ((packed)) +#else +# define _PACKED +#endif + +#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__) +# ifdef __IBMC__ +# pragma pack(1) +# else +# pragma pack(push, 1) +# endif +#endif + +typedef struct _U32_S { U32 v; } _PACKED U32_S; + +#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__) +# pragma pack(pop) +#endif + +#define A32(x) (((U32_S *)(x))->v) + + +//*************************************** +// Compiler-specific Functions and Macros +//*************************************** +#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) + +// Note : although _rotl exists for minGW (GCC under windows), performance seems poor +#if defined(_MSC_VER) +# define XXH_rotl32(x,r) _rotl(x,r) +#else +# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r))) +#endif + +#if defined(_MSC_VER) // Visual Studio +# define XXH_swap32 _byteswap_ulong +#elif GCC_VERSION >= 403 +# define XXH_swap32 __builtin_bswap32 +#else +static inline U32 XXH_swap32 (U32 x) { + return ((x << 24) & 0xff000000 ) | + ((x << 8) & 0x00ff0000 ) | + ((x >> 8) & 0x0000ff00 ) | + ((x >> 24) & 0x000000ff );} +#endif + + +//************************************** +// Constants +//************************************** +#define PRIME32_1 2654435761U +#define PRIME32_2 2246822519U +#define PRIME32_3 3266489917U +#define PRIME32_4 668265263U +#define PRIME32_5 374761393U + + +//************************************** +// Architecture Macros +//************************************** +typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess; +#ifndef XXH_CPU_LITTLE_ENDIAN // It is possible to define XXH_CPU_LITTLE_ENDIAN externally, for example using a compiler switch + static const int one = 1; +# define XXH_CPU_LITTLE_ENDIAN (*(char*)(&one)) +#endif + + +//************************************** +// Macros +//************************************** +#define XXH_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(!!(c)) }; } // use only *after* variable declarations + + +//**************************** +// Memory reads +//**************************** +typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment; + +forceinline U32 XXH_readLE32_align(const U32* ptr, XXH_endianess endian, XXH_alignment align) +{ + if (align==XXH_unaligned) + return endian==XXH_littleEndian ? A32(ptr) : XXH_swap32(A32(ptr)); + else + return endian==XXH_littleEndian ? *ptr : XXH_swap32(*ptr); +} + +forceinline U32 XXH_readLE32(const U32* ptr, XXH_endianess endian) { return XXH_readLE32_align(ptr, endian, XXH_unaligned); } + + +//**************************** +// Simple Hash Functions +//**************************** +forceinline U32 XXH32_endian_align(const void* input, int len, U32 seed, XXH_endianess endian, XXH_alignment align) +{ + const BYTE* p = (const BYTE*)input; + const BYTE* const bEnd = p + len; + U32 h32; + +#ifdef XXH_ACCEPT_NULL_INPUT_POINTER + if (p==NULL) { len=0; p=(const BYTE*)(size_t)16; } +#endif + + if (len>=16) + { + const BYTE* const limit = bEnd - 16; + U32 v1 = seed + PRIME32_1 + PRIME32_2; + U32 v2 = seed + PRIME32_2; + U32 v3 = seed + 0; + U32 v4 = seed - PRIME32_1; + + do + { + v1 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4; + v2 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4; + v3 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4; + v4 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4; + } while (p<=limit); + + h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); + } + else + { + h32 = seed + PRIME32_5; + } + + h32 += (U32) len; + + while (p<=bEnd-4) + { + h32 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_3; + h32 = XXH_rotl32(h32, 17) * PRIME32_4 ; + p+=4; + } + + while (p> 15; + h32 *= PRIME32_2; + h32 ^= h32 >> 13; + h32 *= PRIME32_3; + h32 ^= h32 >> 16; + + return h32; +} + + +U32 XXH32(const void* input, int len, U32 seed) +{ +#if 0 + // Simple version, good for code maintenance, but unfortunately slow for small inputs + void* state = XXH32_init(seed); + XXH32_update(state, input, len); + return XXH32_digest(state); +#else + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + +# if !defined(XXH_USE_UNALIGNED_ACCESS) + if (!(((size_t)input) & 3)) // Input is aligned, let's leverage the speed advantage + { + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); + else + return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); + } +# endif + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); + else + return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); +#endif +} + + +//**************************** +// Advanced Hash Functions +//**************************** + +struct XXH_state32_t +{ + U64 total_len; + U32 seed; + U32 v1; + U32 v2; + U32 v3; + U32 v4; + int memsize; + char memory[16]; +}; + + +int XXH32_sizeofState(void) +{ + XXH_STATIC_ASSERT(XXH32_SIZEOFSTATE >= sizeof(struct XXH_state32_t)); // A compilation error here means XXH32_SIZEOFSTATE is not large enough + return sizeof(struct XXH_state32_t); +} + + +XXH_errorcode XXH32_resetState(void* state_in, U32 seed) +{ + struct XXH_state32_t * state = (struct XXH_state32_t *) state_in; + state->seed = seed; + state->v1 = seed + PRIME32_1 + PRIME32_2; + state->v2 = seed + PRIME32_2; + state->v3 = seed + 0; + state->v4 = seed - PRIME32_1; + state->total_len = 0; + state->memsize = 0; + return XXH_OK; +} + + +void* XXH32_init (U32 seed) +{ + void* state = XXH_malloc (sizeof(struct XXH_state32_t)); + XXH32_resetState(state, seed); + return state; +} + + +forceinline XXH_errorcode XXH32_update_endian (void* state_in, const void* input, int len, XXH_endianess endian) +{ + struct XXH_state32_t * state = (struct XXH_state32_t *) state_in; + const BYTE* p = (const BYTE*)input; + const BYTE* const bEnd = p + len; + +#ifdef XXH_ACCEPT_NULL_INPUT_POINTER + if (input==NULL) return XXH_ERROR; +#endif + + state->total_len += len; + + if (state->memsize + len < 16) // fill in tmp buffer + { + XXH_memcpy(state->memory + state->memsize, input, len); + state->memsize += len; + return XXH_OK; + } + + if (state->memsize) // some data left from previous update + { + XXH_memcpy(state->memory + state->memsize, input, 16-state->memsize); + { + const U32* p32 = (const U32*)state->memory; + state->v1 += XXH_readLE32(p32, endian) * PRIME32_2; state->v1 = XXH_rotl32(state->v1, 13); state->v1 *= PRIME32_1; p32++; + state->v2 += XXH_readLE32(p32, endian) * PRIME32_2; state->v2 = XXH_rotl32(state->v2, 13); state->v2 *= PRIME32_1; p32++; + state->v3 += XXH_readLE32(p32, endian) * PRIME32_2; state->v3 = XXH_rotl32(state->v3, 13); state->v3 *= PRIME32_1; p32++; + state->v4 += XXH_readLE32(p32, endian) * PRIME32_2; state->v4 = XXH_rotl32(state->v4, 13); state->v4 *= PRIME32_1; p32++; + } + p += 16-state->memsize; + state->memsize = 0; + } + + if (p <= bEnd-16) + { + const BYTE* const limit = bEnd - 16; + U32 v1 = state->v1; + U32 v2 = state->v2; + U32 v3 = state->v3; + U32 v4 = state->v4; + + do + { + v1 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4; + v2 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4; + v3 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4; + v4 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4; + } while (p<=limit); + + state->v1 = v1; + state->v2 = v2; + state->v3 = v3; + state->v4 = v4; + } + + if (p < bEnd) + { + XXH_memcpy(state->memory, p, bEnd-p); + state->memsize = (int)(bEnd-p); + } + + return XXH_OK; +} + +XXH_errorcode XXH32_update (void* state_in, const void* input, int len) +{ + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_update_endian(state_in, input, len, XXH_littleEndian); + else + return XXH32_update_endian(state_in, input, len, XXH_bigEndian); +} + + + +forceinline U32 XXH32_intermediateDigest_endian (void* state_in, XXH_endianess endian) +{ + struct XXH_state32_t * state = (struct XXH_state32_t *) state_in; + const BYTE * p = (const BYTE*)state->memory; + BYTE* bEnd = (BYTE*)state->memory + state->memsize; + U32 h32; + + if (state->total_len >= 16) + { + h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18); + } + else + { + h32 = state->seed + PRIME32_5; + } + + h32 += (U32) state->total_len; + + while (p<=bEnd-4) + { + h32 += XXH_readLE32((const U32*)p, endian) * PRIME32_3; + h32 = XXH_rotl32(h32, 17) * PRIME32_4; + p+=4; + } + + while (p> 15; + h32 *= PRIME32_2; + h32 ^= h32 >> 13; + h32 *= PRIME32_3; + h32 ^= h32 >> 16; + + return h32; +} + + +U32 XXH32_intermediateDigest (void* state_in) +{ + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_intermediateDigest_endian(state_in, XXH_littleEndian); + else + return XXH32_intermediateDigest_endian(state_in, XXH_bigEndian); +} + + +U32 XXH32_digest (void* state_in) +{ + U32 h32 = XXH32_intermediateDigest(state_in); + + XXH_free(state_in); + + return h32; +} Property changes on: contrib/libucl/src/xxhash.c ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/src/xxhash.h =================================================================== --- contrib/libucl/src/xxhash.h (revision 0) +++ contrib/libucl/src/xxhash.h (working copy) @@ -0,0 +1,164 @@ +/* + xxHash - Fast Hash algorithm + Header File + Copyright (C) 2012-2013, Yann Collet. + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - xxHash source repository : http://code.google.com/p/xxhash/ +*/ + +/* Notice extracted from xxHash homepage : + +xxHash is an extremely fast Hash algorithm, running at RAM speed limits. +It also successfully passes all tests from the SMHasher suite. + +Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz) + +Name Speed Q.Score Author +xxHash 5.4 GB/s 10 +CrapWow 3.2 GB/s 2 Andrew +MumurHash 3a 2.7 GB/s 10 Austin Appleby +SpookyHash 2.0 GB/s 10 Bob Jenkins +SBox 1.4 GB/s 9 Bret Mulvey +Lookup3 1.2 GB/s 9 Bob Jenkins +SuperFastHash 1.2 GB/s 1 Paul Hsieh +CityHash64 1.05 GB/s 10 Pike & Alakuijala +FNV 0.55 GB/s 5 Fowler, Noll, Vo +CRC32 0.43 GB/s 9 +MD5-32 0.33 GB/s 10 Ronald L. Rivest +SHA1-32 0.28 GB/s 10 + +Q.Score is a measure of quality of the hash function. +It depends on successfully passing SMHasher test set. +10 is a perfect score. +*/ + +#pragma once + +#if defined (__cplusplus) +extern "C" { +#endif + + +//**************************** +// Type +//**************************** +typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode; + + + +//**************************** +// Simple Hash Functions +//**************************** + +unsigned int XXH32 (const void* input, int len, unsigned int seed); + +/* +XXH32() : + Calculate the 32-bits hash of sequence of length "len" stored at memory address "input". + The memory between input & input+len must be valid (allocated and read-accessible). + "seed" can be used to alter the result predictably. + This function successfully passes all SMHasher tests. + Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s + Note that "len" is type "int", which means it is limited to 2^31-1. + If your data is larger, use the advanced functions below. +*/ + + + +//**************************** +// Advanced Hash Functions +//**************************** + +void* XXH32_init (unsigned int seed); +XXH_errorcode XXH32_update (void* state, const void* input, int len); +unsigned int XXH32_digest (void* state); + +/* +These functions calculate the xxhash of an input provided in several small packets, +as opposed to an input provided as a single block. + +It must be started with : +void* XXH32_init() +The function returns a pointer which holds the state of calculation. + +This pointer must be provided as "void* state" parameter for XXH32_update(). +XXH32_update() can be called as many times as necessary. +The user must provide a valid (allocated) input. +The function returns an error code, with 0 meaning OK, and any other value meaning there is an error. +Note that "len" is type "int", which means it is limited to 2^31-1. +If your data is larger, it is recommended to chunk your data into blocks +of size for example 2^30 (1GB) to avoid any "int" overflow issue. + +Finally, you can end the calculation anytime, by using XXH32_digest(). +This function returns the final 32-bits hash. +You must provide the same "void* state" parameter created by XXH32_init(). +Memory will be freed by XXH32_digest(). +*/ + + +int XXH32_sizeofState(void); +XXH_errorcode XXH32_resetState(void* state, unsigned int seed); + +#define XXH32_SIZEOFSTATE 48 +typedef struct { long long ll[(XXH32_SIZEOFSTATE+(sizeof(long long)-1))/sizeof(long long)]; } XXH32_stateSpace_t; +/* +These functions allow user application to make its own allocation for state. + +XXH32_sizeofState() is used to know how much space must be allocated for the xxHash 32-bits state. +Note that the state must be aligned to access 'long long' fields. Memory must be allocated and referenced by a pointer. +This pointer must then be provided as 'state' into XXH32_resetState(), which initializes the state. + +For static allocation purposes (such as allocation on stack, or freestanding systems without malloc()), +use the structure XXH32_stateSpace_t, which will ensure that memory space is large enough and correctly aligned to access 'long long' fields. +*/ + + +unsigned int XXH32_intermediateDigest (void* state); +/* +This function does the same as XXH32_digest(), generating a 32-bit hash, +but preserve memory context. +This way, it becomes possible to generate intermediate hashes, and then continue feeding data with XXH32_update(). +To free memory context, use XXH32_digest(), or free(). +*/ + + + +//**************************** +// Deprecated function names +//**************************** +// The following translations are provided to ease code transition +// You are encouraged to no longer this function names +#define XXH32_feed XXH32_update +#define XXH32_result XXH32_digest +#define XXH32_getIntermediateResult XXH32_intermediateDigest + + + +#if defined (__cplusplus) +} +#endif Property changes on: contrib/libucl/src/xxhash.h ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/tests/1.in =================================================================== --- contrib/libucl/tests/1.in (revision 0) +++ contrib/libucl/tests/1.in (working copy) @@ -0,0 +1,11 @@ +{ +"key1": value; +"key1": value2; +"key1": "value;" +"key1": 1.0, +"key1": -1e-10, +"key1": 1 +"key1": true +"key1": no +"key1": yes +} Property changes on: contrib/libucl/tests/1.in ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/tests/1.res =================================================================== --- contrib/libucl/tests/1.res (revision 0) +++ contrib/libucl/tests/1.res (working copy) @@ -0,0 +1,10 @@ +key1 = "value"; +key1 = "value2"; +key1 = "value;"; +key1 = 1.0; +key1 = -1e-10; +key1 = 1; +key1 = true; +key1 = false; +key1 = true; + Index: contrib/libucl/tests/2.in =================================================================== --- contrib/libucl/tests/2.in (revision 0) +++ contrib/libucl/tests/2.in (working copy) @@ -0,0 +1,24 @@ +section1 { param1 = value; param2 = value, +section3 {param = value; param2 = value, param3 = ["value1", value2, 100500]}} +section2 { param1 = {key = value}, param1 = ["key"]} + +# Numbers +key1 = 1s +key2 = 1min +key3 = 1kb +key4 = 5M +key5 = 10mS +key6 = 10y + +# Strings +key1 = "some string"; +key2 = /some/path; +key3 = 111some, +key4: s1, +"key5": "\n\r123" + +# Variables +keyvar = "$ABItest"; +keyvar = "${ABI}$ABI${ABI}${$ABI}"; +keyvar = "${some}$no${}$$test$$$$$$$"; +keyvar = "$ABI$$ABI$$$ABI$$$$"; Property changes on: contrib/libucl/tests/2.in ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/tests/2.res =================================================================== --- contrib/libucl/tests/2.res (revision 0) +++ contrib/libucl/tests/2.res (working copy) @@ -0,0 +1,37 @@ +section1 { + param1 = "value"; + param2 = "value"; + section3 { + param = "value"; + param2 = "value"; + param3 [ + "value1", + "value2", + 100500, + ] + } +} +section2 { + param1 { + key = "value"; + } + param1 [ + "key", + ] +} +key1 = 1.0; +key1 = "some string"; +key2 = 60.0; +key2 = "/some/path"; +key3 = 1024; +key3 = "111some"; +key4 = 5000000; +key4 = "s1"; +key5 = 0.010000; +key5 = "\n\r123"; +key6 = 2207520000.000000; +keyvar = "unknowntest"; +keyvar = "unknownunknownunknown${unknown}"; +keyvar = "${some}$no${}$$test$$$$$$$"; +keyvar = "unknown$ABI$unknown$$"; + Index: contrib/libucl/tests/3.in =================================================================== --- contrib/libucl/tests/3.in (revision 0) +++ contrib/libucl/tests/3.in (working copy) @@ -0,0 +1,31 @@ +/* + * Pkg conf + */ + +#packagesite http//pkg.freebsd.org/freebsd-9-amd64/latest +#packagesite http//pkg.freebsd.org/freebsd-9-amd64/latest +packagesite: http://pkg-test.freebsd.org/pkg-test/${ABI}/latest +squaretest: some[]value +ALIAS : { + all-depends: query %dn-%dv, + annotations: info -A, + build-depends: info -qd, + download: fetch, + iinfo: info -i -g -x, + isearch: search -i -g -x, + leaf: query -e '%a == 0' '%n-%v', + leaf: query -e '%a == 0' '%n-%v', + list: info -ql, + origin: info -qo, + provided-depends: info -qb, + raw: info -R, + required-depends: info -qr, + shared-depends: info -qB, + show: info -f -k, + size: info -sq, + } + +repo_dirs : [ + /home/bapt, + /usr/local/etc +] Property changes on: contrib/libucl/tests/3.in ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/tests/3.res =================================================================== --- contrib/libucl/tests/3.res (revision 0) +++ contrib/libucl/tests/3.res (working copy) @@ -0,0 +1,25 @@ +packagesite = "http://pkg-test.freebsd.org/pkg-test/unknown/latest"; +squaretest = "some[]value"; +alias { + all-depends = "query %dn-%dv"; + annotations = "info -A"; + build-depends = "info -qd"; + download = "fetch"; + iinfo = "info -i -g -x"; + isearch = "search -i -g -x"; + leaf = "query -e '%a == 0' '%n-%v'"; + leaf = "query -e '%a == 0' '%n-%v'"; + list = "info -ql"; + origin = "info -qo"; + provided-depends = "info -qb"; + raw = "info -R"; + required-depends = "info -qr"; + shared-depends = "info -qB"; + show = "info -f -k"; + size = "info -sq"; +} +repo_dirs [ + "/home/bapt", + "/usr/local/etc", +] + Index: contrib/libucl/tests/4.in =================================================================== --- contrib/libucl/tests/4.in (revision 0) +++ contrib/libucl/tests/4.in (working copy) @@ -0,0 +1,47 @@ +name : "pkgconf" +version : "0.9.3" +origin : "devel/pkgconf" +comment : "Utility to help to configure compiler and linker flags" +arch : "freebsd:9:x86:64" +maintainer : "bapt@FreeBSD.org" +prefix : "/usr/local" +licenselogic : "single" +licenses : [ + "BSD", +] +flatsize : 60523 +desc : "pkgconf is a program which helps to configure compiler and linker flags for\ndevelopment frameworks. It is similar to pkg-config, but was written from\nscratch in Summer of 2011 to replace pkg-config, which now needs itself to build\nitself.\n\nWWW: https://github.com/pkgconf/pkgconf" +categories : [ + "devel", +] +files : { + /usr/local/bin/pkg-config : "-", + /usr/local/bin/pkgconf : "4a0fc53e5ad64e8085da2e61652d61c50b192a086421d865703f1de9f724da38", + /usr/local/share/aclocal/pkg.m4 : "cffab33d659adfe36497ec57665eec36fa6fb7b007e578e6ac2434cc28be8820", + /usr/local/share/licenses/pkgconf-0.9.3/BSD : "85e7a53b5e2d3e350e2d084fed2f94b7f63005f8e1168740e1e84aa9fa5d48ce", + /usr/local/share/licenses/pkgconf-0.9.3/LICENSE : "d9cce0db43502eb1bd8fbef7e960cfaa43b5647186f7f7379923b336209fd77b", + /usr/local/share/licenses/pkgconf-0.9.3/catalog.mk : "e7b131acce7c3d3c61f2214607b11b34526e03b05afe89a608f50586a898e2ef", +} +directories : { + /usr/local/share/licenses/pkgconf-0.9.3/ : false, + /usr/local/share/licenses/ : true, +} +scripts : { + post-install : "cd /usr/local\nn", + pre-deinstall : "cd /usr/local\nn", + post-deinstall : "cd /usr/local\nn", +} +multiline-key : </dev/null + if [ $? -ne 0 ] ; then + rm $_t.out + echo "Test: $_t output missmatch" + exit 1 + fi + fi + rm $_t.out +done + +if [ $# -gt 2 ] ; then + $3 ${TEST_DIR}/generate.out + diff -s ${TEST_DIR}/generate.out ${TEST_DIR}/generate.res -u 2>/dev/null + if [ $? -ne 0 ] ; then + rm ${TEST_DIR}/generate.out + echo "Test: generate.res output missmatch" + exit 1 + fi + rm ${TEST_DIR}/generate.out +fi + +sh -c "xz -c < /dev/null > /dev/null" +if [ $? -eq 0 -a $# -gt 1 ] ; then + echo 'Running speed tests' + for _tin in ${TEST_DIR}/*.xz ; do + echo "Unpacking $_tin..." + xz -cd < $_tin > ${TEST_DIR}/test_file + # Preread file to cheat benchmark! + cat ${TEST_DIR}/test_file > /dev/null + echo "Starting benchmarking for $_tin..." + $2 ${TEST_DIR}/test_file + if [ $? -ne 0 ] ; then + echo "Test: $_tin failed" + rm ${TEST_DIR}/test_file + exit 1 + fi + rm ${TEST_DIR}/test_file + done +fi + Property changes on: contrib/libucl/tests/run_tests.sh ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: contrib/libucl/tests/test_basic.c =================================================================== --- contrib/libucl/tests/test_basic.c (revision 0) +++ contrib/libucl/tests/test_basic.c (working copy) @@ -0,0 +1,119 @@ +/* Copyright (c) 2013, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "ucl.h" + +int +main (int argc, char **argv) +{ + char inbuf[8192]; + struct ucl_parser *parser = NULL, *parser2 = NULL; + ucl_object_t *obj; + FILE *in, *out; + unsigned char *emitted = NULL; + const char *fname_in = NULL, *fname_out = NULL; + int ret = 0; + + switch (argc) { + case 2: + fname_in = argv[1]; + break; + case 3: + fname_in = argv[1]; + fname_out = argv[2]; + break; + } + + if (fname_in != NULL) { + in = fopen (fname_in, "r"); + if (in == NULL) { + exit (-errno); + } + } + else { + in = stdin; + } + parser = ucl_parser_new (UCL_PARSER_KEY_LOWERCASE); + ucl_parser_register_variable (parser, "ABI", "unknown"); + + if (fname_in != NULL) { + ucl_parser_set_filevars (parser, fname_in, true); + } + + while (!feof (in)) { + memset (inbuf, 0, sizeof (inbuf)); + (void)fread (inbuf, sizeof (inbuf), 1, in); + ucl_parser_add_chunk (parser, inbuf, strlen (inbuf)); + } + fclose (in); + + if (fname_out != NULL) { + out = fopen (fname_out, "w"); + if (out == NULL) { + exit (-errno); + } + } + else { + out = stdout; + } + if (ucl_parser_get_error(parser) != NULL) { + fprintf (out, "Error occurred: %s\n", ucl_parser_get_error(parser)); + ret = 1; + goto end; + } + obj = ucl_parser_get_object (parser); + emitted = ucl_object_emit (obj, UCL_EMIT_CONFIG); + ucl_parser_free (parser); + ucl_object_unref (obj); + parser2 = ucl_parser_new (UCL_PARSER_KEY_LOWERCASE); + ucl_parser_add_chunk (parser2, emitted, strlen (emitted)); + + if (ucl_parser_get_error(parser2) != NULL) { + fprintf (out, "Error occurred: %s\n", ucl_parser_get_error(parser2)); + fprintf (out, "%s\n", emitted); + ret = 1; + goto end; + } + if (emitted != NULL) { + free (emitted); + } + obj = ucl_parser_get_object (parser2); + emitted = ucl_object_emit (obj, UCL_EMIT_CONFIG); + + fprintf (out, "%s\n", emitted); + ucl_object_unref (obj); + +end: + if (emitted != NULL) { + free (emitted); + } + if (parser2 != NULL) { + ucl_parser_free (parser2); + } + + fclose (out); + + return ret; +} Property changes on: contrib/libucl/tests/test_basic.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: contrib/libucl/tests/test_generate.c =================================================================== --- contrib/libucl/tests/test_generate.c (revision 0) +++ contrib/libucl/tests/test_generate.c (working copy) @@ -0,0 +1,105 @@ +/* Copyright (c) 2013, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "ucl.h" + +int +main (int argc, char **argv) +{ + ucl_object_t *obj, *cur, *ar; + FILE *out; + unsigned char *emitted; + const char *fname_out = NULL; + int ret = 0; + + switch (argc) { + case 2: + fname_out = argv[1]; + break; + } + + + if (fname_out != NULL) { + out = fopen (fname_out, "w"); + if (out == NULL) { + exit (-errno); + } + } + else { + out = stdout; + } + + obj = ucl_object_typed_new (UCL_OBJECT); + /* Create some strings */ + cur = ucl_object_fromstring_common (" test string ", 0, UCL_STRING_TRIM); + obj = ucl_object_insert_key (obj, cur, "key1", 0, false); + cur = ucl_object_fromstring_common (" test \nstring\n ", 0, UCL_STRING_TRIM | UCL_STRING_ESCAPE); + obj = ucl_object_insert_key (obj, cur, "key2", 0, false); + cur = ucl_object_fromstring_common (" test string \n", 0, 0); + obj = ucl_object_insert_key (obj, cur, "key3", 0, false); + /* Array of numbers */ + cur = ucl_object_fromint (10); + ar = ucl_array_append (NULL, cur); + cur = ucl_object_fromdouble (10.1); + ar = ucl_array_append (ar, cur); + obj = ucl_object_insert_key (obj, ar, "key4", 0, false); + cur = ucl_object_frombool (true); + obj = ucl_object_insert_key (obj, cur, "key4", 0, false); + /* Empty strings */ + cur = ucl_object_fromstring_common (" ", 0, UCL_STRING_TRIM); + obj = ucl_object_insert_key (obj, cur, "key5", 0, false); + cur = ucl_object_fromstring_common ("", 0, UCL_STRING_ESCAPE); + obj = ucl_object_insert_key (obj, cur, "key6", 0, false); + cur = ucl_object_fromstring_common (" \n", 0, UCL_STRING_ESCAPE); + obj = ucl_object_insert_key (obj, cur, "key7", 0, false); + /* Numbers and booleans */ + cur = ucl_object_fromstring_common ("1mb", 0, UCL_STRING_ESCAPE | UCL_STRING_PARSE); + obj = ucl_object_insert_key (obj, cur, "key8", 0, false); + cur = ucl_object_fromstring_common ("3.14", 0, UCL_STRING_PARSE); + obj = ucl_object_insert_key (obj, cur, "key9", 0, false); + cur = ucl_object_fromstring_common ("true", 0, UCL_STRING_PARSE); + obj = ucl_object_insert_key (obj, cur, "key10", 0, false); + cur = ucl_object_fromstring_common (" off ", 0, UCL_STRING_PARSE | UCL_STRING_TRIM); + obj = ucl_object_insert_key (obj, cur, "key11", 0, false); + cur = ucl_object_fromstring_common ("gslin@gslin.org", 0, UCL_STRING_PARSE_INT); + obj = ucl_object_insert_key (obj, cur, "key12", 0, false); + cur = ucl_object_fromstring_common ("#test", 0, UCL_STRING_PARSE_INT); + obj = ucl_object_insert_key (obj, cur, "key13", 0, false); + cur = ucl_object_frombool (true); + obj = ucl_object_insert_key (obj, cur, "k=3", 0, false); + + + emitted = ucl_object_emit (obj, UCL_EMIT_CONFIG); + + fprintf (out, "%s\n", emitted); + ucl_object_unref (obj); + + if (emitted != NULL) { + free (emitted); + } + fclose (out); + + return ret; +} Property changes on: contrib/libucl/tests/test_generate.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: contrib/libucl/tests/test_speed.c =================================================================== --- contrib/libucl/tests/test_speed.c (revision 0) +++ contrib/libucl/tests/test_speed.c (working copy) @@ -0,0 +1,147 @@ +/* Copyright (c) 2013, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __APPLE__ +#include +#endif + +#include "ucl.h" + +static double +get_ticks (void) +{ + double res; + +#ifdef __APPLE__ + res = mach_absolute_time () / 1000000000.; +#else + struct timespec ts; + clock_gettime (CLOCK_MONOTONIC, &ts); + + res = (double)ts.tv_sec + ts.tv_nsec / 1000000000.; +#endif + + return res; +} + +int +main (int argc, char **argv) +{ + void *map; + struct ucl_parser *parser; + ucl_object_t *obj; + int fin; + unsigned char *emitted; + struct stat st; + const char *fname_in = NULL; + int ret = 0; + double start, end, seconds; + + switch (argc) { + case 2: + fname_in = argv[1]; + break; + } + + fin = open (fname_in, O_RDONLY); + if (fin == -1) { + perror ("open failed"); + exit (EXIT_FAILURE); + } + parser = ucl_parser_new (UCL_PARSER_ZEROCOPY); + + (void)fstat (fin, &st); + map = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fin, 0); + if (map == MAP_FAILED) { + perror ("mmap failed"); + exit (EXIT_FAILURE); + } + + close (fin); + + start = get_ticks (); + ucl_parser_add_chunk (parser, map, st.st_size); + + obj = ucl_parser_get_object (parser); + end = get_ticks (); + + seconds = end - start; + printf ("ucl: parsed input in %.4f seconds\n", seconds); + if (ucl_parser_get_error(parser)) { + printf ("Error occurred: %s\n", ucl_parser_get_error(parser)); + ret = 1; + } + + start = get_ticks (); + emitted = ucl_object_emit (obj, UCL_EMIT_CONFIG); + end = get_ticks (); + + seconds = end - start; + printf ("ucl: emitted config in %.4f seconds\n", seconds); + + free (emitted); + + start = get_ticks (); + emitted = ucl_object_emit (obj, UCL_EMIT_JSON); + end = get_ticks (); + + seconds = end - start; + printf ("ucl: emitted json in %.4f seconds\n", seconds); + + free (emitted); + + start = get_ticks (); + emitted = ucl_object_emit (obj, UCL_EMIT_JSON_COMPACT); + end = get_ticks (); + + seconds = end - start; + printf ("ucl: emitted compact json in %.4f seconds\n", seconds); + + free (emitted); + + start = get_ticks (); + emitted = ucl_object_emit (obj, UCL_EMIT_YAML); + end = get_ticks (); + + seconds = end - start; + printf ("ucl: emitted yaml in %.4f seconds\n", seconds); + + free (emitted); + + ucl_parser_free (parser); + ucl_object_unref (obj); + + munmap (map, st.st_size); + + return ret; +} Property changes on: contrib/libucl/tests/test_speed.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: contrib/libucl/uthash/uthash.h =================================================================== --- contrib/libucl/uthash/uthash.h (revision 0) +++ contrib/libucl/uthash/uthash.h (working copy) @@ -0,0 +1,720 @@ +/* +Copyright (c) 2003-2013, Troy D. Hanson http://troydhanson.github.com/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef UTHASH_H +#define UTHASH_H + +#include /* memcmp,strlen */ +#include /* ptrdiff_t */ +#include /* exit() */ +#include "xxhash.h" + +/* These macros use decltype or the earlier __typeof GNU extension. + As decltype is only available in newer compilers (VS2010 or gcc 4.3+ + when compiling c++ source) this code uses whatever method is needed + or, for VS2008 where neither is available, uses casting workarounds. */ +#ifdef _MSC_VER /* MS compiler */ +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ +#define DECLTYPE(x) (decltype(x)) +#else /* VS2008 or older (or VS2010 in C mode) */ +#define NO_DECLTYPE +#define DECLTYPE(x) +#endif +#else /* GNU, Sun and other compilers */ +#define DECLTYPE(x) (__typeof(x)) +#endif + +#ifdef NO_DECLTYPE +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + char **_da_dst = (char**)(&(dst)); \ + *_da_dst = (char*)(src); \ +} while(0) +#else +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + (dst) = DECLTYPE(dst)(src); \ +} while(0) +#endif + +/* a number of the hash function use uint32_t which isn't defined on win32 */ +#ifdef _MSC_VER +typedef unsigned int uint32_t; +typedef unsigned char uint8_t; +#else +#include /* uint32_t */ +#endif + +#define UTHASH_VERSION 1.9.8 + +#ifndef uthash_fatal +#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */ +#endif +#ifndef uthash_malloc +#define uthash_malloc(sz) malloc(sz) /* malloc fcn */ +#endif +#ifndef uthash_free +#define uthash_free(ptr,sz) free(ptr) /* free fcn */ +#endif + +#ifndef uthash_noexpand_fyi +#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ +#endif +#ifndef uthash_expand_fyi +#define uthash_expand_fyi(tbl) /* can be defined to log expands */ +#endif + +/* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */ +#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */ + +/* calculate the element whose hash handle address is hhe */ +#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) + +#define HASH_FIND(hh,head,keyptr,keylen,out) \ +do { \ + unsigned _hf_bkt,_hf_hashv; \ + out=NULL; \ + if (head) { \ + HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \ + if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \ + HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \ + keyptr,keylen,out); \ + } \ + } \ +} while (0) + +#ifdef HASH_BLOOM +#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM) +#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0) +#define HASH_BLOOM_MAKE(tbl) \ +do { \ + (tbl)->bloom_nbits = HASH_BLOOM; \ + (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ + if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \ + memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \ + (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ +} while (0) + +#define HASH_BLOOM_FREE(tbl) \ +do { \ + uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ +} while (0) + +#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8))) +#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8))) + +#define HASH_BLOOM_ADD(tbl,hashv) \ + HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) + +#define HASH_BLOOM_TEST(tbl,hashv) \ + HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) + +#else +#define HASH_BLOOM_MAKE(tbl) +#define HASH_BLOOM_FREE(tbl) +#define HASH_BLOOM_ADD(tbl,hashv) +#define HASH_BLOOM_TEST(tbl,hashv) (1) +#define HASH_BLOOM_BYTELEN 0 +#endif + +#define HASH_MAKE_TABLE(hh,head) \ +do { \ + (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \ + sizeof(UT_hash_table)); \ + if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \ + memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \ + (head)->hh.tbl->tail = &((head)->hh); \ + (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ + (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ + (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ + (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ + HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ + if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \ + memset((head)->hh.tbl->buckets, 0, \ + HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ + HASH_BLOOM_MAKE((head)->hh.tbl); \ + (head)->hh.tbl->signature = HASH_SIGNATURE; \ +} while(0) + +#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ + HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add) + +#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \ +do { \ + replaced=NULL; \ + HASH_FIND(hh,head,&((add)->fieldname),keylen_in,replaced); \ + if (replaced!=NULL) { \ + HASH_DELETE(hh,head,replaced); \ + }; \ + HASH_ADD(hh,head,fieldname,keylen_in,add); \ +} while(0) + +#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ +do { \ + unsigned _ha_bkt; \ + (add)->hh.next = NULL; \ + (add)->hh.key = (const char*)keyptr; \ + (add)->hh.keylen = (unsigned)keylen_in; \ + if (!(head)) { \ + head = (add); \ + (head)->hh.prev = NULL; \ + HASH_MAKE_TABLE(hh,head); \ + } else { \ + (head)->hh.tbl->tail->next = (add); \ + (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ + (head)->hh.tbl->tail = &((add)->hh); \ + } \ + (head)->hh.tbl->num_items++; \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \ + (add)->hh.hashv, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \ + HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \ + HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \ + HASH_FSCK(hh,head); \ +} while(0) + +#define HASH_TO_BKT( hashv, num_bkts, bkt ) \ +do { \ + bkt = ((hashv) & ((num_bkts) - 1)); \ +} while(0) + +/* delete "delptr" from the hash table. + * "the usual" patch-up process for the app-order doubly-linked-list. + * The use of _hd_hh_del below deserves special explanation. + * These used to be expressed using (delptr) but that led to a bug + * if someone used the same symbol for the head and deletee, like + * HASH_DELETE(hh,users,users); + * We want that to work, but by changing the head (users) below + * we were forfeiting our ability to further refer to the deletee (users) + * in the patch-up process. Solution: use scratch space to + * copy the deletee pointer, then the latter references are via that + * scratch pointer rather than through the repointed (users) symbol. + */ +#define HASH_DELETE(hh,head,delptr) \ +do { \ + unsigned _hd_bkt; \ + struct UT_hash_handle *_hd_hh_del; \ + if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + head = NULL; \ + } else { \ + _hd_hh_del = &((delptr)->hh); \ + if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \ + (head)->hh.tbl->tail = \ + (UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ + (head)->hh.tbl->hho); \ + } \ + if ((delptr)->hh.prev) { \ + ((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ + (head)->hh.tbl->hho))->next = (delptr)->hh.next; \ + } else { \ + DECLTYPE_ASSIGN(head,(delptr)->hh.next); \ + } \ + if (_hd_hh_del->next) { \ + ((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next + \ + (head)->hh.tbl->hho))->prev = \ + _hd_hh_del->prev; \ + } \ + HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ + (head)->hh.tbl->num_items--; \ + } \ + HASH_FSCK(hh,head); \ +} while (0) + + +/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ +#define HASH_FIND_STR(head,findstr,out) \ + HASH_FIND(hh,head,findstr,strlen(findstr),out) +#define HASH_ADD_STR(head,strfield,add) \ + HASH_ADD(hh,head,strfield,strlen(add->strfield),add) +#define HASH_REPLACE_STR(head,strfield,add,replaced) \ + HASH_REPLACE(hh,head,strfield,strlen(add->strfield),add,replaced) +#define HASH_FIND_INT(head,findint,out) \ + HASH_FIND(hh,head,findint,sizeof(int),out) +#define HASH_ADD_INT(head,intfield,add) \ + HASH_ADD(hh,head,intfield,sizeof(int),add) +#define HASH_REPLACE_INT(head,intfield,add,replaced) \ + HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced) +#define HASH_FIND_PTR(head,findptr,out) \ + HASH_FIND(hh,head,findptr,sizeof(void *),out) +#define HASH_ADD_PTR(head,ptrfield,add) \ + HASH_ADD(hh,head,ptrfield,sizeof(void *),add) +#define HASH_REPLACE_PTR(head,ptrfield,add) \ + HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced) +#define HASH_DEL(head,delptr) \ + HASH_DELETE(hh,head,delptr) + +/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. + * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. + */ +#ifdef HASH_DEBUG +#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0) +#define HASH_FSCK(hh,head) \ +do { \ + unsigned _bkt_i; \ + unsigned _count, _bkt_count; \ + char *_prev; \ + struct UT_hash_handle *_thh; \ + if (head) { \ + _count = 0; \ + for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \ + _bkt_count = 0; \ + _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ + _prev = NULL; \ + while (_thh) { \ + if (_prev != (char*)(_thh->hh_prev)) { \ + HASH_OOPS("invalid hh_prev %p, actual %p\n", \ + _thh->hh_prev, _prev ); \ + } \ + _bkt_count++; \ + _prev = (char*)(_thh); \ + _thh = _thh->hh_next; \ + } \ + _count += _bkt_count; \ + if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ + HASH_OOPS("invalid bucket count %d, actual %d\n", \ + (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ + } \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("invalid hh item count %d, actual %d\n", \ + (head)->hh.tbl->num_items, _count ); \ + } \ + /* traverse hh in app order; check next/prev integrity, count */ \ + _count = 0; \ + _prev = NULL; \ + _thh = &(head)->hh; \ + while (_thh) { \ + _count++; \ + if (_prev !=(char*)(_thh->prev)) { \ + HASH_OOPS("invalid prev %p, actual %p\n", \ + _thh->prev, _prev ); \ + } \ + _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ + _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \ + (head)->hh.tbl->hho) : NULL ); \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("invalid app item count %d, actual %d\n", \ + (head)->hh.tbl->num_items, _count ); \ + } \ + } \ +} while (0) +#else +#define HASH_FSCK(hh,head) +#endif + +/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to + * the descriptor to which this macro is defined for tuning the hash function. + * The app can #include to get the prototype for write(2). */ +#ifdef HASH_EMIT_KEYS +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ +do { \ + unsigned _klen = fieldlen; \ + write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ + write(HASH_EMIT_KEYS, keyptr, fieldlen); \ +} while (0) +#else +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) +#endif + +/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */ +#ifdef HASH_FUNCTION +#define HASH_FCN HASH_FUNCTION +#else +#define HASH_FCN HASH_XX +#endif + +#define XX_HASH_PRIME 2654435761U + +#define HASH_XX(key,keylen,num_bkts,hashv,bkt) \ +do { \ + hashv = XXH32 (key, keylen, XX_HASH_PRIME); \ + bkt = (hashv) & (num_bkts-1); \ +} while (0) + + + +/* key comparison function; return 0 if keys equal */ +#define HASH_KEYCMP(a,b,len) memcmp(a,b,len) + +/* iterate over items in a known bucket to find desired item */ +#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \ +do { \ + if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \ + else out=NULL; \ + while (out) { \ + if ((out)->hh.keylen == keylen_in) { \ + if ((HASH_KEYCMP((out)->hh.key,keyptr,keylen_in)) == 0) break; \ + } \ + if ((out)->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,(out)->hh.hh_next)); \ + else out = NULL; \ + } \ +} while(0) + +/* add an item to a bucket */ +#define HASH_ADD_TO_BKT(head,addhh) \ +do { \ + head.count++; \ + (addhh)->hh_next = head.hh_head; \ + (addhh)->hh_prev = NULL; \ + if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \ + (head).hh_head=addhh; \ + if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \ + && (addhh)->tbl->noexpand != 1) { \ + HASH_EXPAND_BUCKETS((addhh)->tbl); \ + } \ +} while(0) + +/* remove an item from a given bucket */ +#define HASH_DEL_IN_BKT(hh,head,hh_del) \ + (head).count--; \ + if ((head).hh_head == hh_del) { \ + (head).hh_head = hh_del->hh_next; \ + } \ + if (hh_del->hh_prev) { \ + hh_del->hh_prev->hh_next = hh_del->hh_next; \ + } \ + if (hh_del->hh_next) { \ + hh_del->hh_next->hh_prev = hh_del->hh_prev; \ + } + +/* Bucket expansion has the effect of doubling the number of buckets + * and redistributing the items into the new buckets. Ideally the + * items will distribute more or less evenly into the new buckets + * (the extent to which this is true is a measure of the quality of + * the hash function as it applies to the key domain). + * + * With the items distributed into more buckets, the chain length + * (item count) in each bucket is reduced. Thus by expanding buckets + * the hash keeps a bound on the chain length. This bounded chain + * length is the essence of how a hash provides constant time lookup. + * + * The calculation of tbl->ideal_chain_maxlen below deserves some + * explanation. First, keep in mind that we're calculating the ideal + * maximum chain length based on the *new* (doubled) bucket count. + * In fractions this is just n/b (n=number of items,b=new num buckets). + * Since the ideal chain length is an integer, we want to calculate + * ceil(n/b). We don't depend on floating point arithmetic in this + * hash, so to calculate ceil(n/b) with integers we could write + * + * ceil(n/b) = (n/b) + ((n%b)?1:0) + * + * and in fact a previous version of this hash did just that. + * But now we have improved things a bit by recognizing that b is + * always a power of two. We keep its base 2 log handy (call it lb), + * so now we can write this with a bit shift and logical AND: + * + * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) + * + */ +#define HASH_EXPAND_BUCKETS(tbl) \ +do { \ + unsigned _he_bkt; \ + unsigned _he_bkt_i; \ + struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ + UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ + _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ + 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \ + memset(_he_new_buckets, 0, \ + 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + tbl->ideal_chain_maxlen = \ + (tbl->num_items >> (tbl->log2_num_buckets+1)) + \ + ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \ + tbl->nonideal_items = 0; \ + for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \ + { \ + _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \ + while (_he_thh) { \ + _he_hh_nxt = _he_thh->hh_next; \ + HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \ + _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \ + if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \ + tbl->nonideal_items++; \ + _he_newbkt->expand_mult = _he_newbkt->count / \ + tbl->ideal_chain_maxlen; \ + } \ + _he_thh->hh_prev = NULL; \ + _he_thh->hh_next = _he_newbkt->hh_head; \ + if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \ + _he_thh; \ + _he_newbkt->hh_head = _he_thh; \ + _he_thh = _he_hh_nxt; \ + } \ + } \ + uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ + tbl->num_buckets *= 2; \ + tbl->log2_num_buckets++; \ + tbl->buckets = _he_new_buckets; \ + tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \ + (tbl->ineff_expands+1) : 0; \ + if (tbl->ineff_expands > 1) { \ + tbl->noexpand=1; \ + uthash_noexpand_fyi(tbl); \ + } \ + uthash_expand_fyi(tbl); \ +} while(0) + + +/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ +/* Note that HASH_SORT assumes the hash handle name to be hh. + * HASH_SRT was added to allow the hash handle name to be passed in. */ +#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) +#define HASH_SRT(hh,head,cmpfcn) \ +do { \ + unsigned _hs_i; \ + unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ + struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ + if (head) { \ + _hs_insize = 1; \ + _hs_looping = 1; \ + _hs_list = &((head)->hh); \ + while (_hs_looping) { \ + _hs_p = _hs_list; \ + _hs_list = NULL; \ + _hs_tail = NULL; \ + _hs_nmerges = 0; \ + while (_hs_p) { \ + _hs_nmerges++; \ + _hs_q = _hs_p; \ + _hs_psize = 0; \ + for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \ + _hs_psize++; \ + _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ + ((void*)((char*)(_hs_q->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + if (! (_hs_q) ) break; \ + } \ + _hs_qsize = _hs_insize; \ + while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \ + if (_hs_psize == 0) { \ + _hs_e = _hs_q; \ + _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ + ((void*)((char*)(_hs_q->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + _hs_qsize--; \ + } else if ( (_hs_qsize == 0) || !(_hs_q) ) { \ + _hs_e = _hs_p; \ + if (_hs_p){ \ + _hs_p = (UT_hash_handle*)((_hs_p->next) ? \ + ((void*)((char*)(_hs_p->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + } \ + _hs_psize--; \ + } else if (( \ + cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \ + DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \ + ) <= 0) { \ + _hs_e = _hs_p; \ + if (_hs_p){ \ + _hs_p = (UT_hash_handle*)((_hs_p->next) ? \ + ((void*)((char*)(_hs_p->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + } \ + _hs_psize--; \ + } else { \ + _hs_e = _hs_q; \ + _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ + ((void*)((char*)(_hs_q->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + _hs_qsize--; \ + } \ + if ( _hs_tail ) { \ + _hs_tail->next = ((_hs_e) ? \ + ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \ + } else { \ + _hs_list = _hs_e; \ + } \ + if (_hs_e) { \ + _hs_e->prev = ((_hs_tail) ? \ + ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \ + } \ + _hs_tail = _hs_e; \ + } \ + _hs_p = _hs_q; \ + } \ + if (_hs_tail){ \ + _hs_tail->next = NULL; \ + } \ + if ( _hs_nmerges <= 1 ) { \ + _hs_looping=0; \ + (head)->hh.tbl->tail = _hs_tail; \ + DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ + } \ + _hs_insize *= 2; \ + } \ + HASH_FSCK(hh,head); \ + } \ +} while (0) + +/* This function selects items from one hash into another hash. + * The end result is that the selected items have dual presence + * in both hashes. There is no copy of the items made; rather + * they are added into the new hash through a secondary hash + * hash handle that must be present in the structure. */ +#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ +do { \ + unsigned _src_bkt, _dst_bkt; \ + void *_last_elt=NULL, *_elt; \ + UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ + ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ + if (src) { \ + for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ + for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ + _src_hh; \ + _src_hh = _src_hh->hh_next) { \ + _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ + if (cond(_elt)) { \ + _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \ + _dst_hh->key = _src_hh->key; \ + _dst_hh->keylen = _src_hh->keylen; \ + _dst_hh->hashv = _src_hh->hashv; \ + _dst_hh->prev = _last_elt; \ + _dst_hh->next = NULL; \ + if (_last_elt_hh) { _last_elt_hh->next = _elt; } \ + if (!dst) { \ + DECLTYPE_ASSIGN(dst,_elt); \ + HASH_MAKE_TABLE(hh_dst,dst); \ + } else { \ + _dst_hh->tbl = (dst)->hh_dst.tbl; \ + } \ + HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ + HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \ + (dst)->hh_dst.tbl->num_items++; \ + _last_elt = _elt; \ + _last_elt_hh = _dst_hh; \ + } \ + } \ + } \ + } \ + HASH_FSCK(hh_dst,dst); \ +} while (0) + +#define HASH_CLEAR(hh,head) \ +do { \ + if (head) { \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head)=NULL; \ + } \ +} while(0) + +#define HASH_OVERHEAD(hh,head) \ + (size_t)((((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ + ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ + (sizeof(UT_hash_table)) + \ + (HASH_BLOOM_BYTELEN))) + +#ifdef NO_DECLTYPE +#define HASH_ITER(hh,head,el,tmp) \ +for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \ + el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL)) +#else +#define HASH_ITER(hh,head,el,tmp) \ +for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \ + el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL)) +#endif + +/* obtain a count of items in the hash */ +#define HASH_COUNT(head) HASH_CNT(hh,head) +#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0) + +typedef struct UT_hash_bucket { + struct UT_hash_handle *hh_head; + unsigned count; + + /* expand_mult is normally set to 0. In this situation, the max chain length + * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If + * the bucket's chain exceeds this length, bucket expansion is triggered). + * However, setting expand_mult to a non-zero value delays bucket expansion + * (that would be triggered by additions to this particular bucket) + * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. + * (The multiplier is simply expand_mult+1). The whole idea of this + * multiplier is to reduce bucket expansions, since they are expensive, in + * situations where we know that a particular bucket tends to be overused. + * It is better to let its chain length grow to a longer yet-still-bounded + * value, than to do an O(n) bucket expansion too often. + */ + unsigned expand_mult; + +} UT_hash_bucket; + +/* random signature used only to find hash tables in external analysis */ +#define HASH_SIGNATURE 0xa0111fe1 +#define HASH_BLOOM_SIGNATURE 0xb12220f2 + +typedef struct UT_hash_table { + UT_hash_bucket *buckets; + unsigned num_buckets, log2_num_buckets; + unsigned num_items; + struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ + ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ + + /* in an ideal situation (all buckets used equally), no bucket would have + * more than ceil(#items/#buckets) items. that's the ideal chain length. */ + unsigned ideal_chain_maxlen; + + /* nonideal_items is the number of items in the hash whose chain position + * exceeds the ideal chain maxlen. these items pay the penalty for an uneven + * hash distribution; reaching them in a chain traversal takes >ideal steps */ + unsigned nonideal_items; + + /* ineffective expands occur when a bucket doubling was performed, but + * afterward, more than half the items in the hash had nonideal chain + * positions. If this happens on two consecutive expansions we inhibit any + * further expansion, as it's not helping; this happens when the hash + * function isn't a good fit for the key domain. When expansion is inhibited + * the hash will still work, albeit no longer in constant time. */ + unsigned ineff_expands, noexpand; + + uint32_t signature; /* used only to find hash tables in external analysis */ +#ifdef HASH_BLOOM + uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ + uint8_t *bloom_bv; + char bloom_nbits; +#endif + +} UT_hash_table; + +typedef struct UT_hash_handle { + struct UT_hash_table *tbl; + void *prev; /* prev element in app order */ + void *next; /* next element in app order */ + struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ + struct UT_hash_handle *hh_next; /* next hh in bucket order */ + const void *key; /* ptr to enclosing struct's key */ + unsigned keylen; /* enclosing struct's key len */ + unsigned hashv; /* result of hash-fcn(key) */ +} UT_hash_handle; + +#endif /* UTHASH_H */ Property changes on: contrib/libucl/uthash/uthash.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: contrib/libucl/uthash/utlist.h =================================================================== --- contrib/libucl/uthash/utlist.h (revision 0) +++ contrib/libucl/uthash/utlist.h (working copy) @@ -0,0 +1,757 @@ +/* +Copyright (c) 2007-2013, Troy D. Hanson http://troydhanson.github.com/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef UTLIST_H +#define UTLIST_H + +#define UTLIST_VERSION 1.9.8 + +#include + +/* + * This file contains macros to manipulate singly and doubly-linked lists. + * + * 1. LL_ macros: singly-linked lists. + * 2. DL_ macros: doubly-linked lists. + * 3. CDL_ macros: circular doubly-linked lists. + * + * To use singly-linked lists, your structure must have a "next" pointer. + * To use doubly-linked lists, your structure must "prev" and "next" pointers. + * Either way, the pointer to the head of the list must be initialized to NULL. + * + * ----------------.EXAMPLE ------------------------- + * struct item { + * int id; + * struct item *prev, *next; + * } + * + * struct item *list = NULL: + * + * int main() { + * struct item *item; + * ... allocate and populate item ... + * DL_APPEND(list, item); + * } + * -------------------------------------------------- + * + * For doubly-linked lists, the append and delete macros are O(1) + * For singly-linked lists, append and delete are O(n) but prepend is O(1) + * The sort macro is O(n log(n)) for all types of single/double/circular lists. + */ + +/* These macros use decltype or the earlier __typeof GNU extension. + As decltype is only available in newer compilers (VS2010 or gcc 4.3+ + when compiling c++ code), this code uses whatever method is needed + or, for VS2008 where neither is available, uses casting workarounds. */ +#ifdef _MSC_VER /* MS compiler */ +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ +#define LDECLTYPE(x) decltype(x) +#else /* VS2008 or older (or VS2010 in C mode) */ +#define NO_DECLTYPE +#define LDECLTYPE(x) char* +#endif +#elif defined(__ICCARM__) +#define NO_DECLTYPE +#define LDECLTYPE(x) char* +#else /* GNU, Sun and other compilers */ +#define LDECLTYPE(x) __typeof(x) +#endif + +/* for VS2008 we use some workarounds to get around the lack of decltype, + * namely, we always reassign our tmp variable to the list head if we need + * to dereference its prev/next pointers, and save/restore the real head.*/ +#ifdef NO_DECLTYPE +#define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); } +#define _NEXT(elt,list,next) ((char*)((list)->next)) +#define _NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); } +/* #define _PREV(elt,list,prev) ((char*)((list)->prev)) */ +#define _PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); } +#define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; } +#define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); } +#else +#define _SV(elt,list) +#define _NEXT(elt,list,next) ((elt)->next) +#define _NEXTASGN(elt,list,to,next) ((elt)->next)=(to) +/* #define _PREV(elt,list,prev) ((elt)->prev) */ +#define _PREVASGN(elt,list,to,prev) ((elt)->prev)=(to) +#define _RS(list) +#define _CASTASGN(a,b) (a)=(b) +#endif + +/****************************************************************************** + * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort * + * Unwieldy variable names used here to avoid shadowing passed-in variables. * + *****************************************************************************/ +#define LL_SORT(list, cmp) \ + LL_SORT2(list, cmp, next) + +#define LL_SORT2(list, cmp, next) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + _CASTASGN(_ls_p,list); \ + list = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \ + _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \ + _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \ + _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \ + } else { \ + _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \ + _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \ + } \ + if (_ls_tail) { \ + _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \ + } else { \ + _CASTASGN(list,_ls_e); \ + } \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + if (_ls_tail) { \ + _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \ + } \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ +} while (0) + + +#define DL_SORT(list, cmp) \ + DL_SORT2(list, cmp, prev, next) + +#define DL_SORT2(list, cmp, prev, next) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + _CASTASGN(_ls_p,list); \ + list = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \ + _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \ + _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \ + _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \ + } else { \ + _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \ + _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \ + } \ + if (_ls_tail) { \ + _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \ + } else { \ + _CASTASGN(list,_ls_e); \ + } \ + _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + _CASTASGN(list->prev, _ls_tail); \ + _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ +} while (0) + +#define CDL_SORT(list, cmp) \ + CDL_SORT2(list, cmp, prev, next) + +#define CDL_SORT2(list, cmp, prev, next) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + LDECLTYPE(list) _ls_oldhead; \ + LDECLTYPE(list) _tmp; \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + _CASTASGN(_ls_p,list); \ + _CASTASGN(_ls_oldhead,list); \ + list = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + _SV(_ls_q,list); \ + if (_NEXT(_ls_q,list,next) == _ls_oldhead) { \ + _ls_q = NULL; \ + } else { \ + _ls_q = _NEXT(_ls_q,list,next); \ + } \ + _RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \ + _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \ + if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \ + _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \ + if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \ + _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \ + if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ + } else { \ + _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \ + _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \ + if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ + } \ + if (_ls_tail) { \ + _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \ + } else { \ + _CASTASGN(list,_ls_e); \ + } \ + _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + _CASTASGN(list->prev,_ls_tail); \ + _CASTASGN(_tmp,list); \ + _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp,next); _RS(list); \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ +} while (0) + +/****************************************************************************** + * singly linked list macros (non-circular) * + *****************************************************************************/ +#define LL_PREPEND(head,add) \ + LL_PREPEND2(head,add,next) + +#define LL_PREPEND2(head,add,next) \ +do { \ + (add)->next = head; \ + head = add; \ +} while (0) + +#define LL_CONCAT(head1,head2) \ + LL_CONCAT2(head1,head2,next) + +#define LL_CONCAT2(head1,head2,next) \ +do { \ + LDECLTYPE(head1) _tmp; \ + if (head1) { \ + _tmp = head1; \ + while (_tmp->next) { _tmp = _tmp->next; } \ + _tmp->next=(head2); \ + } else { \ + (head1)=(head2); \ + } \ +} while (0) + +#define LL_APPEND(head,add) \ + LL_APPEND2(head,add,next) + +#define LL_APPEND2(head,add,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + (add)->next=NULL; \ + if (head) { \ + _tmp = head; \ + while (_tmp->next) { _tmp = _tmp->next; } \ + _tmp->next=(add); \ + } else { \ + (head)=(add); \ + } \ +} while (0) + +#define LL_DELETE(head,del) \ + LL_DELETE2(head,del,next) + +#define LL_DELETE2(head,del,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if ((head) == (del)) { \ + (head)=(head)->next; \ + } else { \ + _tmp = head; \ + while (_tmp->next && (_tmp->next != (del))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = ((del)->next); \ + } \ + } \ +} while (0) + +/* Here are VS2008 replacements for LL_APPEND and LL_DELETE */ +#define LL_APPEND_VS2008(head,add) \ + LL_APPEND2_VS2008(head,add,next) + +#define LL_APPEND2_VS2008(head,add,next) \ +do { \ + if (head) { \ + (add)->next = head; /* use add->next as a temp variable */ \ + while ((add)->next->next) { (add)->next = (add)->next->next; } \ + (add)->next->next=(add); \ + } else { \ + (head)=(add); \ + } \ + (add)->next=NULL; \ +} while (0) + +#define LL_DELETE_VS2008(head,del) \ + LL_DELETE2_VS2008(head,del,next) + +#define LL_DELETE2_VS2008(head,del,next) \ +do { \ + if ((head) == (del)) { \ + (head)=(head)->next; \ + } else { \ + char *_tmp = (char*)(head); \ + while ((head)->next && ((head)->next != (del))) { \ + head = (head)->next; \ + } \ + if ((head)->next) { \ + (head)->next = ((del)->next); \ + } \ + { \ + char **_head_alias = (char**)&(head); \ + *_head_alias = _tmp; \ + } \ + } \ +} while (0) +#ifdef NO_DECLTYPE +#undef LL_APPEND +#define LL_APPEND LL_APPEND_VS2008 +#undef LL_DELETE +#define LL_DELETE LL_DELETE_VS2008 +#undef LL_DELETE2 +#define LL_DELETE2 LL_DELETE2_VS2008 +#undef LL_APPEND2 +#define LL_APPEND2 LL_APPEND2_VS2008 +#undef LL_CONCAT /* no LL_CONCAT_VS2008 */ +#undef DL_CONCAT /* no DL_CONCAT_VS2008 */ +#endif +/* end VS2008 replacements */ + +#define LL_COUNT(head,el,counter) \ + LL_COUNT2(head,el,counter,next) \ + +#define LL_COUNT2(head,el,counter,next) \ +{ \ + counter = 0; \ + LL_FOREACH2(head,el,next){ ++counter; } \ +} + +#define LL_FOREACH(head,el) \ + LL_FOREACH2(head,el,next) + +#define LL_FOREACH2(head,el,next) \ + for(el=head;el;el=(el)->next) + +#define LL_FOREACH_SAFE(head,el,tmp) \ + LL_FOREACH_SAFE2(head,el,tmp,next) + +#define LL_FOREACH_SAFE2(head,el,tmp,next) \ + for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp) + +#define LL_SEARCH_SCALAR(head,out,field,val) \ + LL_SEARCH_SCALAR2(head,out,field,val,next) + +#define LL_SEARCH_SCALAR2(head,out,field,val,next) \ +do { \ + LL_FOREACH2(head,out,next) { \ + if ((out)->field == (val)) break; \ + } \ +} while(0) + +#define LL_SEARCH(head,out,elt,cmp) \ + LL_SEARCH2(head,out,elt,cmp,next) + +#define LL_SEARCH2(head,out,elt,cmp,next) \ +do { \ + LL_FOREACH2(head,out,next) { \ + if ((cmp(out,elt))==0) break; \ + } \ +} while(0) + +#define LL_REPLACE_ELEM(head, el, add) \ +do { \ + LDECLTYPE(head) _tmp; \ + assert(head != NULL); \ + assert(el != NULL); \ + assert(add != NULL); \ + (add)->next = (el)->next; \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + _tmp = head; \ + while (_tmp->next && (_tmp->next != (el))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (add); \ + } \ + } \ +} while (0) + +#define LL_PREPEND_ELEM(head, el, add) \ +do { \ + LDECLTYPE(head) _tmp; \ + assert(head != NULL); \ + assert(el != NULL); \ + assert(add != NULL); \ + (add)->next = (el); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + _tmp = head; \ + while (_tmp->next && (_tmp->next != (el))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (add); \ + } \ + } \ +} while (0) \ + + +/****************************************************************************** + * doubly linked list macros (non-circular) * + *****************************************************************************/ +#define DL_PREPEND(head,add) \ + DL_PREPEND2(head,add,prev,next) + +#define DL_PREPEND2(head,add,prev,next) \ +do { \ + (add)->next = head; \ + if (head) { \ + (add)->prev = (head)->prev; \ + (head)->prev = (add); \ + } else { \ + (add)->prev = (add); \ + } \ + (head) = (add); \ +} while (0) + +#define DL_APPEND(head,add) \ + DL_APPEND2(head,add,prev,next) + +#define DL_APPEND2(head,add,prev,next) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (head)->prev->next = (add); \ + (head)->prev = (add); \ + (add)->next = NULL; \ + } else { \ + (head)=(add); \ + (head)->prev = (head); \ + (head)->next = NULL; \ + } \ +} while (0) + +#define DL_CONCAT(head1,head2) \ + DL_CONCAT2(head1,head2,prev,next) + +#define DL_CONCAT2(head1,head2,prev,next) \ +do { \ + LDECLTYPE(head1) _tmp; \ + if (head2) { \ + if (head1) { \ + _tmp = (head2)->prev; \ + (head2)->prev = (head1)->prev; \ + (head1)->prev->next = (head2); \ + (head1)->prev = _tmp; \ + } else { \ + (head1)=(head2); \ + } \ + } \ +} while (0) + +#define DL_DELETE(head,del) \ + DL_DELETE2(head,del,prev,next) + +#define DL_DELETE2(head,del,prev,next) \ +do { \ + assert((del)->prev != NULL); \ + if ((del)->prev == (del)) { \ + (head)=NULL; \ + } else if ((del)==(head)) { \ + (del)->next->prev = (del)->prev; \ + (head) = (del)->next; \ + } else { \ + (del)->prev->next = (del)->next; \ + if ((del)->next) { \ + (del)->next->prev = (del)->prev; \ + } else { \ + (head)->prev = (del)->prev; \ + } \ + } \ +} while (0) + +#define DL_COUNT(head,el,counter) \ + DL_COUNT2(head,el,counter,next) \ + +#define DL_COUNT2(head,el,counter,next) \ +{ \ + counter = 0; \ + DL_FOREACH2(head,el,next){ ++counter; } \ +} + +#define DL_FOREACH(head,el) \ + DL_FOREACH2(head,el,next) + +#define DL_FOREACH2(head,el,next) \ + for(el=head;el;el=(el)->next) + +/* this version is safe for deleting the elements during iteration */ +#define DL_FOREACH_SAFE(head,el,tmp) \ + DL_FOREACH_SAFE2(head,el,tmp,next) + +#define DL_FOREACH_SAFE2(head,el,tmp,next) \ + for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp) + +/* these are identical to their singly-linked list counterparts */ +#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR +#define DL_SEARCH LL_SEARCH +#define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2 +#define DL_SEARCH2 LL_SEARCH2 + +#define DL_REPLACE_ELEM(head, el, add) \ +do { \ + assert(head != NULL); \ + assert(el != NULL); \ + assert(add != NULL); \ + if ((head) == (el)) { \ + (head) = (add); \ + (add)->next = (el)->next; \ + if ((el)->next == NULL) { \ + (add)->prev = (add); \ + } else { \ + (add)->prev = (el)->prev; \ + (add)->next->prev = (add); \ + } \ + } else { \ + (add)->next = (el)->next; \ + (add)->prev = (el)->prev; \ + (add)->prev->next = (add); \ + if ((el)->next == NULL) { \ + (head)->prev = (add); \ + } else { \ + (add)->next->prev = (add); \ + } \ + } \ +} while (0) + +#define DL_PREPEND_ELEM(head, el, add) \ +do { \ + assert(head != NULL); \ + assert(el != NULL); \ + assert(add != NULL); \ + (add)->next = (el); \ + (add)->prev = (el)->prev; \ + (el)->prev = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->prev->next = (add); \ + } \ +} while (0) \ + + +/****************************************************************************** + * circular doubly linked list macros * + *****************************************************************************/ +#define CDL_PREPEND(head,add) \ + CDL_PREPEND2(head,add,prev,next) + +#define CDL_PREPEND2(head,add,prev,next) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (add)->prev->next = (add); \ + } else { \ + (add)->prev = (add); \ + (add)->next = (add); \ + } \ +(head)=(add); \ +} while (0) + +#define CDL_DELETE(head,del) \ + CDL_DELETE2(head,del,prev,next) + +#define CDL_DELETE2(head,del,prev,next) \ +do { \ + if ( ((head)==(del)) && ((head)->next == (head))) { \ + (head) = 0L; \ + } else { \ + (del)->next->prev = (del)->prev; \ + (del)->prev->next = (del)->next; \ + if ((del) == (head)) (head)=(del)->next; \ + } \ +} while (0) + +#define CDL_COUNT(head,el,counter) \ + CDL_COUNT2(head,el,counter,next) \ + +#define CDL_COUNT2(head, el, counter,next) \ +{ \ + counter = 0; \ + CDL_FOREACH2(head,el,next){ ++counter; } \ +} + +#define CDL_FOREACH(head,el) \ + CDL_FOREACH2(head,el,next) + +#define CDL_FOREACH2(head,el,next) \ + for(el=head;el;el=((el)->next==head ? 0L : (el)->next)) + +#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \ + CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) + +#define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \ + for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \ + (el) && ((tmp2)=(el)->next, 1); \ + ((el) = (((el)==(tmp1)) ? 0L : (tmp2)))) + +#define CDL_SEARCH_SCALAR(head,out,field,val) \ + CDL_SEARCH_SCALAR2(head,out,field,val,next) + +#define CDL_SEARCH_SCALAR2(head,out,field,val,next) \ +do { \ + CDL_FOREACH2(head,out,next) { \ + if ((out)->field == (val)) break; \ + } \ +} while(0) + +#define CDL_SEARCH(head,out,elt,cmp) \ + CDL_SEARCH2(head,out,elt,cmp,next) + +#define CDL_SEARCH2(head,out,elt,cmp,next) \ +do { \ + CDL_FOREACH2(head,out,next) { \ + if ((cmp(out,elt))==0) break; \ + } \ +} while(0) + +#define CDL_REPLACE_ELEM(head, el, add) \ +do { \ + assert(head != NULL); \ + assert(el != NULL); \ + assert(add != NULL); \ + if ((el)->next == (el)) { \ + (add)->next = (add); \ + (add)->prev = (add); \ + (head) = (add); \ + } else { \ + (add)->next = (el)->next; \ + (add)->prev = (el)->prev; \ + (add)->next->prev = (add); \ + (add)->prev->next = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } \ + } \ +} while (0) + +#define CDL_PREPEND_ELEM(head, el, add) \ +do { \ + assert(head != NULL); \ + assert(el != NULL); \ + assert(add != NULL); \ + (add)->next = (el); \ + (add)->prev = (el)->prev; \ + (el)->prev = (add); \ + (add)->prev->next = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } \ +} while (0) \ + +#endif /* UTLIST_H */ + Property changes on: contrib/libucl/uthash/utlist.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: contrib/libucl/uthash/utstring.h =================================================================== --- contrib/libucl/uthash/utstring.h (revision 0) +++ contrib/libucl/uthash/utstring.h (working copy) @@ -0,0 +1,410 @@ +/* +Copyright (c) 2008-2013, Troy D. Hanson http://troydhanson.github.com/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* a dynamic string implementation using macros + */ +#ifndef UTSTRING_H +#define UTSTRING_H + +#define UTSTRING_VERSION 1.9.8 + +#ifdef __GNUC__ +#define _UNUSED_ __attribute__ ((__unused__)) +#else +#define _UNUSED_ +#endif + +#include +#include +#include + +#ifndef oom +#define oom() exit(-1) +#endif + +typedef struct { + char *d; + size_t n; /* allocd size */ + size_t i; /* index of first unused byte */ +} UT_string; + +#define utstring_reserve(s,amt) \ +do { \ + if (((s)->n - (s)->i) < (size_t)(amt)) { \ + (s)->d = (char*)realloc((s)->d, (s)->n + amt); \ + if ((s)->d == NULL) oom(); \ + (s)->n += amt; \ + } \ +} while(0) + +#define utstring_init(s) \ +do { \ + (s)->n = 0; (s)->i = 0; (s)->d = NULL; \ + utstring_reserve(s,128); \ + (s)->d[0] = '\0'; \ +} while(0) + +#define utstring_done(s) \ +do { \ + if ((s)->d != NULL) free((s)->d); \ + (s)->n = 0; \ +} while(0) + +#define utstring_free(s) \ +do { \ + utstring_done(s); \ + free(s); \ +} while(0) + +#define utstring_new(s) \ +do { \ + s = (UT_string*)calloc(sizeof(UT_string),1); \ + if (!s) oom(); \ + utstring_init(s); \ +} while(0) + +#define utstring_renew(s) \ +do { \ + if (s) { \ + utstring_clear(s); \ + } else { \ + utstring_new(s); \ + } \ +} while(0) + +#define utstring_clear(s) \ +do { \ + (s)->i = 0; \ + (s)->d[0] = '\0'; \ +} while(0) + +#define utstring_bincpy(s,b,l) \ +do { \ + utstring_reserve((s),(l)+1); \ + if (l) memcpy(&(s)->d[(s)->i], b, l); \ + (s)->i += l; \ + (s)->d[(s)->i]='\0'; \ +} while(0) + +#define utstring_concat(dst,src) \ +do { \ + utstring_reserve((dst),((src)->i)+1); \ + if ((src)->i) memcpy(&(dst)->d[(dst)->i], (src)->d, (src)->i); \ + (dst)->i += (src)->i; \ + (dst)->d[(dst)->i]='\0'; \ +} while(0) + +#define utstring_len(s) ((unsigned)((s)->i)) + +#define utstring_body(s) ((s)->d) + +_UNUSED_ static void utstring_printf_va(UT_string *s, const char *fmt, va_list ap) { + int n; + va_list cp; + while (1) { +#ifdef _WIN32 + cp = ap; +#else + va_copy(cp, ap); +#endif + n = vsnprintf (&s->d[s->i], s->n-s->i, fmt, cp); + va_end(cp); + + if ((n > -1) && (n < (int)(s->n-s->i))) { + s->i += n; + return; + } + + /* Else try again with more space. */ + if (n > -1) utstring_reserve(s,n+1); /* exact */ + else utstring_reserve(s,(s->n)*2); /* 2x */ + } +} +#ifdef __GNUC__ +/* support printf format checking (2=the format string, 3=start of varargs) */ +static void utstring_printf(UT_string *s, const char *fmt, ...) + __attribute__ (( format( printf, 2, 3) )); +#endif +_UNUSED_ static void utstring_printf(UT_string *s, const char *fmt, ...) { + va_list ap; + va_start(ap,fmt); + utstring_printf_va(s,fmt,ap); + va_end(ap); +} + +#define utstring_append_len(dst, src, len) \ +do { \ + while ((dst)->n-(dst)->i <= (len)) utstring_reserve((dst),((dst)->n)*2); \ + memcpy(&(dst)->d[(dst)->i], (src), (len)); \ + (dst)->i+=(len); \ + (dst)->d[(dst)->i]='\0'; \ +} while(0) + +#define utstring_append_c(dst, c) \ +do { \ + if ((dst)->n-(dst)->i < 2) utstring_reserve((dst),((dst)->n)*2); \ + (dst)->d[(dst)->i++] = (c); \ + (dst)->d[(dst)->i]='\0'; \ +} while(0) + +/******************************************************************************* + * begin substring search functions * + ******************************************************************************/ +/* Build KMP table from left to right. */ +_UNUSED_ static void _utstring_BuildTable( + const char *P_Needle, + ssize_t P_NeedleLen, + long *P_KMP_Table) +{ + long i, j; + + i = 0; + j = i - 1; + P_KMP_Table[i] = j; + while (i < P_NeedleLen) + { + while ( (j > -1) && (P_Needle[i] != P_Needle[j]) ) + { + j = P_KMP_Table[j]; + } + i++; + j++; + if (i < P_NeedleLen) + { + if (P_Needle[i] == P_Needle[j]) + { + P_KMP_Table[i] = P_KMP_Table[j]; + } + else + { + P_KMP_Table[i] = j; + } + } + else + { + P_KMP_Table[i] = j; + } + } + + return; +} + + +/* Build KMP table from right to left. */ +_UNUSED_ static void _utstring_BuildTableR( + const char *P_Needle, + ssize_t P_NeedleLen, + long *P_KMP_Table) +{ + long i, j; + + i = P_NeedleLen - 1; + j = i + 1; + P_KMP_Table[i + 1] = j; + while (i >= 0) + { + while ( (j < P_NeedleLen) && (P_Needle[i] != P_Needle[j]) ) + { + j = P_KMP_Table[j + 1]; + } + i--; + j--; + if (i >= 0) + { + if (P_Needle[i] == P_Needle[j]) + { + P_KMP_Table[i + 1] = P_KMP_Table[j + 1]; + } + else + { + P_KMP_Table[i + 1] = j; + } + } + else + { + P_KMP_Table[i + 1] = j; + } + } + + return; +} + + +/* Search data from left to right. ( Multiple search mode. ) */ +_UNUSED_ static long _utstring_find( + const char *P_Haystack, + size_t P_HaystackLen, + const char *P_Needle, + size_t P_NeedleLen, + long *P_KMP_Table) +{ + long i, j; + long V_FindPosition = -1; + + /* Search from left to right. */ + i = j = 0; + while ( (j < (int)P_HaystackLen) && (((P_HaystackLen - j) + i) >= P_NeedleLen) ) + { + while ( (i > -1) && (P_Needle[i] != P_Haystack[j]) ) + { + i = P_KMP_Table[i]; + } + i++; + j++; + if (i >= (int)P_NeedleLen) + { + /* Found. */ + V_FindPosition = j - i; + break; + } + } + + return V_FindPosition; +} + + +/* Search data from right to left. ( Multiple search mode. ) */ +_UNUSED_ static long _utstring_findR( + const char *P_Haystack, + size_t P_HaystackLen, + const char *P_Needle, + size_t P_NeedleLen, + long *P_KMP_Table) +{ + long i, j; + long V_FindPosition = -1; + + /* Search from right to left. */ + j = (P_HaystackLen - 1); + i = (P_NeedleLen - 1); + while ( (j >= 0) && (j >= i) ) + { + while ( (i < (int)P_NeedleLen) && (P_Needle[i] != P_Haystack[j]) ) + { + i = P_KMP_Table[i + 1]; + } + i--; + j--; + if (i < 0) + { + /* Found. */ + V_FindPosition = j + 1; + break; + } + } + + return V_FindPosition; +} + + +/* Search data from left to right. ( One time search mode. ) */ +_UNUSED_ static long utstring_find( + UT_string *s, + long P_StartPosition, /* Start from 0. -1 means last position. */ + const char *P_Needle, + ssize_t P_NeedleLen) +{ + long V_StartPosition; + long V_HaystackLen; + long *V_KMP_Table; + long V_FindPosition = -1; + + if (P_StartPosition < 0) + { + V_StartPosition = s->i + P_StartPosition; + } + else + { + V_StartPosition = P_StartPosition; + } + V_HaystackLen = s->i - V_StartPosition; + if ( (V_HaystackLen >= P_NeedleLen) && (P_NeedleLen > 0) ) + { + V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1)); + if (V_KMP_Table != NULL) + { + _utstring_BuildTable(P_Needle, P_NeedleLen, V_KMP_Table); + + V_FindPosition = _utstring_find(s->d + V_StartPosition, + V_HaystackLen, + P_Needle, + P_NeedleLen, + V_KMP_Table); + if (V_FindPosition >= 0) + { + V_FindPosition += V_StartPosition; + } + + free(V_KMP_Table); + } + } + + return V_FindPosition; +} + + +/* Search data from right to left. ( One time search mode. ) */ +_UNUSED_ static long utstring_findR( + UT_string *s, + long P_StartPosition, /* Start from 0. -1 means last position. */ + const char *P_Needle, + ssize_t P_NeedleLen) +{ + long V_StartPosition; + long V_HaystackLen; + long *V_KMP_Table; + long V_FindPosition = -1; + + if (P_StartPosition < 0) + { + V_StartPosition = s->i + P_StartPosition; + } + else + { + V_StartPosition = P_StartPosition; + } + V_HaystackLen = V_StartPosition + 1; + if ( (V_HaystackLen >= P_NeedleLen) && (P_NeedleLen > 0) ) + { + V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1)); + if (V_KMP_Table != NULL) + { + _utstring_BuildTableR(P_Needle, P_NeedleLen, V_KMP_Table); + + V_FindPosition = _utstring_findR(s->d, + V_HaystackLen, + P_Needle, + P_NeedleLen, + V_KMP_Table); + + free(V_KMP_Table); + } + } + + return V_FindPosition; +} +/******************************************************************************* + * end substring search functions * + ******************************************************************************/ + +#endif /* UTSTRING_H */ Property changes on: contrib/libucl/uthash/utstring.h ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: contrib/libucl/utils/chargen.c =================================================================== --- contrib/libucl/utils/chargen.c (revision 0) +++ contrib/libucl/utils/chargen.c (working copy) @@ -0,0 +1,128 @@ +/* Copyright (c) 2013, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file this utility generates character table for ucl + */ + +#include +#include +#include + +static inline int +print_flag (const char *flag, bool *need_or, char *val) +{ + int res; + res = sprintf (val, "%s%s", *need_or ? "|" : "", flag); + + *need_or |= true; + + return res; +} + +int +main (int argc, char **argv) +{ + int i, col, r; + const char *name = "ucl_chartable"; + bool need_or; + char valbuf[2048]; + + col = 0; + + if (argc > 1) { + name = argv[1]; + } + + printf ("static const unsigned int %s[255] = {\n", name); + + for (i = 0; i < 255; i ++) { + need_or = false; + r = 0; + /* UCL_CHARACTER_VALUE_END */ + + if (i == ' ' || i == '\t') { + r += print_flag ("UCL_CHARACTER_WHITESPACE", &need_or, valbuf + r); + } + if (isspace (i)) { + r += print_flag ("UCL_CHARACTER_WHITESPACE_UNSAFE", &need_or, valbuf + r); + } + if (isalnum (i) || i >= 0x80 || i == '/' || i == '_') { + r += print_flag ("UCL_CHARACTER_KEY_START", &need_or, valbuf + r); + } + if (isalnum (i) || i == '-' || i == '_' || i == '/' || i == '.' || i >= 0x80) { + r += print_flag ("UCL_CHARACTER_KEY", &need_or, valbuf + r); + } + if (i == 0 || i == '\r' || i == '\n' || i == ']' || i == '}' || i == ';' || i == ',' || i == '#') { + r += print_flag ("UCL_CHARACTER_VALUE_END", &need_or, valbuf + r); + } + else { + if (isprint (i) || i >= 0x80) { + r += print_flag ("UCL_CHARACTER_VALUE_STR", &need_or, valbuf + r); + } + if (isdigit (i) || i == '-') { + r += print_flag ("UCL_CHARACTER_VALUE_DIGIT_START", &need_or, valbuf + r); + } + if (isalnum (i) || i == '.' || i == '-' || i == '+') { + r += print_flag ("UCL_CHARACTER_VALUE_DIGIT", &need_or, valbuf + r); + } + } + if (i == '"' || i == '\\' || i == '/' || i == 'b' || + i == 'f' || i == 'n' || i == 'r' || i == 't' || i == 'u') { + r += print_flag ("UCL_CHARACTER_ESCAPE", &need_or, valbuf + r); + } + if (i == ' ' || i == '\t' || i == ':' || i == '=') { + r += print_flag ("UCL_CHARACTER_KEY_SEP", &need_or, valbuf + r); + } + if (i == '\n' || i == '\r' || i == '\\' || i == '\b' || i == '\t' || + i == '"' || i == '\f') { + r += print_flag ("UCL_CHARACTER_JSON_UNSAFE", &need_or, valbuf + r); + } + if (i == '\n' || i == '\r' || i == '\\' || i == '\b' || i == '\t' || + i == '"' || i == '\f' || i == '=' || i == ':' || i == '{' || i == '[' || i == ' ') { + r += print_flag ("UCL_CHARACTER_UCL_UNSAFE", &need_or, valbuf + r); + } + + if (!need_or) { + r += print_flag ("UCL_CHARACTER_DENIED", &need_or, valbuf + r); + } + + if (isprint (i)) { + r += sprintf (valbuf + r, " /* %c */", i); + } + if (i != 254) { + r += sprintf (valbuf + r, ", "); + } + col += r; + if (col > 80) { + printf ("\n%s", valbuf); + col = r; + } + else { + printf ("%s", valbuf); + } + } + printf ("\n}\n"); + + return 0; +} Property changes on: contrib/libucl/utils/chargen.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: contrib/libucl/utils/objdump.c =================================================================== --- contrib/libucl/utils/objdump.c (revision 0) +++ contrib/libucl/utils/objdump.c (working copy) @@ -0,0 +1,159 @@ +/* Copyright (c) 2013, Dmitriy V. Reshetnikov + * Copyright (c) 2013, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "ucl.h" + +void +ucl_obj_dump(ucl_object_t *obj, unsigned int shift) +{ + int num = shift * 4 + 5; + char *pre = (char *) malloc (num * sizeof(char)); + ucl_object_t *cur, *tmp; + ucl_object_iter_t it = NULL, it_obj = NULL; + + pre[--num] = 0x00; + while (num--) + pre[num] = 0x20; + + tmp = obj; + + while ((obj = ucl_iterate_object (tmp, &it, false))) { + printf ("%sucl object address: %p\n", pre + 4, obj); + if (obj->key != NULL) { + printf ("%skey: \"%s\"\n", pre, ucl_object_key (obj)); + } + printf ("%sref: %hd\n", pre, obj->ref); + printf ("%slen: %zd\n", pre, obj->len); + printf ("%sprev: %p\n", pre, obj->prev); + printf ("%snext: %p\n", pre, obj->next); + if (obj->type == UCL_OBJECT) { + printf ("%stype: UCL_OBJECT\n", pre); + printf ("%svalue: %p\n", pre, obj->value.ov); + while ((cur = ucl_iterate_object (obj, &it_obj, true))) { + ucl_obj_dump (cur, shift + 2); + } + } + else if (obj->type == UCL_ARRAY) { + printf ("%stype: UCL_ARRAY\n", pre); + printf ("%svalue: %p\n", pre, obj->value.av); + ucl_obj_dump (obj->value.av, shift + 2); + } + else if (obj->type == UCL_INT) { + printf ("%stype: UCL_INT\n", pre); + printf ("%svalue: %ld\n", pre, ucl_object_toint (obj)); + } + else if (obj->type == UCL_FLOAT) { + printf ("%stype: UCL_FLOAT\n", pre); + printf ("%svalue: %f\n", pre, ucl_object_todouble (obj)); + } + else if (obj->type == UCL_STRING) { + printf ("%stype: UCL_STRING\n", pre); + printf ("%svalue: \"%s\"\n", pre, ucl_object_tostring (obj)); + } + else if (obj->type == UCL_BOOLEAN) { + printf ("%stype: UCL_BOOLEAN\n", pre); + printf ("%svalue: %s\n", pre, ucl_object_tostring_forced (obj)); + } + else if (obj->type == UCL_TIME) { + printf ("%stype: UCL_TIME\n", pre); + printf ("%svalue: %f\n", pre, ucl_object_todouble (obj)); + } + else if (obj->type == UCL_USERDATA) { + printf ("%stype: UCL_USERDATA\n", pre); + printf ("%svalue: %p\n", pre, obj->value.ud); + } + } + + free (pre); +} + +int +main(int argc, char **argv) +{ + const char *fn = NULL; + char inbuf[8192]; + struct ucl_parser *parser; + int k, ret = 0; + ucl_object_t *obj = NULL; + ucl_object_t *par; + FILE *in; + + if (argc > 1) { + fn = argv[1]; + } + + if (fn != NULL) { + in = fopen (fn, "r"); + if (in == NULL) { + exit (-errno); + } + } + else { + in = stdin; + } + + parser = ucl_parser_new (0); + while (!feof (in)) { + fread (inbuf, sizeof (inbuf), 1, in); + ucl_parser_add_chunk (parser, inbuf, strlen (inbuf)); + } + fclose (in); + if (ucl_parser_get_error(parser)) { + printf ("Error occured: %s\n", ucl_parser_get_error(parser)); + ret = 1; + goto end; + } + + obj = ucl_parser_get_object (parser); + if (ucl_parser_get_error(parser)) { + printf ("Error occured: %s\n", ucl_parser_get_error(parser)); + ret = 1; + goto end; + } + + if (argc > 2) { + for (k = 2; k < argc; k++) { + printf ("search for \"%s\"... ", argv[k]); + par = ucl_object_find_key (obj, argv[k]); + printf ("%sfound\n", (par == NULL )?"not ":""); + ucl_obj_dump (par, 0); + } + } + else { + ucl_obj_dump (obj, 0); + } + +end: + if (parser != NULL) { + ucl_parser_free (parser); + } + if (obj != NULL) { + ucl_object_unref (obj); + } + + return ret; +} Property changes on: contrib/libucl/utils/objdump.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: lib/Makefile =================================================================== --- lib/Makefile (revision 260605) +++ lib/Makefile (working copy) @@ -119,6 +119,7 @@ ${_libtelnet} \ ${_libthr} \ libthread_db \ + libucl \ libufs \ libugidfw \ libulog \ Index: lib/libucl/Makefile =================================================================== --- lib/libucl/Makefile (revision 0) +++ lib/libucl/Makefile (working copy) @@ -0,0 +1,20 @@ + +LIBUCL= ${.CURDIR}/../../contrib/libucl + +LIB= ucl +PRIVATELIB= true +SHLIB_MAJOR= 1 +SRCS= ucl_emitter.c \ + ucl_hash.c \ + ucl_parser.c \ + ucl_util.c \ + xxhash.c + +.PATH: ${LIBUCL}/src + +WARNS= 3 +CFLAGS+= -I${LIBUCL}/include \ + -I${LIBUCL}/src \ + -I${LIBUCL}/uthash + +.include Property changes on: lib/libucl/Makefile ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property