Adding upstream version 3.1.0+dfsg.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
64dbec996d
commit
cfcebb1a7d
569 changed files with 205393 additions and 0 deletions
3
.gitattributes
vendored
Normal file
3
.gitattributes
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
# the tests check that LF is kept as a LF in the checkout
|
||||
tests/modules/yang/ietf-netconf@*.yang -text
|
||||
tests/modules/yang/ietf-netconf-nmda@*.yang -text
|
238
.github/workflows/ci.yml
vendored
Normal file
238
.github/workflows/ci.yml
vendored
Normal file
|
@ -0,0 +1,238 @@
|
|||
name: libyang CI
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- devel
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- devel
|
||||
|
||||
jobs:
|
||||
build-unix:
|
||||
name: ${{ matrix.config.name }}
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {
|
||||
name: "Release, gcc",
|
||||
os: "ubuntu-22.04",
|
||||
build-type: "Release",
|
||||
cc: "gcc",
|
||||
options: "-DENABLE_TESTS=ON",
|
||||
packager: "sudo apt-get",
|
||||
# no expect because stdout seems to be redirected
|
||||
packages: "libcmocka-dev shunit2",
|
||||
snaps: "",
|
||||
build-cmd: "make"
|
||||
}
|
||||
- {
|
||||
name: "Release, clang",
|
||||
os: "ubuntu-22.04",
|
||||
build-type: "Release",
|
||||
cc: "clang",
|
||||
options: "-DENABLE_TESTS=ON",
|
||||
packager: "sudo apt-get",
|
||||
packages: "libcmocka-dev shunit2",
|
||||
snaps: "",
|
||||
build-cmd: "make"
|
||||
}
|
||||
- {
|
||||
name: "Debug, gcc",
|
||||
os: "ubuntu-22.04",
|
||||
build-type: "Debug",
|
||||
cc: "gcc",
|
||||
options: "",
|
||||
packager: "sudo apt-get",
|
||||
packages: "libcmocka-dev valgrind shunit2",
|
||||
snaps: "",
|
||||
build-cmd: "make"
|
||||
}
|
||||
- {
|
||||
name: "Debug, clang",
|
||||
os: "ubuntu-22.04",
|
||||
build-type: "Debug",
|
||||
cc: "clang",
|
||||
options: "",
|
||||
packager: "sudo apt-get",
|
||||
# no valgrind because it does not support DWARF5 yet generated by clang 14
|
||||
packages: "libcmocka-dev shunit2",
|
||||
snaps: "",
|
||||
build-cmd: "make"
|
||||
}
|
||||
- {
|
||||
name: "Release, macOS 11, clang",
|
||||
os: "macos-11",
|
||||
build-type: "Release",
|
||||
cc: "clang",
|
||||
options: "-DENABLE_TESTS=ON -DPATH_EXPECT=",
|
||||
packager: "brew",
|
||||
packages: "cmocka shunit2",
|
||||
snaps: "",
|
||||
build-cmd: "make"
|
||||
}
|
||||
- {
|
||||
name: "ASAN and UBSAN",
|
||||
os: "ubuntu-22.04",
|
||||
build-type: "Debug",
|
||||
cc: "clang",
|
||||
options: "-DCMAKE_C_FLAGS=-fsanitize=address,undefined -DENABLE_TESTS=ON -DENABLE_VALGRIND_TESTS=OFF",
|
||||
packager: "sudo apt-get",
|
||||
packages: "libcmocka-dev",
|
||||
snaps: "",
|
||||
build-cmd: "make"
|
||||
}
|
||||
- {
|
||||
name: "ABI Check",
|
||||
os: "ubuntu-22.04",
|
||||
build-type: "ABICheck",
|
||||
cc: "gcc",
|
||||
options: "",
|
||||
packager: "sudo apt-get",
|
||||
packages: "libcmocka-dev abi-dumper abi-compliance-checker",
|
||||
snaps: "core universal-ctags",
|
||||
build-cmd: "make abi-check"
|
||||
}
|
||||
- {
|
||||
name: "DEB Package",
|
||||
os: "ubuntu-22.04",
|
||||
build-type: "Release",
|
||||
cc: "gcc",
|
||||
options: "",
|
||||
packager: "sudo apt-get",
|
||||
packages: "cmake debhelper libcmocka-dev python3-pip",
|
||||
snaps: "",
|
||||
build-cmd: ""
|
||||
}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@main
|
||||
with:
|
||||
fetch-depth: 100
|
||||
|
||||
- name: Deps-packages
|
||||
shell: bash
|
||||
run: |
|
||||
${{ matrix.config.packager }} update
|
||||
if ${{ matrix.config.packages != '' }}
|
||||
then ${{ matrix.config.packager }} install ${{ matrix.config.packages }}
|
||||
fi
|
||||
if ${{ matrix.config.snaps != '' }}
|
||||
then sudo snap install ${{ matrix.config.snaps }}
|
||||
fi
|
||||
|
||||
- name: Deps-uncrustify
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
git clone --branch uncrustify-0.77.1 https://github.com/uncrustify/uncrustify
|
||||
cd uncrustify
|
||||
mkdir build
|
||||
cd build
|
||||
CC=${{ matrix.config.cc }} cmake ..
|
||||
make
|
||||
sudo make install
|
||||
if: ${{ matrix.config.name == 'Debug, gcc' }}
|
||||
|
||||
- name: Build-and-install-package
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
pip install apkg
|
||||
apkg system-setup
|
||||
apkg build
|
||||
apkg install
|
||||
if: ${{ matrix.config.name == 'DEB Package' }}
|
||||
|
||||
- name: Configure
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
CC=${{ matrix.config.cc }} cmake -DCMAKE_BUILD_TYPE=${{ matrix.config.build-type }} ${{ matrix.config.options }} ..
|
||||
if: ${{ matrix.config.name != 'DEB Package' }}
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}/build
|
||||
run: |
|
||||
export LC_ALL=C.UTF-8
|
||||
export PATH=/snap/bin:${{ github.workspace }}/coverity-tools/bin:$PATH
|
||||
${{ matrix.config.build-cmd }}
|
||||
if: ${{ matrix.config.name != 'DEB Package' }}
|
||||
|
||||
- name: Test
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}/build
|
||||
run: ctest --output-on-failure
|
||||
if: ${{ matrix.config.name != 'DEB Package' }}
|
||||
|
||||
build-windows:
|
||||
name: ${{ matrix.name }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: "Windows 2022 MSVC 16 LF"
|
||||
os: windows-2022
|
||||
triplet: x64-windows
|
||||
build_type: Release
|
||||
generators: "Visual Studio 17 2022"
|
||||
autocrlf: input
|
||||
eol: lf
|
||||
|
||||
- name: "Windows 2022 MSVC 16 no autoCRLF"
|
||||
os: windows-2022
|
||||
triplet: x64-windows
|
||||
build_type: Release
|
||||
generators: "Visual Studio 17 2022"
|
||||
|
||||
steps:
|
||||
- name: Unix line endings in git
|
||||
if: matrix.autocrlf
|
||||
run: |
|
||||
git config --global core.autocrlf ${{ matrix.autocrlf }}
|
||||
|
||||
- name: Unix line endings in git
|
||||
if: matrix.eol
|
||||
run: |
|
||||
git config --global core.eol ${{ matrix.eol }}
|
||||
|
||||
- uses: actions/checkout@main
|
||||
|
||||
- name: Get number of CPU cores
|
||||
id: cpu-cores
|
||||
uses: SimenB/github-actions-cpu-cores@v1
|
||||
|
||||
- name: Install Windows dependencies
|
||||
run: vcpkg install --triplet=${{ matrix.triplet }} pcre2 pthreads dirent dlfcn-win32 cmocka getopt
|
||||
|
||||
- name: Configure
|
||||
shell: bash
|
||||
run: |
|
||||
cmake \
|
||||
-S '${{ github.workspace }}/' \
|
||||
-B '${{ github.workspace }}/'../build \
|
||||
-G '${{ matrix.generators }}' \
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
|
||||
-DVCPKG_TARGET_TRIPLET=${{ matrix.triplet }} \
|
||||
-DCMAKE_TOOLCHAIN_FILE=${VCPKG_INSTALLATION_ROOT//\\//}/scripts/buildsystems/vcpkg.cmake \
|
||||
-DENABLE_TESTS=ON \
|
||||
'-DCMAKE_INSTALL_PREFIX:PATH=${{ github.workspace }}'/../target
|
||||
|
||||
- name: Build
|
||||
working-directory: '${{ github.workspace }}/../build'
|
||||
run: cmake --build . -j${{ steps.cpu-cores.outputs.count }} --config ${{ matrix.build_type }}
|
||||
|
||||
- name: Test
|
||||
working-directory: '${{ github.workspace }}/../build'
|
||||
run: ctest --output-on-failure -j${{ steps.cpu-cores.outputs.count }} --build-config ${{ matrix.build_type }}
|
||||
|
||||
- name: Install
|
||||
working-directory: '${{ github.workspace }}/../build'
|
||||
run: cmake --install . --strip
|
24
.github/workflows/cifuzz.yml
vendored
Normal file
24
.github/workflows/cifuzz.yml
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
name: CIFuzz
|
||||
on: [pull_request]
|
||||
jobs:
|
||||
Fuzzing:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Build Fuzzers
|
||||
id: build
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'libyang'
|
||||
dry-run: false
|
||||
- name: Run Fuzzers
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'libyang'
|
||||
fuzz-seconds: 300
|
||||
dry-run: false
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@v3
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
with:
|
||||
name: artifacts
|
||||
path: ./out/artifacts
|
39
.github/workflows/codeql.yml
vendored
Normal file
39
.github/workflows/codeql.yml
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master", "devel" ]
|
||||
pull_request:
|
||||
branches: [ "devel" ]
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ cpp ]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@main
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@main
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
queries: +security-and-quality
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@main
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@main
|
||||
with:
|
||||
category: "/language:${{ matrix.language }}"
|
109
.github/workflows/devel-push.yml
vendored
Normal file
109
.github/workflows/devel-push.yml
vendored
Normal file
|
@ -0,0 +1,109 @@
|
|||
name: libyang devel push
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- devel
|
||||
|
||||
env:
|
||||
COVERITY_PROJECT: CESNET%2Flibyang
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: ${{ matrix.config.name }}
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {
|
||||
name: "Coverity",
|
||||
os: "ubuntu-latest",
|
||||
build-type: "Debug",
|
||||
cc: "clang",
|
||||
options: "",
|
||||
packager: "sudo apt-get",
|
||||
packages: "",
|
||||
snaps: "",
|
||||
make-prepend: "cov-build --dir cov-int",
|
||||
make-target: ""
|
||||
}
|
||||
- {
|
||||
name: "Codecov",
|
||||
os: "ubuntu-latest",
|
||||
build-type: "Debug",
|
||||
cc: "gcc",
|
||||
options: "-DENABLE_COVERAGE=ON",
|
||||
packager: "sudo apt-get",
|
||||
packages: "libcmocka-dev lcov",
|
||||
snaps: "",
|
||||
make-prepend: "",
|
||||
make-target: ""
|
||||
}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@main
|
||||
|
||||
- name: Deps-packages
|
||||
shell: bash
|
||||
run: |
|
||||
${{ matrix.config.packager }} update
|
||||
if ${{ matrix.config.packages != '' }}
|
||||
then ${{ matrix.config.packager }} install ${{ matrix.config.packages }}
|
||||
fi
|
||||
if ${{ matrix.config.snaps != '' }}
|
||||
then sudo snap install ${{ matrix.config.snaps }}
|
||||
fi
|
||||
|
||||
- name: Deps-coverity
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
wget -q https://scan.coverity.com/download/linux64 --post-data "token=$TOKEN&project=$COVERITY_PROJECT" -O coverity-tools.tar.gz
|
||||
mkdir coverity-tools
|
||||
tar xzf coverity-tools.tar.gz --strip 1 -C coverity-tools
|
||||
env:
|
||||
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
||||
if: ${{ matrix.config.name == 'Coverity' }}
|
||||
|
||||
- name: Configure
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
CC=${{ matrix.config.cc }} cmake -DCMAKE_BUILD_TYPE=${{ matrix.config.build-type }} ${{ matrix.config.options }} ..
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}/build
|
||||
run: |
|
||||
export LC_ALL=C.UTF-8
|
||||
export PATH=/snap/bin:${{ github.workspace }}/coverity-tools/bin:$PATH
|
||||
${{ matrix.config.make-prepend }} make ${{ matrix.config.make-target }}
|
||||
|
||||
- name: Test
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}/build
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: Upload to Coverity.com
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}/build
|
||||
run: |
|
||||
tar czvf libyang.tgz cov-int
|
||||
curl \
|
||||
--form token=$TOKEN \
|
||||
--form email=mvasko@cesnet.cz \
|
||||
--form file=@libyang.tgz \
|
||||
--form version="`./yanglint -v | cut -d\" \" -f2`" \
|
||||
--form description="libyang YANG library" \
|
||||
https://scan.coverity.com/builds?project=$COVERITY_PROJECT
|
||||
env:
|
||||
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
||||
if: ${{ matrix.config.name == 'Coverity' }}
|
||||
|
||||
- name: Upload to Codecov.io
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}/build
|
||||
run: bash <(curl -s https://codecov.io/bash)
|
||||
if: ${{ matrix.config.name == 'Codecov' }}
|
6
.mailmap
Normal file
6
.mailmap
Normal file
|
@ -0,0 +1,6 @@
|
|||
David Sedlák <xsedla1d@stud.fit.vutbr.cz>
|
||||
FredGan <ganshaolong@vip.qq.com>
|
||||
Juraj Vijtiuk <juraj.vijtiuk@sartura.hr> <vijtiuk.juraj@gmail.com> <30860583+jvijtiuk@users.noreply.github.com>
|
||||
Juraj Vijtiuk <juraj.vijtiuk@sartura.hr> <30860583+jvijtiuk@users.noreply.github.com>
|
||||
Michal Vasko <mvasko@cesnet.cz>
|
||||
Radek Krejci <rkrejci@cesnet.cz>
|
491
CMakeLists.txt
Normal file
491
CMakeLists.txt
Normal file
|
@ -0,0 +1,491 @@
|
|||
if(WIN32)
|
||||
cmake_minimum_required(VERSION 3.22.0)
|
||||
else()
|
||||
cmake_minimum_required(VERSION 2.8.12...3.28.1)
|
||||
endif()
|
||||
|
||||
# force out-of-source build
|
||||
if(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR})
|
||||
message(FATAL_ERROR "In-source build is not allowed. Please make a standalone build directory and run CMake from there. You may need to remove CMakeCache.txt.")
|
||||
endif()
|
||||
|
||||
project(libyang C)
|
||||
|
||||
# include custom Modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/")
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(UseCompat)
|
||||
include(ABICheck)
|
||||
include(SourceFormat)
|
||||
include(GenDoc)
|
||||
include(GenCoverage)
|
||||
|
||||
# set default build type if not specified by user
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
endif()
|
||||
# normalize build type string
|
||||
# see https://github.com/CESNET/libyang/pull/1692 for why CMAKE_C_FLAGS_<type> are not used directly
|
||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" BUILD_TYPE_UPPER)
|
||||
if ("${BUILD_TYPE_UPPER}" STREQUAL "RELEASE")
|
||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build Type" FORCE)
|
||||
set(CMAKE_C_FLAGS "-DNDEBUG -O2 ${CMAKE_C_FLAGS}")
|
||||
elseif("${BUILD_TYPE_UPPER}" STREQUAL "DEBUG")
|
||||
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build Type" FORCE)
|
||||
set(CMAKE_C_FLAGS "-g3 -O0 ${CMAKE_C_FLAGS}")
|
||||
elseif("${BUILD_TYPE_UPPER}" STREQUAL "RELWITHDEBINFO")
|
||||
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Build Type" FORCE)
|
||||
elseif("${BUILD_TYPE_UPPER}" STREQUAL "RELWITHDEBUG")
|
||||
set(CMAKE_BUILD_TYPE "RelWithDebug" CACHE STRING "Build Type" FORCE)
|
||||
elseif("${BUILD_TYPE_UPPER}" STREQUAL "ABICHECK")
|
||||
set(CMAKE_BUILD_TYPE "ABICheck" CACHE STRING "Build Type" FORCE)
|
||||
set(CMAKE_C_FLAGS "-g -Og ${CMAKE_C_FLAGS}")
|
||||
elseif("${BUILD_TYPE_UPPER}" STREQUAL "DOCONLY")
|
||||
set(CMAKE_BUILD_TYPE "DocOnly" CACHE STRING "Build Type" FORCE)
|
||||
endif()
|
||||
|
||||
#
|
||||
# variables
|
||||
#
|
||||
|
||||
set(LIBYANG_DESCRIPTION "libyang is YANG data modelling language parser and toolkit written (and providing API) in C.")
|
||||
|
||||
# Correct RPATH usage on OS X
|
||||
set(CMAKE_MACOSX_RPATH TRUE)
|
||||
|
||||
# keep all binaries in the build directory
|
||||
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
# set version of the project
|
||||
set(LIBYANG_MAJOR_VERSION 3)
|
||||
set(LIBYANG_MINOR_VERSION 1)
|
||||
set(LIBYANG_MICRO_VERSION 0)
|
||||
set(LIBYANG_VERSION ${LIBYANG_MAJOR_VERSION}.${LIBYANG_MINOR_VERSION}.${LIBYANG_MICRO_VERSION})
|
||||
|
||||
# set version of the library
|
||||
set(LIBYANG_MAJOR_SOVERSION 3)
|
||||
set(LIBYANG_MINOR_SOVERSION 2)
|
||||
set(LIBYANG_MICRO_SOVERSION 0)
|
||||
set(LIBYANG_SOVERSION_FULL ${LIBYANG_MAJOR_SOVERSION}.${LIBYANG_MINOR_SOVERSION}.${LIBYANG_MICRO_SOVERSION})
|
||||
set(LIBYANG_SOVERSION ${LIBYANG_MAJOR_SOVERSION})
|
||||
|
||||
if(WIN32)
|
||||
set(C_STANDARD 11)
|
||||
set(C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_C_FLAGS "/Zc:preprocessor /W3 /wd4711 /w14013 /utf-8 ${CMAKE_C_FLAGS}")
|
||||
else()
|
||||
# global C flags
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic -std=c11")
|
||||
endif()
|
||||
|
||||
include_directories(${PROJECT_BINARY_DIR}/libyang ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/src/plugins_exts)
|
||||
|
||||
# type plugins are separate because they have their documentation generated
|
||||
set(type_plugins
|
||||
src/plugins_types/binary.c
|
||||
src/plugins_types/bits.c
|
||||
src/plugins_types/boolean.c
|
||||
src/plugins_types/decimal64.c
|
||||
src/plugins_types/empty.c
|
||||
src/plugins_types/enumeration.c
|
||||
src/plugins_types/identityref.c
|
||||
src/plugins_types/instanceid.c
|
||||
src/plugins_types/instanceid_keys.c
|
||||
src/plugins_types/integer.c
|
||||
src/plugins_types/leafref.c
|
||||
src/plugins_types/lyds_tree.c
|
||||
src/plugins_types/string.c
|
||||
src/plugins_types/union.c
|
||||
src/plugins_types/ipv4_address.c
|
||||
src/plugins_types/ipv4_address_no_zone.c
|
||||
src/plugins_types/ipv6_address.c
|
||||
src/plugins_types/ipv6_address_no_zone.c
|
||||
src/plugins_types/ipv4_prefix.c
|
||||
src/plugins_types/ipv6_prefix.c
|
||||
src/plugins_types/date_and_time.c
|
||||
src/plugins_types/hex_string.c
|
||||
src/plugins_types/xpath1.0.c
|
||||
src/plugins_types/node_instanceid.c)
|
||||
|
||||
set(libsrc
|
||||
src/ly_common.c
|
||||
src/log.c
|
||||
src/hash_table.c
|
||||
src/dict.c
|
||||
src/set.c
|
||||
src/path.c
|
||||
src/diff.c
|
||||
src/context.c
|
||||
src/json.c
|
||||
src/tree_data.c
|
||||
src/tree_data_free.c
|
||||
src/tree_data_common.c
|
||||
src/tree_data_hash.c
|
||||
src/tree_data_new.c
|
||||
src/parser_xml.c
|
||||
src/parser_json.c
|
||||
src/parser_lyb.c
|
||||
src/out.c
|
||||
src/printer_data.c
|
||||
src/printer_xml.c
|
||||
src/printer_json.c
|
||||
src/printer_lyb.c
|
||||
src/schema_compile.c
|
||||
src/schema_compile_node.c
|
||||
src/schema_compile_amend.c
|
||||
src/schema_features.c
|
||||
src/tree_data_sorted.c
|
||||
src/tree_schema.c
|
||||
src/tree_schema_free.c
|
||||
src/tree_schema_common.c
|
||||
src/in.c
|
||||
src/lyb.c
|
||||
src/parser_common.c
|
||||
src/parser_yang.c
|
||||
src/parser_yin.c
|
||||
src/printer_schema.c
|
||||
src/printer_yang.c
|
||||
src/printer_yin.c
|
||||
src/printer_tree.c
|
||||
src/plugins.c
|
||||
src/plugins_types.c
|
||||
src/plugins_exts.c
|
||||
src/plugins_exts/metadata.c
|
||||
src/plugins_exts/nacm.c
|
||||
src/plugins_exts/yangdata.c
|
||||
src/plugins_exts/schema_mount.c
|
||||
src/plugins_exts/structure.c
|
||||
src/xml.c
|
||||
src/xpath.c
|
||||
src/validation.c
|
||||
${type_plugins})
|
||||
|
||||
set(headers
|
||||
src/context.h
|
||||
src/hash_table.h
|
||||
src/dict.h
|
||||
src/in.h
|
||||
src/libyang.h
|
||||
src/log.h
|
||||
src/out.h
|
||||
src/parser_data.h
|
||||
src/parser_schema.h
|
||||
src/plugins.h
|
||||
src/plugins_exts.h
|
||||
src/plugins_exts/metadata.h
|
||||
src/plugins_types.h
|
||||
src/printer_data.h
|
||||
src/printer_schema.h
|
||||
src/set.h
|
||||
src/tree.h
|
||||
src/tree_data.h
|
||||
src/tree_edit.h
|
||||
src/tree_schema.h)
|
||||
|
||||
set(internal_headers
|
||||
src/ly_common.h
|
||||
src/diff.h
|
||||
src/hash_table_internal.h
|
||||
src/in_internal.h
|
||||
src/json.h
|
||||
src/lyb.h
|
||||
src/out_internal.h
|
||||
src/parser_internal.h
|
||||
src/path.h
|
||||
src/plugins_internal.h
|
||||
src/printer_internal.h
|
||||
src/schema_compile.h
|
||||
src/schema_compile_amend.h
|
||||
src/schema_compile_node.h
|
||||
src/schema_features.h
|
||||
src/tree_data_internal.h
|
||||
src/tree_schema_internal.h
|
||||
src/validation.h
|
||||
src/xml.h
|
||||
src/xpath.h)
|
||||
|
||||
set(gen_headers
|
||||
version.h
|
||||
ly_config.h)
|
||||
|
||||
# files to generate doxygen from
|
||||
set(doxy_files
|
||||
doc/build.dox
|
||||
doc/transition_1_2.dox
|
||||
doc/transition_2_3.dox
|
||||
${headers}
|
||||
${PROJECT_BINARY_DIR}/libyang/version.h
|
||||
${type_plugins})
|
||||
|
||||
# project (doxygen) logo
|
||||
set(project_logo
|
||||
doc/logo.png)
|
||||
|
||||
# source files to be covered by the 'format' target
|
||||
set(format_sources
|
||||
compat/*.c
|
||||
compat/*.h*
|
||||
src/*.c
|
||||
src/*.h
|
||||
src/plugins_exts/*
|
||||
src/plugins_types/*)
|
||||
#
|
||||
# options
|
||||
#
|
||||
|
||||
if(("${BUILD_TYPE_UPPER}" STREQUAL "DEBUG") OR ("${BUILD_TYPE_UPPER}" STREQUAL "RELWITHDEBINFO"))
|
||||
option(ENABLE_TESTS "Build tests" ON)
|
||||
option(ENABLE_VALGRIND_TESTS "Build tests with valgrind" ON)
|
||||
else()
|
||||
option(ENABLE_TESTS "Build tests" OFF)
|
||||
option(ENABLE_VALGRIND_TESTS "Build tests with valgrind" OFF)
|
||||
endif()
|
||||
option(ENABLE_PERF_TESTS "Build performance tests" OFF)
|
||||
option(ENABLE_COVERAGE "Build code coverage report from tests" OFF)
|
||||
option(ENABLE_FUZZ_TARGETS "Build target programs suitable for fuzzing with AFL" OFF)
|
||||
option(ENABLE_INTERNAL_DOCS "Generate doxygen documentation also from internal headers" OFF)
|
||||
option(ENABLE_YANGLINT_INTERACTIVE "Enable interactive CLI yanglint" ON)
|
||||
option(ENABLE_TOOLS "Build binary tools 'yanglint' and 'yangre'" ON)
|
||||
option(ENABLE_COMMON_TARGETS "Define common custom target names such as 'doc' or 'uninstall', may cause conflicts when using add_subdirectory() to build this project" ON)
|
||||
option(BUILD_SHARED_LIBS "By default, shared libs are enabled. Turn off for a static build." ON)
|
||||
set(YANG_MODULE_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/yang/modules/libyang" CACHE STRING "Directory where to copy the YANG modules to")
|
||||
|
||||
if(ENABLE_INTERNAL_DOCS)
|
||||
set(doxy_files ${doxy_files} ${internal_headers})
|
||||
set(INTERNAL_DOCS YES)
|
||||
else()
|
||||
set(INTERNAL_DOCS NO)
|
||||
endif()
|
||||
|
||||
set(LYD_VALUE_SIZE "24" CACHE STRING "Maximum size in bytes of data node values that do not need to be allocated dynamically, minimum is 8")
|
||||
if(LYD_VALUE_SIZE LESS 8)
|
||||
message(FATAL_ERROR "Data node value size \"${LYD_VALUE_SIZE}\" is not valid.")
|
||||
endif()
|
||||
set(PLUGINS_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/libyang" CACHE STRING "Directory with libyang plugins (extensions and user types)")
|
||||
set(PLUGINS_DIR_EXTENSIONS "${PLUGINS_DIR}/extensions" CACHE STRING "Directory with libyang user extensions plugins")
|
||||
set(PLUGINS_DIR_TYPES "${PLUGINS_DIR}/types" CACHE STRING "Directory with libyang user types plugins")
|
||||
|
||||
#
|
||||
# checks
|
||||
#
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
message(STATUS "Disabling tests for static build")
|
||||
set(ENABLE_TESTS OFF)
|
||||
set(ENABLE_VALGRIND_TESTS OFF)
|
||||
endif()
|
||||
|
||||
if(ENABLE_VALGRIND_TESTS)
|
||||
if(NOT ENABLE_TESTS)
|
||||
message(WARNING "Tests are disabled! Disabling memory leak tests.")
|
||||
set(ENABLE_VALGRIND_TESTS OFF)
|
||||
else()
|
||||
find_program(VALGRIND_FOUND valgrind)
|
||||
if(NOT VALGRIND_FOUND)
|
||||
message(WARNING "valgrind executable not found! Disabling memory leak tests.")
|
||||
set(ENABLE_VALGRIND_TESTS OFF)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_TESTS)
|
||||
find_package(CMocka 1.0.1)
|
||||
if(NOT CMOCKA_FOUND)
|
||||
message(STATUS "Disabling tests because of missing CMocka")
|
||||
set(ENABLE_TESTS OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_PERF_TESTS)
|
||||
find_path(VALGRIND_INCLUDE_DIR
|
||||
NAMES
|
||||
valgrind/callgrind.h
|
||||
PATHS
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
${CMAKE_INCLUDE_PATH}
|
||||
${CMAKE_INSTALL_PREFIX}/include)
|
||||
if(VALGRIND_INCLUDE_DIR)
|
||||
set(HAVE_CALLGRIND 1)
|
||||
else()
|
||||
message(STATUS "Disabling callgrind macros in performance tests because of missing valgrind headers")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_COVERAGE)
|
||||
gen_coverage_enable(${ENABLE_TESTS})
|
||||
endif()
|
||||
|
||||
if ("${BUILD_TYPE_UPPER}" STREQUAL "DEBUG")
|
||||
# enable before adding tests to let them detect that format checking is available - one of the tests is format checking
|
||||
source_format_enable(0.77)
|
||||
endif()
|
||||
|
||||
# generate and copy all public header files
|
||||
configure_file(${PROJECT_SOURCE_DIR}/src/ly_config.h.in ${PROJECT_BINARY_DIR}/libyang/ly_config.h @ONLY)
|
||||
configure_file(${PROJECT_SOURCE_DIR}/src/version.h.in ${PROJECT_BINARY_DIR}/libyang/version.h @ONLY)
|
||||
file(COPY ${headers} DESTINATION ${PROJECT_BINARY_DIR}/libyang)
|
||||
|
||||
# DOC-only target with no extra dependencies
|
||||
if("${BUILD_TYPE_UPPER}" STREQUAL "DOCONLY")
|
||||
gen_doc("${doxy_files}" ${LIBYANG_VERSION} ${LIBYANG_DESCRIPTION} ${project_logo})
|
||||
return()
|
||||
endif()
|
||||
|
||||
#
|
||||
# targets
|
||||
#
|
||||
|
||||
# link compat
|
||||
use_compat()
|
||||
|
||||
# create static libyang library
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
add_definitions(-DSTATIC)
|
||||
|
||||
# allow binaries compilation linking both static and dynamic libraries never linking static glibc
|
||||
#set(CMAKE_EXE_LINKER_FLAGS -static)
|
||||
|
||||
# prefer static libraries
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES .a;.so)
|
||||
set(CMAKE_LINK_SEARCH_START_STATIC TRUE)
|
||||
|
||||
set(CMAKE_EXE_LINK_DYNAMIC_C_FLAGS) # remove -Wl,-Bdynamic
|
||||
set(CMAKE_EXE_LINK_DYNAMIC_CXX_FLAGS)
|
||||
add_library(yang STATIC ${libsrc} ${compatsrc})
|
||||
else()
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
|
||||
add_library(yangobj OBJECT ${libsrc} ${compatsrc})
|
||||
if(NOT WIN32)
|
||||
set_target_properties(yangobj PROPERTIES COMPILE_FLAGS "-fvisibility=hidden")
|
||||
endif()
|
||||
target_compile_definitions(yangobj PRIVATE LIBYANG_BUILD)
|
||||
add_library(yang SHARED $<TARGET_OBJECTS:yangobj>)
|
||||
|
||||
if(WIN32)
|
||||
find_package(dlfcn-win32 REQUIRED)
|
||||
set(CMAKE_DL_LIBS dlfcn-win32::dl)
|
||||
endif()
|
||||
|
||||
#link dl
|
||||
target_link_libraries(yang ${CMAKE_DL_LIBS})
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
find_path(DIRENT_INCLUDE_DIR NAMES dirent.h REQUIRED)
|
||||
message(STATUS "Found <dirent.h> at ${DIRENT_INCLUDE_DIR}")
|
||||
|
||||
set(COMPAT_POSIX_INCLUDES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/compat/posix-shims
|
||||
${DIRENT_INCLUDE_DIR})
|
||||
|
||||
if(TARGET yangobj)
|
||||
target_include_directories(yangobj PRIVATE ${COMPAT_POSIX_INCLUDES})
|
||||
endif()
|
||||
target_include_directories(yang PRIVATE ${COMPAT_POSIX_INCLUDES})
|
||||
include_directories(${COMPAT_POSIX_INCLUDES})
|
||||
|
||||
find_package(pthreads REQUIRED)
|
||||
set(COMPAT_WIN_LIBRARIES PThreads4W::PThreads4W shlwapi.lib ws2_32)
|
||||
target_link_libraries(yang ${COMPAT_WIN_LIBRARIES})
|
||||
endif()
|
||||
|
||||
set_target_properties(yang PROPERTIES VERSION ${LIBYANG_SOVERSION_FULL} SOVERSION ${LIBYANG_SOVERSION})
|
||||
|
||||
# link math
|
||||
if(NOT WIN32)
|
||||
target_link_libraries(yang m)
|
||||
endif()
|
||||
|
||||
# find pthreads
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(yang ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
# find PCRE2 library
|
||||
unset(PCRE2_LIBRARY CACHE)
|
||||
find_package(PCRE2 10.21 REQUIRED)
|
||||
include_directories(${PCRE2_INCLUDE_DIRS})
|
||||
target_link_libraries(yang ${PCRE2_LIBRARIES})
|
||||
|
||||
# generated header list
|
||||
foreach(h IN LISTS gen_headers)
|
||||
list(APPEND g_headers ${PROJECT_BINARY_DIR}/libyang/${h})
|
||||
endforeach()
|
||||
|
||||
# install the modules
|
||||
install(DIRECTORY "${PROJECT_SOURCE_DIR}/models/" DESTINATION ${YANG_MODULE_DIR} FILES_MATCHING PATTERN "*.yang")
|
||||
|
||||
# install all library files
|
||||
install(TARGETS yang DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(FILES ${headers} ${g_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libyang)
|
||||
|
||||
find_package(PkgConfig)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
# generate and install pkg-config file
|
||||
configure_file("libyang.pc.in" "libyang.pc" @ONLY)
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libyang.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||
# check that pkg-config includes the used path
|
||||
execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable pc_path pkg-config RESULT_VARIABLE RETURN OUTPUT_VARIABLE PC_PATH ERROR_QUIET)
|
||||
if(RETURN EQUAL 0)
|
||||
string(STRIP "${PC_PATH}" PC_PATH)
|
||||
set(PC_PATH "${PC_PATH}:$ENV{PKG_CONFIG_PATH}")
|
||||
string(REGEX MATCH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/pkgconfig" SUBSTR "${PC_PATH}")
|
||||
string(LENGTH "${SUBSTR}" SUBSTR_LEN)
|
||||
if(SUBSTR_LEN EQUAL 0)
|
||||
message(WARNING "pkg-config will not detect the new package after installation, adjust PKG_CONFIG_PATH using \"export PKG_CONFIG_PATH=\${PKG_CONFIG_PATH}:${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/pkgconfig\".")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# tests
|
||||
if(ENABLE_TESTS OR ENABLE_PERF_TESTS)
|
||||
enable_testing()
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
if(ENABLE_FUZZ_TARGETS)
|
||||
set(FUZZER "AFL" CACHE STRING "fuzzer type")
|
||||
if(FUZZER STREQUAL "LibFuzzer")
|
||||
if (NOT CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
message(FATAL_ERROR "LibFuzzer works only with clang")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# create coverage target for generating coverage reports
|
||||
gen_coverage("utest_.*" "utest_.*_valgrind")
|
||||
|
||||
# tools - yanglint, yangre
|
||||
if(ENABLE_TOOLS)
|
||||
add_subdirectory(tools)
|
||||
endif()
|
||||
|
||||
# generate doxygen documentation for libyang API
|
||||
if(ENABLE_COMMON_TARGETS)
|
||||
gen_doc("${doxy_files}" ${LIBYANG_VERSION} ${LIBYANG_DESCRIPTION} ${project_logo})
|
||||
endif()
|
||||
|
||||
# generate API/ABI report
|
||||
if("${BUILD_TYPE_UPPER}" STREQUAL "ABICHECK")
|
||||
lib_abi_check(yang "${headers}" ${LIBYANG_SOVERSION_FULL} 708a8bfad983a4095c8d4dc537a9d2a1d5ca65c5)
|
||||
endif()
|
||||
|
||||
# source code format target for Makefile
|
||||
# - add it after tests which may also update list of sources to format
|
||||
source_format(${format_sources})
|
||||
|
||||
# uninstall
|
||||
if(ENABLE_COMMON_TARGETS)
|
||||
add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_MODULE_PATH}/uninstall.cmake")
|
||||
endif()
|
||||
|
||||
# clean cmake cache
|
||||
add_custom_target(cclean
|
||||
COMMAND make clean
|
||||
COMMAND find . -iname '*cmake*' -not -name CMakeLists.txt -not -path './CMakeModules*' -exec rm -rf {} +
|
||||
COMMAND rm -rf Makefile Doxyfile
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
66
CMakeModules/ABICheck.cmake
Normal file
66
CMakeModules/ABICheck.cmake
Normal file
|
@ -0,0 +1,66 @@
|
|||
# generate API/ABI report
|
||||
macro(LIB_ABI_CHECK LIB_TARGET LIB_HEADERS LIB_SOVERSION_FULL ABI_BASE_HASH)
|
||||
# get short hash
|
||||
string(SUBSTRING "${ABI_BASE_HASH}" 0 8 ABI_BASE_HASH_SHORT)
|
||||
|
||||
# find abi-dumper
|
||||
find_program(ABI_DUMPER abi-dumper)
|
||||
find_package_handle_standard_args(abi-dumper DEFAULT_MSG ABI_DUMPER)
|
||||
if(NOT ABI_DUMPER)
|
||||
message(FATAL_ERROR "Program abi-dumper not found!")
|
||||
endif()
|
||||
|
||||
# find abi-checker
|
||||
find_program(ABI_CHECKER abi-compliance-checker)
|
||||
find_package_handle_standard_args(abi-compliance-checker DEFAULT_MSG ABI_CHECKER)
|
||||
if(NOT ABI_CHECKER)
|
||||
message(FATAL_ERROR "Program abi-compliance-checker not found!")
|
||||
endif()
|
||||
|
||||
# abi-dump target - generating an ABI dump
|
||||
set(PUBLIC_HEADERS ${LIB_HEADERS})
|
||||
string(PREPEND PUBLIC_HEADERS "${CMAKE_SOURCE_DIR}/")
|
||||
string(REPLACE ";" "\n${CMAKE_SOURCE_DIR}/" PUBLIC_HEADERS "${PUBLIC_HEADERS}")
|
||||
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/public_headers CONTENT "${PUBLIC_HEADERS}")
|
||||
add_custom_target(abi-dump
|
||||
COMMAND ${ABI_DUMPER} ./lib${LIB_TARGET}${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
-o lib${LIB_TARGET}.${LIB_SOVERSION_FULL}.dump
|
||||
-lver ${LIB_SOVERSION_FULL} -public-headers ${CMAKE_BINARY_DIR}/public_headers
|
||||
DEPENDS ${LIB_TARGET}
|
||||
BYPRODUCTS ${CMAKE_BINARY_DIR}/lib${LIB_TARGET}.${LIB_SOVERSION_FULL}.dump
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Dumping ABI information of version ${LIB_SOVERSION_FULL} for abi-check")
|
||||
|
||||
# get URL for fetching origin
|
||||
execute_process(COMMAND git remote get-url origin OUTPUT_VARIABLE ORIGIN_URL OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
# generate script for generating the base ABI dump
|
||||
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/abibase.sh CONTENT "#!/bin/sh
|
||||
if [ ! -d abibase ]; then mkdir abibase; fi
|
||||
cd abibase
|
||||
if [ ! -f build/lib${LIB_TARGET}.*.dump ]; then
|
||||
if [ -d .git ] && [ \"${ABI_BASE_HASH}\" != \"`git log --pretty=oneline | cut -d' ' -f1`\" ]; then rm -rf .* 2> /dev/null; fi
|
||||
if [ ! -d .git ]; then
|
||||
git init --initial-branch=master
|
||||
git remote add origin ${ORIGIN_URL}
|
||||
git fetch origin --depth 1 ${ABI_BASE_HASH}
|
||||
git reset --hard FETCH_HEAD
|
||||
fi
|
||||
if [ ! -d build ]; then mkdir build; fi
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=ABICheck ..
|
||||
make abi-dump
|
||||
fi
|
||||
")
|
||||
|
||||
# abi-check target - check ABI compatibility of current version and the base hash version
|
||||
add_custom_target(abi-check
|
||||
COMMAND bash ./abibase.sh
|
||||
COMMAND ${ABI_CHECKER} -l lib${LIB_TARGET}${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
-old abibase/build/lib${LIB_TARGET}.*.dump
|
||||
-new ./lib${LIB_TARGET}.${LIB_SOVERSION_FULL}.dump
|
||||
DEPENDS ${LIB_TARGET} abi-dump
|
||||
BYPRODUCTS ${CMAKE_BINARY_DIR}/compat_reports/lib${LIB_TARGET}${CMAKE_SHARED_LIBRARY_SUFFIX}/*_to_${LIB_SOVERSION_FULL}/compat_report.html
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Checking ABI compatibility of version ${LIB_SOVERSION_FULL} and revision ${ABI_BASE_HASH_SHORT}")
|
||||
endmacro()
|
49
CMakeModules/FindCMocka.cmake
Normal file
49
CMakeModules/FindCMocka.cmake
Normal file
|
@ -0,0 +1,49 @@
|
|||
# - Try to find CMocka
|
||||
# Once done this will define
|
||||
#
|
||||
# CMOCKA_ROOT_DIR - Set this variable to the root installation of CMocka
|
||||
#
|
||||
# Read-Only variables:
|
||||
# CMOCKA_FOUND - system has CMocka
|
||||
# CMOCKA_INCLUDE_DIR - the CMocka include directory
|
||||
# CMOCKA_LIBRARIES - Link these to use CMocka
|
||||
# CMOCKA_DEFINITIONS - Compiler switches required for using CMocka
|
||||
#
|
||||
#=============================================================================
|
||||
# Copyright (c) 2011-2012 Andreas Schneider <asn@cryptomilk.org>
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
#
|
||||
|
||||
find_path(CMOCKA_INCLUDE_DIR
|
||||
NAMES
|
||||
cmocka.h
|
||||
PATHS
|
||||
${CMOCKA_ROOT_DIR}/include
|
||||
)
|
||||
|
||||
find_library(CMOCKA_LIBRARY
|
||||
NAMES
|
||||
cmocka
|
||||
PATHS
|
||||
${CMOCKA_ROOT_DIR}/include
|
||||
)
|
||||
|
||||
if (CMOCKA_LIBRARY)
|
||||
set(CMOCKA_LIBRARIES
|
||||
${CMOCKA_LIBRARIES}
|
||||
${CMOCKA_LIBRARY}
|
||||
)
|
||||
endif (CMOCKA_LIBRARY)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(CMocka DEFAULT_MSG CMOCKA_LIBRARIES CMOCKA_INCLUDE_DIR)
|
||||
|
||||
# show the CMOCKA_INCLUDE_DIR and CMOCKA_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(CMOCKA_INCLUDE_DIR CMOCKA_LIBRARIES)
|
66
CMakeModules/FindPCRE2.cmake
Normal file
66
CMakeModules/FindPCRE2.cmake
Normal file
|
@ -0,0 +1,66 @@
|
|||
# - Find pcre
|
||||
# Find the native PCRE2 headers and libraries.
|
||||
#
|
||||
# PCRE2_INCLUDE_DIRS - where to find pcre.h, etc.
|
||||
# PCRE2_LIBRARIES - List of libraries when using pcre.
|
||||
# PCRE2_FOUND - True if pcre found.
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
if(PCRE2_LIBRARIES AND PCRE2_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(PCRE2_FOUND TRUE)
|
||||
else()
|
||||
find_path(PCRE2_INCLUDE_DIR
|
||||
NAMES
|
||||
pcre2.h
|
||||
PATHS
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
${CMAKE_INCLUDE_PATH}
|
||||
${CMAKE_INSTALL_PREFIX}/include)
|
||||
|
||||
# Look for the library.
|
||||
if (WIN32 AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
# For the Debug build, the pcre2 library is called pcre2-8d. The Release build should be pcre2-8.
|
||||
find_library(PCRE2_LIBRARY pcre2-8d)
|
||||
else()
|
||||
find_library(PCRE2_LIBRARY
|
||||
NAMES
|
||||
pcre2-8
|
||||
PATHS
|
||||
/usr/lib
|
||||
/usr/lib64
|
||||
/usr/local/lib
|
||||
/usr/local/lib64
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
${CMAKE_LIBRARY_PATH}
|
||||
${CMAKE_INSTALL_PREFIX}/lib)
|
||||
endif()
|
||||
|
||||
if(PCRE2_INCLUDE_DIR AND PCRE2_LIBRARY)
|
||||
# learn pcre2 version
|
||||
file(STRINGS ${PCRE2_INCLUDE_DIR}/pcre2.h PCRE2_VERSION_MAJOR
|
||||
REGEX "#define[ ]+PCRE2_MAJOR[ ]+[0-9]+")
|
||||
string(REGEX MATCH " [0-9]+" PCRE2_VERSION_MAJOR ${PCRE2_VERSION_MAJOR})
|
||||
string(STRIP "${PCRE2_VERSION_MAJOR}" PCRE2_VERSION_MAJOR)
|
||||
|
||||
file(STRINGS ${PCRE2_INCLUDE_DIR}/pcre2.h PCRE2_VERSION_MINOR
|
||||
REGEX "#define[ ]+PCRE2_MINOR[ ]+[0-9]+")
|
||||
string(REGEX MATCH " [0-9]+" PCRE2_VERSION_MINOR ${PCRE2_VERSION_MINOR})
|
||||
string(STRIP "${PCRE2_VERSION_MINOR}" PCRE2_VERSION_MINOR)
|
||||
|
||||
set(PCRE2_VERSION ${PCRE2_VERSION_MAJOR}.${PCRE2_VERSION_MINOR})
|
||||
endif()
|
||||
|
||||
set(PCRE2_INCLUDE_DIRS ${PCRE2_INCLUDE_DIR})
|
||||
set(PCRE2_LIBRARIES ${PCRE2_LIBRARY})
|
||||
mark_as_advanced(PCRE2_INCLUDE_DIRS PCRE2_LIBRARIES)
|
||||
|
||||
# Handle the QUIETLY and REQUIRED arguments and set PCRE2_FOUND to TRUE if all listed variables are TRUE.
|
||||
find_package_handle_standard_args(PCRE2 FOUND_VAR PCRE2_FOUND
|
||||
REQUIRED_VARS PCRE2_LIBRARY PCRE2_INCLUDE_DIR
|
||||
VERSION_VAR PCRE2_VERSION)
|
||||
endif()
|
21
CMakeModules/FindUncrustify.cmake
Normal file
21
CMakeModules/FindUncrustify.cmake
Normal file
|
@ -0,0 +1,21 @@
|
|||
# - Find uncrustify
|
||||
# Find the uncrustify binary.
|
||||
#
|
||||
# UNCRUSTIFY - path ot the binary
|
||||
# UNCRUSTIFY_VERSION - found version
|
||||
# UNCRUSTIFY_FOUND - True if uncrustify found.
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_program(UNCRUSTIFY uncrustify)
|
||||
if(UNCRUSTIFY)
|
||||
execute_process(COMMAND ${UNCRUSTIFY} --version OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE VERSION)
|
||||
string(FIND ${VERSION} "-" START_IDX)
|
||||
math(EXPR START_IDX "${START_IDX} + 1")
|
||||
string(SUBSTRING "${VERSION}" ${START_IDX} -1 VERSION)
|
||||
|
||||
string(FIND ${VERSION} "-" LEN)
|
||||
string(SUBSTRING "${VERSION}" 0 ${LEN} UNCRUSTIFY_VERSION)
|
||||
endif()
|
||||
|
||||
# Handle the QUIETLY and REQUIRED arguments and set UNCRUSTIFY_FOUND to TRUE if all listed variables are TRUE.
|
||||
find_package_handle_standard_args(Uncrustify REQUIRED_VARS UNCRUSTIFY VERSION_VAR UNCRUSTIFY_VERSION)
|
118
CMakeModules/GenCoverage.cmake
Normal file
118
CMakeModules/GenCoverage.cmake
Normal file
|
@ -0,0 +1,118 @@
|
|||
# generate test code coverage report
|
||||
|
||||
# check that coverage tools are available - always use before GEN_COVERAGE
|
||||
macro(GEN_COVERAGE_ENABLE ENABLE_TESTS)
|
||||
# make into normal variable
|
||||
set(TESTS_ENABLED ${ENABLE_TESTS})
|
||||
|
||||
set(GEN_COVERAGE_ENABLED ON)
|
||||
if(NOT TESTS_ENABLED)
|
||||
message(WARNING "You cannot generate coverage when tests are disabled. Enable test by additing parameter -DENABLE_TESTS=ON or run cmake with Debug build target.")
|
||||
set(GEN_COVERAGE_ENABLED OFF)
|
||||
endif()
|
||||
|
||||
if(GEN_COVERAGE_ENABLED)
|
||||
find_program(PATH_GCOV NAMES gcov)
|
||||
if(NOT PATH_GCOV)
|
||||
message(WARNING "gcov executable not found! Disabling building code coverage report.")
|
||||
set(GEN_COVERAGE_ENABLED OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(GEN_COVERAGE_ENABLED)
|
||||
find_program(PATH_LCOV NAMES lcov)
|
||||
if(NOT PATH_LCOV)
|
||||
message(WARNING "lcov executable not found! Disabling building code coverage report.")
|
||||
set(GEN_COVERAGE_ENABLED OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(GEN_COVERAGE_ENABLED)
|
||||
find_program(PATH_GENHTML NAMES genhtml)
|
||||
if(NOT PATH_GENHTML)
|
||||
message(WARNING "genhtml executable not found! Disabling building code coverage report.")
|
||||
set(GEN_COVERAGE_ENABLED OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(GEN_COVERAGE_ENABLED)
|
||||
if(NOT CMAKE_COMPILER_IS_GNUCC)
|
||||
message(WARNING "Compiler is not gcc! Coverage may break the tests!")
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND bash "-c" "${CMAKE_C_COMPILER} --version | head -n1 | sed \"s/.* (.*) \\([0-9]\\+.[0-9]\\+.[0-9]\\+ .*\\)/\\1/\""
|
||||
OUTPUT_VARIABLE GCC_VERSION_FULL
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
execute_process(
|
||||
COMMAND bash "-c" "${PATH_GCOV} --version | head -n1 | sed \"s/.* (.*) \\([0-9]\\+.[0-9]\\+.[0-9]\\+ .*\\)/\\1/\""
|
||||
OUTPUT_VARIABLE GCOV_VERSION_FULL
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if(NOT GCC_VERSION_FULL STREQUAL GCOV_VERSION_FULL)
|
||||
message(WARNING "gcc and gcov versions do not match! Generating coverage may fail with errors.")
|
||||
endif()
|
||||
|
||||
# add specific required compile flags
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage -fprofile-arcs -ftest-coverage")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# tests are always expected to be in ${CMAKE_SOURCE_DIR}/tests
|
||||
function(GEN_COVERAGE MATCH_TEST_REGEX EXCLUDE_TEST_REGEX)
|
||||
if(NOT GEN_COVERAGE_ENABLED)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# destination
|
||||
set(COVERAGE_DIR "${CMAKE_BINARY_DIR}/code_coverage/")
|
||||
set(COVERAGE_FILE_RAW "${CMAKE_BINARY_DIR}/coverage_raw.info")
|
||||
set(COVERAGE_FILE_CLEAN "${CMAKE_BINARY_DIR}/coverage_clean.info")
|
||||
|
||||
# test match/exclude
|
||||
if(MATCH_TEST_REGEX)
|
||||
set(MATCH_TEST_ARGS -R \"${MATCH_TEST_REGEX}\")
|
||||
endif()
|
||||
if(EXCLUDE_TEST_REGEX)
|
||||
set(EXCLUDE_TEST_ARGS -E \"${EXCLUDE_TEST_REGEX}\")
|
||||
endif()
|
||||
|
||||
# coverage target
|
||||
add_custom_target(coverage
|
||||
COMMENT "Generating code coverage..."
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||
# Cleanup code counters
|
||||
COMMAND "${PATH_LCOV}" --directory . --zerocounters --quiet
|
||||
|
||||
# Run tests
|
||||
COMMAND "${CMAKE_CTEST_COMMAND}" --quiet ${MATCH_TEST_ARGS} ${EXCLUDE_TEST_ARGS}
|
||||
|
||||
# Capture the counters
|
||||
COMMAND "${PATH_LCOV}"
|
||||
--directory .
|
||||
--rc lcov_branch_coverage=1
|
||||
--rc 'lcov_excl_line=assert'
|
||||
--capture --quiet
|
||||
--output-file "${COVERAGE_FILE_RAW}"
|
||||
# Remove coverage of tests, system headers, etc.
|
||||
COMMAND "${PATH_LCOV}"
|
||||
--remove "${COVERAGE_FILE_RAW}" '${CMAKE_SOURCE_DIR}/tests/*'
|
||||
--rc lcov_branch_coverage=1
|
||||
--quiet --output-file "${COVERAGE_FILE_CLEAN}"
|
||||
# Generate HTML report
|
||||
COMMAND "${PATH_GENHTML}"
|
||||
--branch-coverage --function-coverage --quiet --title "${PROJECT_NAME}"
|
||||
--legend --show-details --output-directory "${COVERAGE_DIR}"
|
||||
"${COVERAGE_FILE_CLEAN}"
|
||||
# Delete the counters
|
||||
COMMAND "${CMAKE_COMMAND}" -E remove
|
||||
${COVERAGE_FILE_RAW} ${COVERAGE_FILE_CLEAN}
|
||||
)
|
||||
|
||||
add_custom_command(TARGET coverage POST_BUILD
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/tests"
|
||||
COMMENT "To see the code coverage report, open ${COVERAGE_DIR}index.html"
|
||||
COMMAND ;
|
||||
)
|
||||
endfunction()
|
28
CMakeModules/GenDoc.cmake
Normal file
28
CMakeModules/GenDoc.cmake
Normal file
|
@ -0,0 +1,28 @@
|
|||
# Prepare building doxygen documentation
|
||||
macro(GEN_DOC INPUT_FILES PROJECT_VERSION PROJECT_DESCRIPTION DOC_LOGO)
|
||||
find_package(Doxygen)
|
||||
if(DOXYGEN_FOUND)
|
||||
find_program(DOT_PATH dot PATH_SUFFIXES graphviz2.38/bin graphviz/bin)
|
||||
if(DOT_PATH)
|
||||
set(HAVE_DOT "YES")
|
||||
else()
|
||||
set(HAVE_DOT "NO")
|
||||
message(AUTHOR_WARNING "Doxygen: to generate UML diagrams please install graphviz")
|
||||
endif()
|
||||
|
||||
# target doc
|
||||
add_custom_target(doc
|
||||
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
# generate list with spaces as separators
|
||||
string(REPLACE ";" " " DOXY_INPUT "${INPUT_FILES}")
|
||||
|
||||
# make other arguments into variables
|
||||
set(PROJECT_VERSION ${PROJECT_VERSION})
|
||||
set(PROJECT_DESCRIPTION ${PROJECT_DESCRIPTION})
|
||||
set(DOC_LOGO ${DOC_LOGO})
|
||||
|
||||
configure_file(Doxyfile.in Doxyfile)
|
||||
endif()
|
||||
endmacro()
|
36
CMakeModules/SourceFormat.cmake
Normal file
36
CMakeModules/SourceFormat.cmake
Normal file
|
@ -0,0 +1,36 @@
|
|||
# format source files with uncrustify
|
||||
|
||||
# check that format checking is available - always use before SOURCE_FORMAT
|
||||
macro(SOURCE_FORMAT_ENABLE)
|
||||
if(NOT ${ARGC} EQUAL 1)
|
||||
message(FATAL_ERROR "source_format_enable() needs the required Uncrustify version!")
|
||||
endif()
|
||||
|
||||
find_package(Uncrustify ${ARGV0})
|
||||
if(UNCRUSTIFY_FOUND)
|
||||
set(SOURCE_FORMAT_ENABLED TRUE)
|
||||
else()
|
||||
set(SOURCE_FORMAT_ENABLED FALSE)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# files are expected to be a list and relative paths are resolved wtih respect to CMAKE_SOURCE DIR
|
||||
macro(SOURCE_FORMAT)
|
||||
if(NOT ${ARGC})
|
||||
message(FATAL_ERROR "source_format() needs a list of files to format!")
|
||||
endif()
|
||||
|
||||
if(SOURCE_FORMAT_ENABLED)
|
||||
add_custom_target(format
|
||||
COMMAND ${UNCRUSTIFY} -c ${CMAKE_SOURCE_DIR}/uncrustify.cfg --no-backup --replace ${ARGN}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
COMMENT "Formating sources with ${UNCRUSTIFY} ...")
|
||||
|
||||
add_custom_target(format-check
|
||||
COMMAND ${UNCRUSTIFY} -c ${CMAKE_SOURCE_DIR}/uncrustify.cfg --check ${ARGN}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
COMMENT "Checking format of the sources with ${UNCRUSTIFY} ...")
|
||||
|
||||
set(SOURCE_FORMAT_ENABLED TRUE)
|
||||
endif()
|
||||
endmacro()
|
77
CMakeModules/UseCompat.cmake
Normal file
77
CMakeModules/UseCompat.cmake
Normal file
|
@ -0,0 +1,77 @@
|
|||
# - Use compat library providing various functions and macros that may be missing on some systems
|
||||
# Once done this will define
|
||||
#
|
||||
# compatsrc - sources to add to compilation
|
||||
#
|
||||
# Additionally, "compat.h" include directory is added and can be included.
|
||||
#
|
||||
# Author Michal Vasko <mvasko@cesnet.cz>
|
||||
# Copyright (c) 2021 CESNET, z.s.p.o.
|
||||
#
|
||||
# This source code is licensed under BSD 3-Clause License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://opensource.org/licenses/BSD-3-Clause
|
||||
#
|
||||
include(CheckSymbolExists)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckIncludeFile)
|
||||
include(TestBigEndian)
|
||||
if(POLICY CMP0075)
|
||||
cmake_policy(SET CMP0075 NEW)
|
||||
endif()
|
||||
|
||||
macro(USE_COMPAT)
|
||||
# compatibility checks
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_POSIX_C_SOURCE=200809L)
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D__BSD_VISIBLE=1)
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_DEFAULT_SOURCE)
|
||||
|
||||
check_symbol_exists(vdprintf "stdio.h;stdarg.h" HAVE_VDPRINTF)
|
||||
check_symbol_exists(asprintf "stdio.h" HAVE_ASPRINTF)
|
||||
check_symbol_exists(vasprintf "stdio.h" HAVE_VASPRINTF)
|
||||
check_symbol_exists(getline "stdio.h" HAVE_GETLINE)
|
||||
|
||||
check_symbol_exists(strndup "string.h" HAVE_STRNDUP)
|
||||
check_symbol_exists(strnstr "string.h" HAVE_STRNSTR)
|
||||
check_symbol_exists(strdupa "string.h" HAVE_STRDUPA)
|
||||
check_symbol_exists(strchrnul "string.h" HAVE_STRCHRNUL)
|
||||
|
||||
check_symbol_exists(get_current_dir_name "unistd.h" HAVE_GET_CURRENT_DIR_NAME)
|
||||
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||
find_package(Threads)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
|
||||
check_function_exists(pthread_mutex_timedlock HAVE_PTHREAD_MUTEX_TIMEDLOCK)
|
||||
list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
test_big_endian(IS_BIG_ENDIAN)
|
||||
|
||||
check_include_file("stdatomic.h" HAVE_STDATOMIC)
|
||||
|
||||
check_symbol_exists(realpath "stdlib.h" HAVE_REALPATH)
|
||||
check_symbol_exists(localtime_r "time.h" HAVE_LOCALTIME_R)
|
||||
check_symbol_exists(gmtime_r "time.h" HAVE_GMTIME_R)
|
||||
check_function_exists(timegm HAVE_TIMEGM)
|
||||
check_symbol_exists(strptime "time.h" HAVE_STRPTIME)
|
||||
check_symbol_exists(mmap "sys/mman.h" HAVE_MMAP)
|
||||
check_symbol_exists(setenv "stdlib.h" HAVE_SETENV)
|
||||
|
||||
list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D_POSIX_C_SOURCE=200809L)
|
||||
list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
|
||||
list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D__BSD_VISIBLE=1)
|
||||
list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D_DEFAULT_SOURCE)
|
||||
|
||||
# header and source file (adding the source directly allows for hiding its symbols)
|
||||
configure_file(${PROJECT_SOURCE_DIR}/compat/compat.h.in ${PROJECT_BINARY_DIR}/compat/compat.h @ONLY)
|
||||
include_directories(${PROJECT_BINARY_DIR}/compat)
|
||||
set(compatsrc ${PROJECT_SOURCE_DIR}/compat/compat.c)
|
||||
if(WIN32)
|
||||
include_directories(${PROJECT_SOURCE_DIR}/compat/posix-shims)
|
||||
endif()
|
||||
if(NOT HAVE_STRPTIME)
|
||||
set(compatsrc ${compatsrc} ${PROJECT_SOURCE_DIR}/compat/strptime.c)
|
||||
endif()
|
||||
endmacro()
|
27
CMakeModules/uninstall.cmake
Normal file
27
CMakeModules/uninstall.cmake
Normal file
|
@ -0,0 +1,27 @@
|
|||
cmake_minimum_required(VERSION 3.0.2)
|
||||
|
||||
set(MANIFEST "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt")
|
||||
|
||||
if(NOT EXISTS ${MANIFEST})
|
||||
message(FATAL_ERROR "Cannot find install manifest: ${MANIFEST}")
|
||||
endif()
|
||||
|
||||
file(STRINGS ${MANIFEST} files)
|
||||
foreach(file ${files})
|
||||
if(EXISTS ${file} OR IS_SYMLINK ${file})
|
||||
message(STATUS "Removing: ${file}")
|
||||
|
||||
execute_process(COMMAND rm -f ${file}
|
||||
RESULT_VARIABLE result
|
||||
OUTPUT_QUIET
|
||||
ERROR_VARIABLE stderr
|
||||
ERROR_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
if(NOT ${result} EQUAL 0)
|
||||
message(FATAL_ERROR "${stderr}")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Does-not-exist: ${file}")
|
||||
endif()
|
||||
endforeach(file)
|
228
CONTRIBUTING.md
Normal file
228
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,228 @@
|
|||
# Contributing to libyang
|
||||
|
||||
First of all, thanks for thinking about contribution to libyang! Not all of us
|
||||
are C guru, but believe that helping us with docs, tests, helping other users to
|
||||
solve their issues / answer ther questions or even letting us to know via
|
||||
[issue tracker](https://github.com/CESNET/libyang/issues) that something
|
||||
can be done in a better or just different way is really appreciated.
|
||||
|
||||
If you are willing to contribute, you will definitely have to build and install
|
||||
libyang first. To do it, please check dependencies and follow build and install
|
||||
instructions provided in [README](README.md).
|
||||
|
||||
If you have something what you believe should be part of the libyang repository,
|
||||
add it via [Github Pull Request mechanism](https://help.github.com/articles/about-pull-requests/).
|
||||
Remember to explain what you wish to add and why. The best approach is to start
|
||||
with creating an issue and discuss possible approaches there. Pull requests can be
|
||||
then connected with such issues.
|
||||
|
||||
## Branches
|
||||
|
||||
There are 2 main branches in libyang project. The default branch is named `master`. It is the
|
||||
most stable and tested code which you get by default when cloning the Git repository. The
|
||||
`devel` branch introduces new features, API changes or even bugfixes in case `master` and
|
||||
`devel` differs significantly at that moment and the fix affects the changed code. There are
|
||||
some more branches for work-in-progress features and special `coverity` branch for submitting
|
||||
code for the [analysis in the Coverity tool](https://scan.coverity.com/projects/5259) usign
|
||||
[Travis CI build](https://travis-ci.org/CESNET/libyang/branches).
|
||||
|
||||
When you create pull request, think carefully about the branch where the patch belongs to.
|
||||
In most cases (if not all), it is the `devel` branch.
|
||||
|
||||
## Issue Ticketing
|
||||
|
||||
All the communication with the developers is done via [issue tracker](https://github.com/CESNET/libyang/issues).
|
||||
You can send us an email, but in case you will ask a question we would think that someone else
|
||||
could ask in future, our answer will be just **use the issue tracker**. Private emails are not visible
|
||||
for others and we don't want to answer the same questions.
|
||||
|
||||
So when you are goingto submit a new issue, **please:**
|
||||
* check that the issue you are having is not already solved in the devel branch,
|
||||
* go through the present issues (in case of question, it can be already a closed issue) in the tracker,
|
||||
* give it as descriptive title as possible,
|
||||
* separate topics - solving multiple issues in one ticket hides the issues from others,
|
||||
* provide as much relevant information as possible (versions, logs, input data, etc.).
|
||||
|
||||
## libyang Coding Style
|
||||
|
||||
When you are going to contribute C code, please follow these coding style guidelines.
|
||||
|
||||
### Basics
|
||||
|
||||
- Use space instead of tabs for indentations.
|
||||
- There is no strict limit for the line length, However, try to keep lines in a
|
||||
reasonable length (120 characters).
|
||||
- Avoid trailing spaces on lines.
|
||||
- Put one blank line between function definitions.
|
||||
- Don't mix declarations and code within a block. Similarly, don't use
|
||||
declarations in iteration statements.
|
||||
|
||||
### Naming
|
||||
|
||||
Use underscores to separate words in an identifier: `multi_word_name`.
|
||||
|
||||
Use lowercase for most names. Use uppercase for macros, macro parameters and
|
||||
members of enumerations.
|
||||
|
||||
Do not use names that begin with `_`. If you need a name for "internal use
|
||||
only", use `__` as a suffix instead of a prefix.
|
||||
|
||||
### Comments
|
||||
|
||||
Avoid `//` comments. Use `/* ... */` comments, write block comments with the
|
||||
leading asterisk on each line. You may put the `/*` and `*/` on the same line as
|
||||
comment text if you prefer.
|
||||
|
||||
```c
|
||||
/*
|
||||
* comment text
|
||||
*/
|
||||
```
|
||||
|
||||
### Functions
|
||||
|
||||
Put the return type, function name, and the braces that surround the function's
|
||||
code on separate lines, all starting in column 0.
|
||||
|
||||
```c
|
||||
static int
|
||||
foo(int arg)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
When you need to put the function parameters on multiple lines, start new line
|
||||
at column after the opening parenthesis from the initial line.
|
||||
|
||||
```c
|
||||
static int
|
||||
my_function(struct my_struct *p1, struct another_struct *p2,
|
||||
int size)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
In the absence of good reasons for another order, the following parameter order
|
||||
is preferred. One notable exception is that data parameters and their
|
||||
corresponding size parameters should be paired.
|
||||
|
||||
1. The primary object being manipulated, if any (equivalent to the "this"
|
||||
pointer in C++).
|
||||
2. Input-only parameters.
|
||||
3. Input/output parameters.
|
||||
4. Output-only parameters.
|
||||
5. Status parameter.
|
||||
|
||||
Functions that destroy an instance of a dynamically-allocated type should accept
|
||||
and ignore a null pointer argument. Code that calls such a function (including
|
||||
the C standard library function `free()`) should omit a null-pointer check. We
|
||||
find that this usually makes code easier to read.
|
||||
|
||||
#### Function Prototypes
|
||||
|
||||
Put the return type and function name on the same line in a function prototype:
|
||||
|
||||
```c
|
||||
static const struct int foo(int arg);
|
||||
```
|
||||
|
||||
### Statements
|
||||
|
||||
- Indent each level of code with 4 spaces.
|
||||
- Put single space between `if`, `while`, `for`, etc. statements and the
|
||||
expression that follow them. On the other hand, function calls has no space
|
||||
between the function name and opening parenthesis.
|
||||
- Opening code block brace is kept at the same line with the `if`, `while`,
|
||||
`for` or `switch` statements.
|
||||
|
||||
```c
|
||||
if (a) {
|
||||
x = exp(a);
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
```
|
||||
|
||||
- Start switch's cases at the same column as the switch.
|
||||
|
||||
```c
|
||||
switch (conn->state) {
|
||||
case 0:
|
||||
return "data found";
|
||||
case 1:
|
||||
return "data not found";
|
||||
default:
|
||||
return "unknown error";
|
||||
}
|
||||
```
|
||||
|
||||
- Do not put gratuitous parentheses around the expression in a return statement,
|
||||
that is, write `return 0;` and not `return(0);`
|
||||
|
||||
### Types
|
||||
|
||||
Use typedefs sparingly. Code is clearer if the actual type is visible at the
|
||||
point of declaration. Do not, in general, declare a typedef for a struct, union,
|
||||
or enum. Do not declare a typedef for a pointer type, because this can be very
|
||||
confusing to the reader.
|
||||
|
||||
Use the `int<N>_t` and `uint<N>_t` types from `<stdint.h>` for exact-width
|
||||
integer types. Use the `PRId<N>`, `PRIu<N>`, and `PRIx<N>` macros from
|
||||
`<inttypes.h>` for formatting them with `printf()` and related functions.
|
||||
|
||||
Pointer declarators bind to the variable name, not the type name. Write
|
||||
`int *x`, not `int* x` and definitely not `int * x`.
|
||||
|
||||
### Expresions
|
||||
|
||||
Put one space on each side of infix binary and ternary operators:
|
||||
|
||||
```c
|
||||
* / % + - << >> < <= > >= == != & ^ | && || ?: = += -= *= /= %= &= ^= |= <<= >>=
|
||||
```
|
||||
|
||||
Do not put any white space around postfix, prefix, or grouping operators with
|
||||
one exception - `sizeof`, see the note below.
|
||||
|
||||
```c
|
||||
() [] -> . ! ~ ++ -- + - * &
|
||||
```
|
||||
|
||||
The "sizeof" operator is unique among C operators in that it accepts two very
|
||||
different kinds of operands: an expression or a type. In general, prefer to
|
||||
specify an expression
|
||||
```c
|
||||
int *x = calloc(1, sizeof *x);
|
||||
```
|
||||
When the operand of sizeof is an expression, there is no need to parenthesize
|
||||
that operand, and please don't. There is an exception to this rule when you need
|
||||
to work with partially compatible structures:
|
||||
|
||||
```c
|
||||
struct a_s {
|
||||
uint8_t type;
|
||||
}
|
||||
|
||||
struct b_s {
|
||||
uint8_t type;
|
||||
char *str;
|
||||
}
|
||||
|
||||
struct c_s {
|
||||
uint8_t type;
|
||||
uint8_t *u8;
|
||||
}
|
||||
...
|
||||
struct a_s *a;
|
||||
|
||||
switch (type) {
|
||||
case 1:
|
||||
a = (struct a_s *)calloc(1, sizeof(struct b_s));
|
||||
break;
|
||||
case 2:
|
||||
a = (struct a_s *)calloc(1, sizeof(struct c_s));
|
||||
break;
|
||||
...
|
||||
```
|
2457
Doxyfile.in
Normal file
2457
Doxyfile.in
Normal file
File diff suppressed because it is too large
Load diff
89
FindLibYANG.cmake
Normal file
89
FindLibYANG.cmake
Normal file
|
@ -0,0 +1,89 @@
|
|||
# - Try to find LibYANG
|
||||
# Once done this will define
|
||||
#
|
||||
# LIBYANG_FOUND - system has LibYANG
|
||||
# LIBYANG_INCLUDE_DIRS - the LibYANG include directory
|
||||
# LIBYANG_LIBRARIES - Link these to use LibYANG
|
||||
# LIBYANG_VERSION - SO version of the found libyang library
|
||||
#
|
||||
# Author Michal Vasko <mvasko@cesnet.cz>
|
||||
# Copyright (c) 2021 CESNET, z.s.p.o.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. The name of the author may not be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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(FindPackageHandleStandardArgs)
|
||||
|
||||
if(LIBYANG_LIBRARIES AND LIBYANG_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(LIBYANG_FOUND TRUE)
|
||||
else()
|
||||
find_path(LIBYANG_INCLUDE_DIR
|
||||
NAMES
|
||||
libyang/libyang.h
|
||||
PATHS
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
${CMAKE_INCLUDE_PATH}
|
||||
${CMAKE_INSTALL_PREFIX}/include
|
||||
)
|
||||
|
||||
find_library(LIBYANG_LIBRARY
|
||||
NAMES
|
||||
yang
|
||||
libyang
|
||||
PATHS
|
||||
/usr/lib
|
||||
/usr/lib64
|
||||
/usr/local/lib
|
||||
/usr/local/lib64
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
${CMAKE_LIBRARY_PATH}
|
||||
${CMAKE_INSTALL_PREFIX}/lib
|
||||
)
|
||||
|
||||
if(LIBYANG_INCLUDE_DIR)
|
||||
find_path(LY_VERSION_PATH "libyang/version.h" HINTS ${LIBYANG_INCLUDE_DIR})
|
||||
if(LY_VERSION_PATH)
|
||||
file(READ "${LY_VERSION_PATH}/libyang/version.h" LY_VERSION_FILE)
|
||||
else()
|
||||
find_path(LY_HEADER_PATH "libyang/libyang.h" HINTS ${LIBYANG_INCLUDE_DIR})
|
||||
file(READ "${LY_HEADER_PATH}/libyang/libyang.h" LY_VERSION_FILE)
|
||||
endif()
|
||||
string(REGEX MATCH "#define LY_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+\"" LY_VERSION_MACRO "${LY_VERSION_FILE}")
|
||||
string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" LIBYANG_VERSION "${LY_VERSION_MACRO}")
|
||||
endif()
|
||||
|
||||
set(LIBYANG_INCLUDE_DIRS ${LIBYANG_INCLUDE_DIR})
|
||||
set(LIBYANG_LIBRARIES ${LIBYANG_LIBRARY})
|
||||
mark_as_advanced(LIBYANG_INCLUDE_DIRS LIBYANG_LIBRARIES)
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set LIBYANG_FOUND to TRUE
|
||||
# if all listed variables are TRUE
|
||||
find_package_handle_standard_args(LibYANG FOUND_VAR LIBYANG_FOUND
|
||||
REQUIRED_VARS LIBYANG_LIBRARY LIBYANG_INCLUDE_DIR
|
||||
VERSION_VAR LIBYANG_VERSION)
|
||||
endif()
|
28
LICENSE
Normal file
28
LICENSE
Normal file
|
@ -0,0 +1,28 @@
|
|||
Copyright (c) 2015-2024, CESNET
|
||||
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.
|
||||
|
||||
* Neither the name of CESNET nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
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 HOLDER 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.
|
||||
|
274
README.md
Normal file
274
README.md
Normal file
|
@ -0,0 +1,274 @@
|
|||
# libyang
|
||||
|
||||
[![BSD license](https://img.shields.io/badge/License-BSD-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
|
||||
[![Build](https://github.com/CESNET/libyang/workflows/libyang%20CI/badge.svg)](https://github.com/CESNET/libyang/actions?query=workflow%3A%22libyang+CI%22)
|
||||
[![Docs](https://img.shields.io/badge/docs-link-blue)](https://netopeer.liberouter.org/doc/libyang/)
|
||||
[![Coverity Scan Build Status](https://scan.coverity.com/projects/5259/badge.svg)](https://scan.coverity.com/projects/5259)
|
||||
[![codecov.io](https://codecov.io/github/CESNET/libyang/coverage.svg?branch=master)](https://codecov.io/github/CESNET/libyang?branch=master)
|
||||
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/libyang.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:libyang)
|
||||
[![Ohloh Project Status](https://www.openhub.net/p/libyang/widgets/project_thin_badge.gif)](https://www.openhub.net/p/libyang)
|
||||
|
||||
libyang is a YANG data modelling language parser and toolkit written (and
|
||||
providing API) in C. The library is used e.g. in [libnetconf2](https://github.com/CESNET/libnetconf2),
|
||||
[Netopeer2](https://github.com/CESNET/Netopeer2) or [sysrepo](https://github.com/sysrepo/sysrepo) projects.
|
||||
|
||||
## Branches
|
||||
|
||||
The project uses 2 main branches `master` and `devel`. Other branches should not be cloned. In `master` there are files of the
|
||||
last official *release*. Any latest improvements and changes, which were tested at least briefly are found in `devel`. On every
|
||||
new *release*, `devel` is merged into `master`.
|
||||
|
||||
This means that when only stable official releases are to be used, either `master` can be used or specific *releases* downloaded.
|
||||
If all the latest bugfixes should be applied, `devel` branch is the one to be used. Note that whenever **a new issue is created**
|
||||
and it occurs on the `master` branch, the **first response will likely be** to use `devel` before any further provided support.
|
||||
|
||||
## Migration from libyang version 1 or older
|
||||
|
||||
Look into the documentation and the section `Transition Manual`. That should help with basic migration and the
|
||||
ability to compile a project. But to actually make use of the new features, it is required to read through
|
||||
the whole documentation and the API.
|
||||
|
||||
## Provided Features
|
||||
|
||||
* Parsing (and validating) schemas in YANG format.
|
||||
* Parsing (and validating) schemas in YIN format.
|
||||
* Parsing, validating and printing instance data in XML format.
|
||||
* Parsing, validating and printing instance data in JSON format
|
||||
([RFC 7951](https://tools.ietf.org/html/rfc7951)).
|
||||
* Manipulation with the instance data.
|
||||
* Support for default values in the instance data ([RFC 6243](https://tools.ietf.org/html/rfc6243)).
|
||||
* Support for YANG extensions.
|
||||
* Support for YANG Metadata ([RFC 7952](https://tools.ietf.org/html/rfc7952)).
|
||||
* Support for YANG Schema Mount ([RFC 8528](https://tools.ietf.org/html/rfc8528)).
|
||||
* Support for YANG Structure ([RFC 8791](https://tools.ietf.org/html/rfc8791)).
|
||||
* [yanglint](#yanglint) - feature-rich YANG tool.
|
||||
|
||||
Current implementation covers YANG 1.0 ([RFC 6020](https://tools.ietf.org/html/rfc6020))
|
||||
as well as YANG 1.1 ([RFC 7950](https://tools.ietf.org/html/rfc7950)).
|
||||
|
||||
## Packages
|
||||
|
||||
Binary RPM or DEB packages of the latest release can be built locally using `apkg`, look into `README` in
|
||||
the `distro` directory.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Unix Build Requirements
|
||||
|
||||
* C compiler
|
||||
* cmake >= 2.8.12
|
||||
* libpcre2 >= 10.21 (including devel package)
|
||||
* note, that PCRE is supposed to be compiled with unicode support (configure's options
|
||||
`--enable-utf` and `--enable-unicode-properties`)
|
||||
|
||||
#### Optional
|
||||
|
||||
* doxygen (for generating documentation)
|
||||
* cmocka >= 1.0.1 (for [tests](#Tests))
|
||||
* valgrind (for enhanced testing)
|
||||
* gcov (for code coverage)
|
||||
* lcov (for code coverage)
|
||||
* genhtml (for code coverage)
|
||||
|
||||
### Unix Runtime Requirements
|
||||
|
||||
* libpcre2 >= 10.21
|
||||
|
||||
### Windows Build Requirements
|
||||
|
||||
* Visual Studio 17 (2022)
|
||||
* cmake >= 3.22.0
|
||||
* libpcre2 (same considerations as on POSIX)
|
||||
* [`pthreads-win32`](https://sourceware.org/pthreads-win32/)
|
||||
* [`dirent`](https://github.com/tronkko/dirent)
|
||||
* [`dlfcn-win32`](https://github.com/dlfcn-win32/dlfcn-win32)
|
||||
* [`getopt-win32`](https://github.com/libimobiledevice-win32/getopt)
|
||||
|
||||
The Windows version [does not support plugins](https://github.com/CESNET/libyang/commit/323c31221645052e13db83f7d0e6e51c3ce9d802), and the `yanglint` works in a [non-interactive mode](https://github.com/CESNET/libyang/commit/2e3f935ed6f4a47e65b31de5aeebcd8877d5a09b) only.
|
||||
On Windows, all YANG date-and-time values are first converted to UTC (if TZ offset was specified), and then returned with "unspecified timezone".
|
||||
|
||||
## Building
|
||||
|
||||
```
|
||||
$ mkdir build; cd build
|
||||
$ cmake ..
|
||||
$ make
|
||||
# make install
|
||||
```
|
||||
|
||||
### Useful CMake Options
|
||||
|
||||
#### Changing Compiler
|
||||
|
||||
Set `CC` variable:
|
||||
|
||||
```
|
||||
$ CC=/usr/bin/clang cmake ..
|
||||
```
|
||||
|
||||
#### Changing Install Path
|
||||
|
||||
To change the prefix where the library, headers and any other files are installed,
|
||||
set `CMAKE_INSTALL_PREFIX` variable:
|
||||
```
|
||||
$ cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr ..
|
||||
```
|
||||
|
||||
Default prefix is `/usr/local`.
|
||||
|
||||
#### Build Modes
|
||||
|
||||
There are two build modes:
|
||||
* Release.
|
||||
This generates library for the production use without any debug information.
|
||||
* Debug.
|
||||
This generates library with the debug information and disables optimization
|
||||
of the code.
|
||||
|
||||
The `Debug` mode is currently used as the default one. to switch to the
|
||||
`Release` mode, enter at the command line:
|
||||
```
|
||||
$ cmake -D CMAKE_BUILD_TYPE:String="Release" ..
|
||||
```
|
||||
|
||||
#### Changing Extensions Plugins Directory
|
||||
|
||||
As for YANG extensions, libyang allows loading extension plugins. By default, the
|
||||
directory to store the plugins is LIBDIR/libyang. To change it, use the following
|
||||
cmake option with the value specifying the desired directory:
|
||||
|
||||
```
|
||||
$ cmake -DPLUGINS_DIR:PATH=`pwd`"/src/extensions/" ..
|
||||
```
|
||||
|
||||
The directory path can be also changed runtime via environment variable, e.g.:
|
||||
|
||||
```
|
||||
$ LIBYANG_EXTENSIONS_PLUGINS_DIR=`pwd`/my/relative/path yanglint
|
||||
```
|
||||
|
||||
Note that plugins are [not available on Windows](https://github.com/CESNET/libyang/commit/323c31221645052e13db83f7d0e6e51c3ce9d802).
|
||||
|
||||
#### Optimizations
|
||||
|
||||
Whenever the latest revision of a schema is supposed to be loaded (import without specific revision),
|
||||
it is performed in the standard way, the first time. By default, every other time when the latest
|
||||
revision of the same schema is needed, the one initially loaded is reused. If you know this can cause
|
||||
problems meaning the latest available revision of a schema can change during operation, you can force
|
||||
libyang to always search for the schema anew by:
|
||||
|
||||
```
|
||||
$ cmake -DENABLE_LATEST_REVISIONS=OFF ..
|
||||
```
|
||||
|
||||
### CMake Notes
|
||||
|
||||
Note that, with CMake, if you want to change the compiler or its options after
|
||||
you already ran CMake, you need to clear its cache first - the most simple way
|
||||
to do it is to remove all content from the 'build' directory.
|
||||
|
||||
## Usage
|
||||
|
||||
All libyang functions are available via the main header:
|
||||
```
|
||||
#include <libyang/libyang.h>
|
||||
```
|
||||
|
||||
To compile your program with libyang, it is necessary to link it with libyang using the
|
||||
following linker parameters:
|
||||
```
|
||||
-lyang
|
||||
```
|
||||
|
||||
Note, that it may be necessary to call `ldconfig(8)` after library installation and if the
|
||||
library was installed into a non-standard path, the path to libyang must be specified to the
|
||||
linker. To help with setting all the compiler's options, there is `libyang.pc` file for
|
||||
`pkg-config(1)` available in the source tree. The file is installed with the library.
|
||||
|
||||
If you are using `cmake` in you project, it is also possible to use the provided
|
||||
`FindLibYANG.cmake` file to detect presence of the libyang library in the system.
|
||||
|
||||
## Bindings
|
||||
|
||||
There are no bindings for other languages directly in this project but they are
|
||||
available separately.
|
||||
|
||||
* [Python](https://github.com/CESNET/libyang-python/)
|
||||
* [C++](https://github.com/CESNET/libyang-cpp/)
|
||||
* [Rust](https://github.com/holo-routing/yang2-rs/)
|
||||
|
||||
## yanglint
|
||||
|
||||
libyang project includes a feature-rich tool called `yanglint(1)` for validation
|
||||
and conversion of the schemas and YANG modeled data. The source codes are
|
||||
located at [`/tools/lint`](./tools/lint) and can be used to explore how an
|
||||
application is supposed to use the libyang library. `yanglint(1)` binary as
|
||||
well as its man page are installed together with the library itself.
|
||||
|
||||
There is also [README](./tools/lint/examples/README.md) describing some examples of
|
||||
using `yanglint`.
|
||||
|
||||
## Tests
|
||||
|
||||
libyang includes several tests built with [cmocka](https://cmocka.org/). The tests
|
||||
can be found in `tests` subdirectory and they are designed for checking library
|
||||
functionality after code changes. Additional regression tests done with
|
||||
a corpus of fuzzing inputs that previously caused crashes are done.
|
||||
Those are available in `tests/fuzz` and are built automatically with the
|
||||
cmocka unit tests.
|
||||
|
||||
|
||||
The tests are by default built in the `Debug` build mode by running
|
||||
```
|
||||
$ make
|
||||
```
|
||||
|
||||
In case of the `Release` mode, the tests are not built by default (it requires
|
||||
additional dependency), but they can be enabled via cmake option:
|
||||
```
|
||||
$ cmake -DENABLE_TESTS=ON ..
|
||||
```
|
||||
|
||||
Note that if the necessary [cmocka](https://cmocka.org/) headers are not present
|
||||
in the system include paths, tests are not available despite the build mode or
|
||||
cmake's options.
|
||||
|
||||
Tests can be run by the make's `test` target:
|
||||
```
|
||||
$ make test
|
||||
```
|
||||
|
||||
### Perf
|
||||
|
||||
There is a performance measurement tool included that prints information about
|
||||
the time required to execute common use-cases of working with YANG instance data.
|
||||
|
||||
To enable this test, use an option and to get representative results, enable Release build type:
|
||||
```
|
||||
$ cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_PERF_TESTS=ON ..
|
||||
```
|
||||
and to run the test with seeing its output run:
|
||||
```
|
||||
$ make
|
||||
$ ctest -V -R ly_perf
|
||||
```
|
||||
|
||||
### Code Coverage
|
||||
|
||||
Based on the tests run, it is possible to generate code coverage report. But
|
||||
it must be enabled and these commands are needed to generate the report:
|
||||
```
|
||||
$ cmake -DENABLE_COVERAGE=ON ..
|
||||
$ make
|
||||
$ make coverage
|
||||
```
|
||||
|
||||
## Fuzzing
|
||||
|
||||
Multiple YANG fuzzing targets and fuzzing instructions are available in the
|
||||
`tests/fuzz` directory.
|
||||
|
||||
All of the targets can be fuzzed with LLVM's LibFuzzer and AFL, and new targets
|
||||
can easily be added.
|
||||
Asciinema examples which describe the fuzzing setup for both AFL (https://asciinema.org/a/311060)
|
||||
and LibFuzzer (https://asciinema.org/a/311035) are available.
|
31
codecov.yml
Normal file
31
codecov.yml
Normal file
|
@ -0,0 +1,31 @@
|
|||
comment:
|
||||
layout: header, changes, diff
|
||||
|
||||
coverage:
|
||||
precision: 2
|
||||
round: nearest
|
||||
|
||||
ignore:
|
||||
- compat/.*
|
||||
- tests/.*
|
||||
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
target: auto
|
||||
if_no_uploads: error
|
||||
|
||||
patch:
|
||||
default:
|
||||
if_no_uploads: error
|
||||
|
||||
changes: true
|
||||
|
||||
parsers:
|
||||
gcov:
|
||||
branch_detection:
|
||||
macro: no
|
||||
loop: no
|
||||
conditional: no
|
||||
method: no
|
||||
|
44
compat/check_includes.sh
Executable file
44
compat/check_includes.sh
Executable file
|
@ -0,0 +1,44 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
RETVAL=0
|
||||
|
||||
# params - paths to the source files to search
|
||||
SRC="$*"
|
||||
|
||||
# param FUNC - name of the function in compat to check
|
||||
check_compat_func () {
|
||||
FILES=`grep -rE "([^[:alnum:]]|^)$1\([^\)]+\)" --include=\*.{c,h} $SRC | cut -d: -f1 | uniq`
|
||||
for f in $FILES; do
|
||||
grep -q "#include \"compat.h\"" $f
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Missing #include \"compat.h\" in file $f for function $1()"
|
||||
RETVAL=$((RETVAL+1))
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
check_compat_macro () {
|
||||
FILES=`grep -rE "([^[:alnum:]]|^)$1([^[:alnum:]]|$)" --include=\*.{c,h} $SRC | cut -d: -f1 | uniq`
|
||||
for f in $FILES; do
|
||||
grep -q "#include \"compat.h\"" $f
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Missing #include \"compat.h\" in file $f for macro $1"
|
||||
RETVAL=$((RETVAL+1))
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
check_compat_func vdprintf
|
||||
check_compat_func asprintf
|
||||
check_compat_func vasprintf
|
||||
check_compat_func getline
|
||||
check_compat_func strndup
|
||||
check_compat_func strnstr
|
||||
check_compat_func strdupa
|
||||
check_compat_func strchrnul
|
||||
check_compat_func get_current_dir_name
|
||||
check_compat_func pthread_mutex_timedlock
|
||||
check_compat_func UNUSED
|
||||
check_compat_macro _PACKED
|
||||
|
||||
exit $RETVAL
|
383
compat/compat.c
Normal file
383
compat/compat.c
Normal file
|
@ -0,0 +1,383 @@
|
|||
/**
|
||||
* @file compat.c
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief compatibility functions
|
||||
*
|
||||
* Copyright (c) 2021 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
#define _POSIX_C_SOURCE 200809L /* fdopen, _POSIX_PATH_MAX, strdup */
|
||||
#define _ISOC99_SOURCE /* vsnprintf */
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef _MSC_VER
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef HAVE_VDPRINTF
|
||||
int
|
||||
vdprintf(int fd, const char *format, va_list ap)
|
||||
{
|
||||
FILE *stream;
|
||||
int count = 0;
|
||||
|
||||
stream = fdopen(dup(fd), "a+");
|
||||
if (stream) {
|
||||
count = vfprintf(stream, format, ap);
|
||||
fclose(stream);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ASPRINTF
|
||||
int
|
||||
asprintf(char **strp, const char *fmt, ...)
|
||||
{
|
||||
int ret;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = vasprintf(strp, fmt, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_VASPRINTF
|
||||
int
|
||||
vasprintf(char **strp, const char *fmt, va_list ap)
|
||||
{
|
||||
va_list ap2;
|
||||
|
||||
va_copy(ap2, ap);
|
||||
int l = vsnprintf(0, 0, fmt, ap2);
|
||||
|
||||
va_end(ap2);
|
||||
|
||||
if ((l < 0) || !(*strp = malloc(l + 1U))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return vsnprintf(*strp, l + 1U, fmt, ap);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETLINE
|
||||
ssize_t
|
||||
getline(char **lineptr, size_t *n, FILE *stream)
|
||||
{
|
||||
static char chunk[256];
|
||||
char *ptr;
|
||||
ssize_t len, written;
|
||||
|
||||
if (!lineptr || !n) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ferror(stream) || feof(stream)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*n = *lineptr ? *n : 0;
|
||||
written = 0;
|
||||
while (fgets(chunk, sizeof(chunk), stream)) {
|
||||
len = strlen(chunk);
|
||||
if ((size_t)(written + len) > *n) {
|
||||
ptr = realloc(*lineptr, *n + sizeof(chunk));
|
||||
if (!ptr) {
|
||||
return -1;
|
||||
}
|
||||
*lineptr = ptr;
|
||||
*n = *n + sizeof(chunk);
|
||||
}
|
||||
memcpy(*lineptr + written, &chunk, len);
|
||||
written += len;
|
||||
if ((*lineptr)[written - 1] == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (written) {
|
||||
(*lineptr)[written] = '\0';
|
||||
} else {
|
||||
written = -1;
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRNDUP
|
||||
char *
|
||||
strndup(const char *s, size_t n)
|
||||
{
|
||||
char *buf;
|
||||
size_t len = 0;
|
||||
|
||||
/* strnlen */
|
||||
for ( ; (len < n) && (s[len] != '\0'); ++len) {}
|
||||
|
||||
if (!(buf = malloc(len + 1U))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(buf, s, len);
|
||||
buf[len] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRNSTR
|
||||
char *
|
||||
strnstr(const char *s, const char *find, size_t slen)
|
||||
{
|
||||
char c, sc;
|
||||
size_t len;
|
||||
|
||||
if ((c = *find++) != '\0') {
|
||||
len = strlen(find);
|
||||
do {
|
||||
do {
|
||||
if ((slen-- < 1) || ((sc = *s++) == '\0')) {
|
||||
return NULL;
|
||||
}
|
||||
} while (sc != c);
|
||||
if (len > slen) {
|
||||
return NULL;
|
||||
}
|
||||
} while (strncmp(s, find, len));
|
||||
s--;
|
||||
}
|
||||
return (char *)s;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRCHRNUL
|
||||
char *
|
||||
strchrnul(const char *s, int c)
|
||||
{
|
||||
char *p = strchr(s, c);
|
||||
|
||||
return p ? p : (char *)s + strlen(s);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GET_CURRENT_DIR_NAME
|
||||
char *
|
||||
get_current_dir_name(void)
|
||||
{
|
||||
char tmp[_POSIX_PATH_MAX];
|
||||
char *retval = NULL;
|
||||
|
||||
if (getcwd(tmp, sizeof(tmp))) {
|
||||
retval = strdup(tmp);
|
||||
if (!retval) {
|
||||
errno = ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK
|
||||
int
|
||||
pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abstime)
|
||||
{
|
||||
int64_t nsec_diff;
|
||||
int32_t diff;
|
||||
struct timespec cur, dur;
|
||||
int rc;
|
||||
|
||||
/* try to acquire the lock and, if we fail, sleep for 5ms. */
|
||||
while ((rc = pthread_mutex_trylock(mutex)) == EBUSY) {
|
||||
/* get real time */
|
||||
#ifdef CLOCK_REALTIME
|
||||
clock_gettime(CLOCK_REALTIME, &cur);
|
||||
#else
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
cur.tv_sec = (time_t)tv.tv_sec;
|
||||
cur.tv_nsec = 1000L * (long)tv.tv_usec;
|
||||
#endif
|
||||
|
||||
/* get time diff */
|
||||
nsec_diff = 0;
|
||||
nsec_diff += (((int64_t)abstime->tv_sec) - ((int64_t)cur.tv_sec)) * 1000000000L;
|
||||
nsec_diff += ((int64_t)abstime->tv_nsec) - ((int64_t)cur.tv_nsec);
|
||||
diff = (nsec_diff ? nsec_diff / 1000000L : 0);
|
||||
|
||||
if (diff < 1) {
|
||||
/* timeout */
|
||||
break;
|
||||
} else if (diff < 5) {
|
||||
/* sleep until timeout */
|
||||
dur.tv_sec = 0;
|
||||
dur.tv_nsec = (long)diff * 1000000;
|
||||
} else {
|
||||
/* sleep 5 ms */
|
||||
dur.tv_sec = 0;
|
||||
dur.tv_nsec = 5000000;
|
||||
}
|
||||
|
||||
nanosleep(&dur, NULL);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_REALPATH
|
||||
#ifdef _WIN32
|
||||
char *
|
||||
realpath(const char *path, char *resolved_path)
|
||||
{
|
||||
char *resolved = _fullpath(resolved_path, path, PATH_MAX);
|
||||
|
||||
if ((_access(resolved, 0) == -1) && (errno == ENOENT)) {
|
||||
return NULL;
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
||||
#elif defined (__NetBSD__)
|
||||
char *
|
||||
realpath(const char *path, char *resolved_path)
|
||||
{
|
||||
ssize_t nbytes;
|
||||
|
||||
nbytes = readlink(path, resolved_path, PATH_MAX);
|
||||
if (nbytes == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return resolved_path;
|
||||
}
|
||||
|
||||
#else
|
||||
#error No realpath() implementation for this platform is available.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LOCALTIME_R
|
||||
#ifdef _WIN32
|
||||
struct tm *
|
||||
localtime_r(const time_t *timep, struct tm *result)
|
||||
{
|
||||
errno_t res = localtime_s(result, timep);
|
||||
|
||||
if (res) {
|
||||
return NULL;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#error No localtime_r() implementation for this platform is available.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GMTIME_R
|
||||
#ifdef _WIN32
|
||||
struct tm *
|
||||
gmtime_r(const time_t *timep, struct tm *result)
|
||||
{
|
||||
errno_t res = gmtime_s(result, timep);
|
||||
|
||||
if (res) {
|
||||
return NULL;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#error No gmtime_r() implementation for this platform is available.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_TIMEGM
|
||||
time_t
|
||||
timegm(struct tm *tm)
|
||||
{
|
||||
pthread_mutex_t tz_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
time_t ret;
|
||||
char *tz;
|
||||
|
||||
pthread_mutex_lock(&tz_lock);
|
||||
|
||||
tz = getenv("TZ");
|
||||
if (tz) {
|
||||
tz = strdup(tz);
|
||||
}
|
||||
setenv("TZ", "", 1);
|
||||
tzset();
|
||||
|
||||
ret = mktime(tm);
|
||||
|
||||
if (tz) {
|
||||
setenv("TZ", tz, 1);
|
||||
free(tz);
|
||||
} else {
|
||||
unsetenv("TZ");
|
||||
}
|
||||
tzset();
|
||||
|
||||
pthread_mutex_unlock(&tz_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SETENV
|
||||
#ifdef _WIN32
|
||||
int
|
||||
setenv(const char *name, const char *value, int overwrite)
|
||||
{
|
||||
int errcode = 0;
|
||||
|
||||
if (!overwrite) {
|
||||
size_t envsize = 0;
|
||||
|
||||
errcode = getenv_s(&envsize, NULL, 0, name);
|
||||
if (errcode || envsize) {
|
||||
return errcode;
|
||||
}
|
||||
}
|
||||
return _putenv_s(name, value);
|
||||
}
|
||||
|
||||
#else
|
||||
#error No setenv() implementation for this platform is available.
|
||||
#endif
|
||||
#endif
|
215
compat/compat.h.in
Normal file
215
compat/compat.h.in
Normal file
|
@ -0,0 +1,215 @@
|
|||
/**
|
||||
* @file compat.h
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief compatibility functions header
|
||||
*
|
||||
* Copyright (c) 2021 - 2023 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef _COMPAT_H_
|
||||
#define _COMPAT_H_
|
||||
|
||||
#ifdef _WIN32
|
||||
/* headers are broken on Windows, which means that some of them simply *have* to come first */
|
||||
# include <winsock2.h>
|
||||
# include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef __WORDSIZE
|
||||
# if defined __x86_64__ && !defined __ILP32__
|
||||
# define __WORDSIZE 64
|
||||
# else
|
||||
# define __WORDSIZE 32
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef __INT64_C
|
||||
# if __WORDSIZE == 64
|
||||
# define __INT64_C(c) c ## L
|
||||
# define __UINT64_C(c) c ## UL
|
||||
# else
|
||||
# define __INT64_C(c) c ## LL
|
||||
# define __UINT64_C(c) c ## ULL
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined (__GNUC__) || defined (__llvm__)
|
||||
# define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
|
||||
# define _PACKED __attribute__((__packed__))
|
||||
#else
|
||||
# define UNUSED(x) UNUSED_ ## x
|
||||
# define _PACKED
|
||||
#endif
|
||||
|
||||
#cmakedefine HAVE_VDPRINTF
|
||||
#cmakedefine HAVE_ASPRINTF
|
||||
#cmakedefine HAVE_VASPRINTF
|
||||
#cmakedefine HAVE_GETLINE
|
||||
#cmakedefine HAVE_STRNDUP
|
||||
#cmakedefine HAVE_STRNSTR
|
||||
#cmakedefine HAVE_STRDUPA
|
||||
#cmakedefine HAVE_STRCHRNUL
|
||||
#cmakedefine HAVE_GET_CURRENT_DIR_NAME
|
||||
#cmakedefine HAVE_PTHREAD_MUTEX_TIMEDLOCK
|
||||
#cmakedefine HAVE_REALPATH
|
||||
#cmakedefine HAVE_LOCALTIME_R
|
||||
#cmakedefine HAVE_GMTIME_R
|
||||
#cmakedefine HAVE_TIMEGM
|
||||
#cmakedefine HAVE_STRPTIME
|
||||
#cmakedefine HAVE_MMAP
|
||||
#cmakedefine HAVE_STRCASECMP
|
||||
#cmakedefine HAVE_SETENV
|
||||
|
||||
#ifndef bswap64
|
||||
#define bswap64(val) \
|
||||
( (((val) >> 56) & 0x00000000000000FF) | (((val) >> 40) & 0x000000000000FF00) | \
|
||||
(((val) >> 24) & 0x0000000000FF0000) | (((val) >> 8) & 0x00000000FF000000) | \
|
||||
(((val) << 8) & 0x000000FF00000000) | (((val) << 24) & 0x0000FF0000000000) | \
|
||||
(((val) << 40) & 0x00FF000000000000) | (((val) << 56) & 0xFF00000000000000) )
|
||||
#endif
|
||||
|
||||
#undef le64toh
|
||||
#undef htole64
|
||||
|
||||
#cmakedefine IS_BIG_ENDIAN
|
||||
|
||||
#ifdef IS_BIG_ENDIAN
|
||||
# define le64toh(x) bswap64(x)
|
||||
# define htole64(x) bswap64(x)
|
||||
#else
|
||||
# define le64toh(x) (x)
|
||||
# define htole64(x) (x)
|
||||
#endif
|
||||
|
||||
#cmakedefine HAVE_STDATOMIC
|
||||
|
||||
#ifdef HAVE_STDATOMIC
|
||||
# include <stdatomic.h>
|
||||
|
||||
# define ATOMIC_T atomic_uint_fast32_t
|
||||
# define ATOMIC_T_MAX UINT_FAST32_MAX
|
||||
|
||||
# define ATOMIC_STORE_RELAXED(var, x) atomic_store_explicit(&(var), x, memory_order_relaxed)
|
||||
# define ATOMIC_LOAD_RELAXED(var) atomic_load_explicit(&(var), memory_order_relaxed)
|
||||
# define ATOMIC_INC_RELAXED(var) atomic_fetch_add_explicit(&(var), 1, memory_order_relaxed)
|
||||
# define ATOMIC_ADD_RELAXED(var, x) atomic_fetch_add_explicit(&(var), x, memory_order_relaxed)
|
||||
# define ATOMIC_DEC_RELAXED(var) atomic_fetch_sub_explicit(&(var), 1, memory_order_relaxed)
|
||||
# define ATOMIC_SUB_RELAXED(var, x) atomic_fetch_sub_explicit(&(var), x, memory_order_relaxed)
|
||||
#else
|
||||
# include <stdint.h>
|
||||
|
||||
# define ATOMIC_T uint32_t
|
||||
# define ATOMIC_T_MAX UINT32_MAX
|
||||
|
||||
# define ATOMIC_STORE_RELAXED(var, x) ((var) = (x))
|
||||
# define ATOMIC_LOAD_RELAXED(var) (var)
|
||||
# ifndef _WIN32
|
||||
# define ATOMIC_INC_RELAXED(var) __sync_fetch_and_add(&(var), 1)
|
||||
# define ATOMIC_ADD_RELAXED(var, x) __sync_fetch_and_add(&(var), x)
|
||||
# define ATOMIC_DEC_RELAXED(var) __sync_fetch_and_sub(&(var), 1)
|
||||
# define ATOMIC_SUB_RELAXED(var, x) __sync_fetch_and_sub(&(var), x)
|
||||
# else
|
||||
# include <windows.h>
|
||||
# define ATOMIC_INC_RELAXED(var) InterlockedExchangeAdd(&(var), 1)
|
||||
# define ATOMIC_ADD_RELAXED(var, x) InterlockedExchangeAdd(&(var), x)
|
||||
# define ATOMIC_DEC_RELAXED(var) InterlockedExchangeAdd(&(var), -1)
|
||||
# define ATOMIC_SUB_RELAXED(var, x) InterlockedExchangeAdd(&(var), -(x))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_VDPRINTF
|
||||
int vdprintf(int fd, const char *format, va_list ap);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ASPRINTF
|
||||
int asprintf(char **strp, const char *fmt, ...);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_VASPRINTF
|
||||
int vasprintf(char **strp, const char *fmt, va_list ap);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETLINE
|
||||
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRNDUP
|
||||
char *strndup(const char *s, size_t n);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRNSTR
|
||||
char *strnstr(const char *s, const char *find, size_t slen);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRDUPA
|
||||
#define strdupa(s) ( \
|
||||
{ \
|
||||
char *buf; \
|
||||
size_t len = strlen(s); \
|
||||
buf = alloca(len + 1); \
|
||||
buf[len] = '\0'; \
|
||||
(char *)memcpy(buf, s, len); \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRCHRNUL
|
||||
char *strchrnul(const char *s, int c);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GET_CURRENT_DIR_NAME
|
||||
char *get_current_dir_name(void);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK
|
||||
int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abstime);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_REALPATH
|
||||
char *realpath(const char *path, char *resolved_path);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LOCALTIME_R
|
||||
struct tm *localtime_r(const time_t *timep, struct tm *result);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GMTIME_R
|
||||
struct tm *gmtime_r(const time_t *timep, struct tm *result);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_TIMEGM
|
||||
# ifdef _WIN32
|
||||
# define timegm _mkgmtime
|
||||
# define HAVE_TIMEGM
|
||||
|
||||
# else
|
||||
time_t timegm(struct tm *tm);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRPTIME
|
||||
char *strptime(const char *s, const char *format, struct tm *tm);
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# define strtok_r strtok_s
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SETENV
|
||||
int setenv(const char *name, const char *value, int overwrite);
|
||||
#endif
|
||||
|
||||
#endif /* _COMPAT_H_ */
|
1
compat/posix-shims/libgen.h
Normal file
1
compat/posix-shims/libgen.h
Normal file
|
@ -0,0 +1 @@
|
|||
char *dirname(char *path);
|
17
compat/posix-shims/strings.h
Normal file
17
compat/posix-shims/strings.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include <compat.h>
|
||||
|
||||
#ifndef HAVE_STRCASECMP
|
||||
#ifdef _MSC_VER
|
||||
#define strcasecmp _stricmp
|
||||
#else
|
||||
#error No strcasecmp() implementation for this platform is available.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRNCASECMP
|
||||
#ifdef _MSC_VER
|
||||
#define strncasecmp _strnicmp
|
||||
#else
|
||||
#error No strncasecmp() implementation for this platform is available.
|
||||
#endif
|
||||
#endif
|
78
compat/posix-shims/unistd.h
Normal file
78
compat/posix-shims/unistd.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
#ifndef _UNISTD_H
|
||||
#define _UNISTD_H 1
|
||||
|
||||
/* headers are broken on Windows, which means that some of them simply *have* to come first */
|
||||
# include <winsock2.h>
|
||||
# include <ws2tcpip.h>
|
||||
|
||||
/* This is intended as a drop-in replacement for unistd.h on Windows.
|
||||
* Please add functionality as neeeded.
|
||||
* https://stackoverflow.com/a/826027/1202830
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <io.h>
|
||||
#include <process.h> /* for getpid() and the exec..() family */
|
||||
#include <direct.h> /* for _getcwd() and _chdir() */
|
||||
|
||||
#define srandom srand
|
||||
#define random rand
|
||||
|
||||
/* Values for the second argument to access.
|
||||
These may be OR'd together. */
|
||||
#define R_OK 4 /* Test for read permission. */
|
||||
#define W_OK 2 /* Test for write permission. */
|
||||
#define X_OK 0 /* jkt: unsupported on Windows, so we don't really care */
|
||||
#define F_OK 0 /* Test for existence. */
|
||||
|
||||
#define access _access
|
||||
#define dup2 _dup2
|
||||
#define execve _execve
|
||||
#define ftruncate _chsize
|
||||
#define unlink _unlink
|
||||
#define fileno _fileno
|
||||
#define getcwd _getcwd
|
||||
#define chdir _chdir
|
||||
#define isatty _isatty
|
||||
#define lseek _lseek
|
||||
#define fsync _commit
|
||||
#define timegm _mkgmtime
|
||||
/* read, write, and close are NOT being #defined here, because while there are file handle specific versions for Windows, they probably don't work for sockets. You need to look at your app and consider whether to call e.g. closesocket(). */
|
||||
|
||||
#define ssize_t SSIZE_T
|
||||
|
||||
#define STDIN_FILENO 0
|
||||
#define STDOUT_FILENO 1
|
||||
#define STDERR_FILENO 2
|
||||
/* should be in some equivalent to <sys/types.h> */
|
||||
typedef __int8 int8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
#include <windows.h>
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX MAX_PATH
|
||||
#endif
|
||||
#ifndef _POSIX_PATH_MAX
|
||||
#define _POSIX_PATH_MAX 256
|
||||
#endif
|
||||
|
||||
#ifndef S_ISREG
|
||||
# define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG)
|
||||
#endif
|
||||
#ifndef S_ISDIR
|
||||
# define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
|
||||
#endif
|
||||
#ifndef S_IRUSR
|
||||
# define S_IRUSR _S_IREAD
|
||||
#endif
|
||||
#ifndef S_IWUSR
|
||||
# define S_IWUSR _S_IWRITE
|
||||
#endif
|
||||
|
||||
#endif /* unistd.h */
|
214
compat/strptime.c
Normal file
214
compat/strptime.c
Normal file
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* This comes from the musl C library which has been licensed under the permissive MIT license.
|
||||
*
|
||||
* Downloaded from https://git.musl-libc.org/cgit/musl/plain/src/time/strptime.c,
|
||||
* commit 98e688a9da5e7b2925dda17a2d6820dddf1fb287.
|
||||
*
|
||||
* Lobotomized to remove references to nl_langinfo().
|
||||
* Adjusted coding style to fit libyang's uncrustify rules.
|
||||
* */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
char *
|
||||
strptime(const char * restrict s, const char * restrict f, struct tm * restrict tm)
|
||||
{
|
||||
int i, w, neg, adj, min, range, *dest, dummy;
|
||||
int want_century = 0, century = 0, relyear = 0;
|
||||
|
||||
while (*f) {
|
||||
if (*f != '%') {
|
||||
if (isspace(*f)) {
|
||||
for ( ; *s && isspace(*s); s++) {}
|
||||
} else if (*s != *f) {
|
||||
return 0;
|
||||
} else {
|
||||
s++;
|
||||
}
|
||||
f++;
|
||||
continue;
|
||||
}
|
||||
f++;
|
||||
if (*f == '+') {
|
||||
f++;
|
||||
}
|
||||
if (isdigit(*f)) {
|
||||
char *new_f;
|
||||
|
||||
w = strtoul(f, &new_f, 10);
|
||||
f = new_f;
|
||||
} else {
|
||||
w = -1;
|
||||
}
|
||||
adj = 0;
|
||||
switch (*f++) {
|
||||
case 'a':
|
||||
case 'A':
|
||||
case 'b':
|
||||
case 'B':
|
||||
case 'h':
|
||||
case 'c':
|
||||
goto fail_nl_langinfo;
|
||||
case 'C':
|
||||
dest = ¢ury;
|
||||
if (w < 0) {
|
||||
w = 2;
|
||||
}
|
||||
want_century |= 2;
|
||||
goto numeric_digits;
|
||||
case 'd':
|
||||
case 'e':
|
||||
dest = &tm->tm_mday;
|
||||
min = 1;
|
||||
range = 31;
|
||||
goto numeric_range;
|
||||
case 'D':
|
||||
s = strptime(s, "%m/%d/%y", tm);
|
||||
if (!s) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 'H':
|
||||
dest = &tm->tm_hour;
|
||||
min = 0;
|
||||
range = 24;
|
||||
goto numeric_range;
|
||||
case 'I':
|
||||
dest = &tm->tm_hour;
|
||||
min = 1;
|
||||
range = 12;
|
||||
goto numeric_range;
|
||||
case 'j':
|
||||
dest = &tm->tm_yday;
|
||||
min = 1;
|
||||
range = 366;
|
||||
adj = 1;
|
||||
goto numeric_range;
|
||||
case 'm':
|
||||
dest = &tm->tm_mon;
|
||||
min = 1;
|
||||
range = 12;
|
||||
adj = 1;
|
||||
goto numeric_range;
|
||||
case 'M':
|
||||
dest = &tm->tm_min;
|
||||
min = 0;
|
||||
range = 60;
|
||||
goto numeric_range;
|
||||
case 'n':
|
||||
case 't':
|
||||
for ( ; *s && isspace(*s); s++) {}
|
||||
break;
|
||||
case 'p':
|
||||
case 'r':
|
||||
goto fail_nl_langinfo;
|
||||
case 'R':
|
||||
s = strptime(s, "%H:%M", tm);
|
||||
if (!s) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
dest = &tm->tm_sec;
|
||||
min = 0;
|
||||
range = 61;
|
||||
goto numeric_range;
|
||||
case 'T':
|
||||
s = strptime(s, "%H:%M:%S", tm);
|
||||
if (!s) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 'U':
|
||||
case 'W':
|
||||
/* Throw away result, for now. (FIXME?) */
|
||||
dest = &dummy;
|
||||
min = 0;
|
||||
range = 54;
|
||||
goto numeric_range;
|
||||
case 'w':
|
||||
dest = &tm->tm_wday;
|
||||
min = 0;
|
||||
range = 7;
|
||||
goto numeric_range;
|
||||
case 'x':
|
||||
case 'X':
|
||||
goto fail_nl_langinfo;
|
||||
case 'y':
|
||||
dest = &relyear;
|
||||
w = 2;
|
||||
want_century |= 1;
|
||||
goto numeric_digits;
|
||||
case 'Y':
|
||||
dest = &tm->tm_year;
|
||||
if (w < 0) {
|
||||
w = 4;
|
||||
}
|
||||
adj = 1900;
|
||||
want_century = 0;
|
||||
goto numeric_digits;
|
||||
case '%':
|
||||
if (*s++ != '%') {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
numeric_range:
|
||||
if (!isdigit(*s)) {
|
||||
return 0;
|
||||
}
|
||||
*dest = 0;
|
||||
for (i = 1; i <= min + range && isdigit(*s); i *= 10) {
|
||||
*dest = *dest * 10 + *s++ - '0';
|
||||
}
|
||||
if (*dest - min >= range) {
|
||||
return 0;
|
||||
}
|
||||
*dest -= adj;
|
||||
switch ((char *)dest - (char *)tm) {
|
||||
case offsetof(struct tm, tm_yday):
|
||||
;
|
||||
}
|
||||
goto update;
|
||||
numeric_digits:
|
||||
neg = 0;
|
||||
if (*s == '+') {
|
||||
s++;
|
||||
} else if (*s == '-') {
|
||||
neg = 1, s++;
|
||||
}
|
||||
if (!isdigit(*s)) {
|
||||
return 0;
|
||||
}
|
||||
for (*dest = i = 0; i < w && isdigit(*s); i++) {
|
||||
*dest = *dest * 10 + *s++ - '0';
|
||||
}
|
||||
if (neg) {
|
||||
*dest = -*dest;
|
||||
}
|
||||
*dest -= adj;
|
||||
goto update;
|
||||
update:
|
||||
// FIXME
|
||||
;
|
||||
}
|
||||
}
|
||||
if (want_century) {
|
||||
tm->tm_year = relyear;
|
||||
if (want_century & 2) {
|
||||
tm->tm_year += century * 100 - 1900;
|
||||
} else if (tm->tm_year <= 68) {
|
||||
tm->tm_year += 100;
|
||||
}
|
||||
}
|
||||
return (char *)s;
|
||||
fail_nl_langinfo:
|
||||
fprintf(stderr, "strptime: nl_langinfo not available");
|
||||
return NULL;
|
||||
}
|
9
distro/README.md
Normal file
9
distro/README.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
# upstream packaging
|
||||
|
||||
## RPM-based system (Fedora, CentOS, SUSE, ...) quickstart
|
||||
```
|
||||
sudo dnf install -y git rpm-build python3-pip
|
||||
pip3 install apkg
|
||||
apkg build -i
|
||||
```
|
||||
See apkg docs: https://pkg.labs.nic.cz/pages/apkg/
|
10
distro/config/apkg.toml
Normal file
10
distro/config/apkg.toml
Normal file
|
@ -0,0 +1,10 @@
|
|||
[project]
|
||||
name = "libyang"
|
||||
make_archive_script = "distro/scripts/make-archive.sh"
|
||||
|
||||
[upstream]
|
||||
archive_url = "https://github.com/CESNET/libyang/archive/v{{ version }}/libyang-{{ version }}.tar.gz"
|
||||
version_script = "distro/scripts/upstream-version.sh"
|
||||
|
||||
[apkg]
|
||||
compat = 2
|
38
distro/pkg/deb/README.Debian
Normal file
38
distro/pkg/deb/README.Debian
Normal file
|
@ -0,0 +1,38 @@
|
|||
Debian packaging for libyang
|
||||
============================
|
||||
|
||||
Where to file issues
|
||||
--------------------
|
||||
|
||||
Please file issues on the Debian BTS as usual. You could also open issues
|
||||
on github, but if it's something about the Debian packaging it's better to
|
||||
stick with the proper Debian ways. The Debian BTS is where other people
|
||||
involved with Debian go look for bugs regarding a package, so that's where
|
||||
they should be.
|
||||
|
||||
Building straight off git
|
||||
-------------------------
|
||||
|
||||
Just the normal:
|
||||
|
||||
```
|
||||
git clone https://github.com/CESNET/libyang -b debian/master
|
||||
cd libyang
|
||||
dpkg-buildpackage
|
||||
```
|
||||
|
||||
Building a Debian .dsc
|
||||
----------------------
|
||||
|
||||
Again, pretty much the normal:
|
||||
|
||||
```
|
||||
git clone https://github.com/CESNET/libyang -b debian/master
|
||||
wget -Olibyang_0.16.105.orig.tar.gz https://github.com/CESNET/libyang/archive/v0.16-r3.tar.gz
|
||||
cd libyang
|
||||
dpkg-source -b .
|
||||
```
|
||||
|
||||
(Note the diverging release numbering though.)
|
||||
|
||||
-- Ondřej Surý <Ondřej Surý <ondrej@debian.org>>, Fri, 22 May 2020 11:10:55 +0200
|
66
distro/pkg/deb/README.source
Normal file
66
distro/pkg/deb/README.source
Normal file
|
@ -0,0 +1,66 @@
|
|||
This module uses gbp and upstream git repository
|
||||
|
||||
To update this package, first import the changes from upstream:
|
||||
- git fetch --all
|
||||
|
||||
Find the latest version:
|
||||
VERSION=$(git describe --tags $(git rev-list '--tags=v2*' --max-count=1) | sed 's/^v//')
|
||||
echo $VERSION
|
||||
|
||||
Update debian/sid branch
|
||||
- git checkout debian/master
|
||||
- git merge v$VERSION
|
||||
|
||||
Update the debian/copyright file:
|
||||
- cme update dpkg-copyright
|
||||
See also https://github.com/dod38fr/config-model/wiki/Updating-debian-copyright-file-with-cme
|
||||
|
||||
Check patches (and cleanup if necessary):
|
||||
- gbp pq rebase --commit --drop
|
||||
|
||||
Download upstream tarball:
|
||||
- uscan --download --verbose --download-version $VERSION
|
||||
|
||||
Add pristine-tar:
|
||||
- pristine-tar commit ../libyang_$VERSION.orig.tar.gz v$VERSION
|
||||
|
||||
Generate a temporary changelog:
|
||||
- gbp dch --new-version=$VERSION-1 --snapshot --auto --commit debian/
|
||||
|
||||
Test the first build::
|
||||
- gbp buildpackage --git-ignore-new --git-pristine-tar --git-no-purge
|
||||
|
||||
Regenerate the symbol file (See https://qt-kde-team.pages.debian.net/symbolfiles.html)
|
||||
- pkgkde-symbolshelper batchpatch -v $VERSION < <path_to>/buildlog
|
||||
|
||||
See https://www.debian.org/doc/manuals/maint-guide/advanced.en.html#librarysymbols
|
||||
and dpkg-gensymbols man page
|
||||
|
||||
Update the changelog:
|
||||
- gbp dch -Ra -c
|
||||
|
||||
Once everything is fine, build a source package and tag:
|
||||
- gbp buildpackage -S --git-tag
|
||||
|
||||
Push on salsa:
|
||||
- gbp push
|
||||
|
||||
For more details, see
|
||||
https://honk.sigxcpu.org/projects/git-buildpackage/manual-html/gbp.import.upstream-git.html#gbp.import.upstream.git.notarball
|
||||
|
||||
Maintainer Notes (moved from README.md)
|
||||
=======================================
|
||||
|
||||
* the project version number is actually the SO ABI version. The release
|
||||
point numbers (0.16-r3) isn't used for Debian.
|
||||
|
||||
* it's intentional that the SONAME is libyang.so.0.16 and not libyang.so.0.
|
||||
ABI compatibility is indicated by the first two numbers being equal;
|
||||
the third number is incremented for compatible changes. cf.
|
||||
CESNET/libyang#656
|
||||
|
||||
* the watch file doesn't work yet but the libyang people agreed to make
|
||||
future release tags the same as the internal version number. At that point
|
||||
the watch file will work.
|
||||
|
||||
-- Ondřej Surý <Ondřej Surý <ondrej@debian.org>>, Tue, 21 Jul 2020 16:31:52 +0200
|
5
distro/pkg/deb/changelog
Normal file
5
distro/pkg/deb/changelog
Normal file
|
@ -0,0 +1,5 @@
|
|||
libyang3 ({{ version }}-{{ release }}) unstable; urgency=medium
|
||||
|
||||
* upstream packaging
|
||||
|
||||
-- Ondřej Surý <ondrej@debian.org> Tue, 04 May 2021 22:20:03 +0200
|
1
distro/pkg/deb/compat
Normal file
1
distro/pkg/deb/compat
Normal file
|
@ -0,0 +1 @@
|
|||
10
|
73
distro/pkg/deb/control
Normal file
73
distro/pkg/deb/control
Normal file
|
@ -0,0 +1,73 @@
|
|||
Source: libyang3
|
||||
Section: libs
|
||||
Homepage: https://github.com/CESNET/libyang/
|
||||
Maintainer: Ondřej Surý <ondrej@debian.org>
|
||||
Priority: optional
|
||||
Standards-Version: 4.5.0
|
||||
Build-Depends: cmake,
|
||||
debhelper (>= 10),
|
||||
libcmocka-dev <!nocheck>,
|
||||
libpcre2-dev,
|
||||
pkg-config
|
||||
Vcs-Browser: https://github.com/CESNET/libyang/tree/master
|
||||
Vcs-Git: https://github.com/CESNET/libyang.git
|
||||
|
||||
Package: libyang3
|
||||
Depends: ${misc:Depends},
|
||||
${shlibs:Depends}
|
||||
Architecture: any
|
||||
Multi-Arch: same
|
||||
Description: parser toolkit for IETF YANG data modeling - runtime
|
||||
Libyang implements functions to process schemas expressed in the
|
||||
YANG data modeling language defined by the IETF in RFCs 6020/7950.
|
||||
Schemas expressed in this language primarily describe configuration
|
||||
used by larger network equipment like routers and switches.
|
||||
.
|
||||
In addition to handling the schemas itself, the library also provides
|
||||
functions to process data described by the schemas.
|
||||
.
|
||||
The library is implemented in C and provides an API for other software
|
||||
to use in processing configurations.
|
||||
|
||||
Package: libyang-dev
|
||||
Depends: libpcre2-dev,
|
||||
libyang3 (= ${binary:Version}),
|
||||
${misc:Depends}
|
||||
Conflicts: libyang2-dev
|
||||
Section: libdevel
|
||||
Architecture: any
|
||||
Multi-Arch: same
|
||||
Description: parser toolkit for IETF YANG data modeling - development files
|
||||
Libyang implements functions to process schemas expressed in the
|
||||
YANG data modeling language defined by the IETF in RFCs 6020/7950.
|
||||
Schemas expressed in this language primarily describe configuration
|
||||
used by larger network equipment like routers and switches.
|
||||
.
|
||||
In addition to handling the schemas itself, the library also provides
|
||||
functions to process data described by the schemas.
|
||||
.
|
||||
This package contains the C headers, a pkgconfig file, and .so entry point
|
||||
for libyang.
|
||||
|
||||
Package: libyang-tools
|
||||
Depends: libyang3 (= ${binary:Version}),
|
||||
${misc:Depends},
|
||||
${shlibs:Depends}
|
||||
Breaks: libyang2-tools (<< ${source:Version})
|
||||
Replaces: libyang2-tools (<< ${source:Version})
|
||||
Section: devel
|
||||
Architecture: any
|
||||
Multi-Arch: foreign
|
||||
Description: parser toolkit for IETF YANG data modeling - executable tools
|
||||
This package provides the "yanglint" and "yangre" tools which can be used
|
||||
during the creation of IETF YANG schemas. The tools are not generally
|
||||
useful for normal operation where libyang primarily processes configuration
|
||||
data, not schemas.
|
||||
|
||||
Package: libyang-modules
|
||||
Section: devel
|
||||
Architecture: all
|
||||
Description: parser toolkit for IETF YANG data modeling - YANG modules
|
||||
This package provides the IETF YANG modules used by libyang. These modules
|
||||
are embedded into libyang so this package is not necessary for libyang
|
||||
operation.
|
79
distro/pkg/deb/copyright
Normal file
79
distro/pkg/deb/copyright
Normal file
|
@ -0,0 +1,79 @@
|
|||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: libyang
|
||||
License: BSD-3-clause
|
||||
|
||||
Files: *
|
||||
Copyright: 2015-2021 by CESNET, z.s.p.o.
|
||||
License: BSD-3-clause
|
||||
|
||||
Files: */iana-*.yin */iana-*.yang */ietf-*.yin */ietf-*.yang */ietf-*.h
|
||||
Copyright: 2011-2018 by the IETF Trust and the persons identified as authors
|
||||
License: IETF-BSD-3-clause
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, is permitted pursuant to, and subject
|
||||
to the license terms contained in, the Simplified BSD
|
||||
License set forth in Section 4.c of the IETF Trust's
|
||||
Legal Provisions Relating to IETF Documents
|
||||
(http://trustee.ietf.org/license-info).
|
||||
.
|
||||
This version of this YANG module is part of RFC 6536; see
|
||||
the RFC itself for full legal notices.
|
||||
|
||||
Files: tools/lint/linenoise/*
|
||||
Copyright:
|
||||
Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
License: BSD-2-clause
|
||||
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 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.
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2018 by David Lamparter
|
||||
2020-2021 Ondřej Surý
|
||||
License: BSD-3-clause
|
||||
|
||||
License: BSD-3-clause
|
||||
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.
|
||||
.
|
||||
* Neither the name of libyang nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
.
|
||||
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 HOLDER 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.
|
4
distro/pkg/deb/gbp.conf
Normal file
4
distro/pkg/deb/gbp.conf
Normal file
|
@ -0,0 +1,4 @@
|
|||
[DEFAULT]
|
||||
pristine-tar = False
|
||||
debian-branch = master
|
||||
upstream-tree = SLOPPY
|
3
distro/pkg/deb/libyang-dev.install
Normal file
3
distro/pkg/deb/libyang-dev.install
Normal file
|
@ -0,0 +1,3 @@
|
|||
usr/include/libyang/*.h
|
||||
usr/lib/*/*.so
|
||||
usr/lib/*/pkgconfig/*.pc
|
1
distro/pkg/deb/libyang-modules.install
Normal file
1
distro/pkg/deb/libyang-modules.install
Normal file
|
@ -0,0 +1 @@
|
|||
usr/share/yang/modules/libyang
|
1
distro/pkg/deb/libyang-tools.examples
Normal file
1
distro/pkg/deb/libyang-tools.examples
Normal file
|
@ -0,0 +1 @@
|
|||
tools/lint/examples/*
|
3
distro/pkg/deb/libyang-tools.install
Normal file
3
distro/pkg/deb/libyang-tools.install
Normal file
|
@ -0,0 +1,3 @@
|
|||
usr/bin/yanglint
|
||||
usr/bin/yangre
|
||||
usr/share/man/man1
|
1
distro/pkg/deb/libyang3.install
Normal file
1
distro/pkg/deb/libyang3.install
Normal file
|
@ -0,0 +1 @@
|
|||
usr/lib/*/*.so.*
|
12
distro/pkg/deb/rules
Executable file
12
distro/pkg/deb/rules
Executable file
|
@ -0,0 +1,12 @@
|
|||
#!/usr/bin/make -f
|
||||
#export DH_VERBOSE=1
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
|
||||
include /usr/share/dpkg/default.mk
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
||||
override_dh_auto_configure:
|
||||
dh_auto_configure -- \
|
||||
-DCMAKE_BUILD_TYPE:String="Release"
|
1
distro/pkg/deb/source/format
Normal file
1
distro/pkg/deb/source/format
Normal file
|
@ -0,0 +1 @@
|
|||
3.0 (quilt)
|
3
distro/pkg/deb/tests/control
Normal file
3
distro/pkg/deb/tests/control
Normal file
|
@ -0,0 +1,3 @@
|
|||
Tests: yanglint
|
||||
Depends: gzip,
|
||||
libyang-tools
|
18
distro/pkg/deb/tests/yanglint
Executable file
18
distro/pkg/deb/tests/yanglint
Executable file
|
@ -0,0 +1,18 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
# Setup the test file
|
||||
trap 'rm -f "${TESTFILE}"; rmdir "${TESTDIR}"' EXIT
|
||||
TESTDIR=$(mktemp -d /tmp/yanglint.XXXXXX)
|
||||
TESTFILE="${TESTDIR}/ietf-interfaces.yang"
|
||||
|
||||
# Unpack or copy the test file
|
||||
if test -f /usr/share/doc/libyang-tools/examples/ietf-interfaces.yang.gz; then
|
||||
gunzip -c < /usr/share/doc/libyang-tools/examples/ietf-interfaces.yang.gz > "${TESTFILE}"
|
||||
else
|
||||
cp /usr/share/doc/libyang-tools/examples/ietf-interfaces.yang "${TESTFILE}"
|
||||
fi
|
||||
|
||||
# Lint the test file
|
||||
yanglint "${TESTFILE}"
|
4
distro/pkg/deb/watch
Normal file
4
distro/pkg/deb/watch
Normal file
|
@ -0,0 +1,4 @@
|
|||
version=4
|
||||
opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%libyang-$1.tar.gz%" \
|
||||
https://github.com/CESNET/libyang/releases \
|
||||
(?:.*?/)?v?(\d[\d.]*)(?:-r\d+)?\.tar\.gz debian uupdate
|
125
distro/pkg/rpm/libyang.spec
Normal file
125
distro/pkg/rpm/libyang.spec
Normal file
|
@ -0,0 +1,125 @@
|
|||
%if 0%{?rhel} == 8
|
||||
%undefine __cmake_in_source_build
|
||||
%endif
|
||||
|
||||
Name: libyang
|
||||
Version: {{ version }}
|
||||
Release: {{ release }}%{?dist}
|
||||
Summary: YANG data modeling language library
|
||||
Url: https://github.com/CESNET/libyang
|
||||
Source: %{url}/archive/v%{version}/%{name}-%{version}.tar.gz
|
||||
License: BSD
|
||||
|
||||
BuildRequires: cmake
|
||||
BuildRequires: doxygen
|
||||
BuildRequires: gcc
|
||||
BuildRequires: cmake(cmocka) >= 1.0.1
|
||||
BuildRequires: make
|
||||
BuildRequires: pkgconfig(libpcre2-8) >= 10.21
|
||||
|
||||
%package modules
|
||||
Summary: YANG modules for libyang
|
||||
|
||||
%package devel
|
||||
Summary: Development files for libyang
|
||||
Requires: %{name}%{?_isa} = %{version}-%{release}
|
||||
Requires: pcre2-devel
|
||||
|
||||
%package devel-doc
|
||||
Summary: Documentation of libyang API
|
||||
Requires: %{name}%{?_isa} = %{version}-%{release}
|
||||
|
||||
%package tools
|
||||
Summary: YANG validator tools
|
||||
Requires: %{name}%{?_isa} = %{version}-%{release}
|
||||
# This was not properly split out before
|
||||
Conflicts: %{name} < 1.0.225-3
|
||||
|
||||
%description modules
|
||||
YANG modules for libyang.
|
||||
|
||||
%description devel
|
||||
Headers of libyang library.
|
||||
|
||||
%description devel-doc
|
||||
Documentation of libyang API.
|
||||
|
||||
%description tools
|
||||
YANG validator tools.
|
||||
|
||||
%description
|
||||
Libyang is YANG data modeling language parser and toolkit
|
||||
written (and providing API) in C.
|
||||
|
||||
%prep
|
||||
%autosetup -p1
|
||||
%if 0%{?rhel} && 0%{?rhel} < 8
|
||||
mkdir build
|
||||
%endif
|
||||
|
||||
%build
|
||||
%if 0%{?rhel} && 0%{?rhel} < 8
|
||||
cd build
|
||||
cmake \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=%{_prefix} \
|
||||
-DCMAKE_BUILD_TYPE:String="Release" \
|
||||
-DCMAKE_C_FLAGS="${RPM_OPT_FLAGS}" \
|
||||
-DCMAKE_CXX_FLAGS="${RPM_OPT_FLAGS}" \
|
||||
..
|
||||
make
|
||||
%else
|
||||
%cmake -DCMAKE_BUILD_TYPE=RELWITHDEBINFO
|
||||
%cmake_build
|
||||
%if "x%{?suse_version}" == "x"
|
||||
cd %{__cmake_builddir}
|
||||
%endif
|
||||
%endif
|
||||
make doc
|
||||
|
||||
%check
|
||||
%if ( 0%{?rhel} == 0 ) || 0%{?rhel} > 7
|
||||
%if "x%{?suse_version}" == "x"
|
||||
cd %{__cmake_builddir}
|
||||
%endif
|
||||
%endif
|
||||
ctest --output-on-failure -V %{?_smp_mflags}
|
||||
|
||||
%install
|
||||
mkdir -m0755 -p %{buildroot}/%{_docdir}/libyang
|
||||
%if 0%{?rhel} && 0%{?rhel} < 8
|
||||
cd build
|
||||
make DESTDIR=%{buildroot} install
|
||||
%else
|
||||
%cmake_install
|
||||
cp -a doc/html %{buildroot}/%{_docdir}/libyang/html
|
||||
%endif
|
||||
|
||||
%files
|
||||
%license LICENSE
|
||||
%{_libdir}/libyang.so.3
|
||||
%{_libdir}/libyang.so.3.*
|
||||
|
||||
%files modules
|
||||
%{_datadir}/yang/modules/libyang/*.yang
|
||||
%dir %{_datadir}/yang/
|
||||
%dir %{_datadir}/yang/modules/
|
||||
%dir %{_datadir}/yang/modules/libyang/
|
||||
|
||||
%files tools
|
||||
%{_bindir}/yanglint
|
||||
%{_bindir}/yangre
|
||||
%{_datadir}/man/man1/yanglint.1.gz
|
||||
%{_datadir}/man/man1/yangre.1.gz
|
||||
|
||||
%files devel
|
||||
%{_libdir}/libyang.so
|
||||
%{_libdir}/pkgconfig/libyang.pc
|
||||
%{_includedir}/libyang/*.h
|
||||
%dir %{_includedir}/libyang/
|
||||
|
||||
%files devel-doc
|
||||
%{_docdir}/libyang
|
||||
|
||||
%changelog
|
||||
* {{ now }} Jakub Ružička <jakub.ruzicka@nic.cz> - {{ version }}-{{ release }}
|
||||
- upstream package
|
14
distro/scripts/make-archive.sh
Executable file
14
distro/scripts/make-archive.sh
Executable file
|
@ -0,0 +1,14 @@
|
|||
#!/bin/bash
|
||||
# create archive from current source using git
|
||||
|
||||
VERSION=$(git log --oneline -n1 --grep="^VERSION" | rev | cut -d' ' -f1 | rev)
|
||||
|
||||
NAMEVER=libyang-$VERSION
|
||||
ARCHIVE=$NAMEVER.tar.gz
|
||||
|
||||
git archive --format tgz --output $ARCHIVE --prefix $NAMEVER/ HEAD
|
||||
mkdir -p pkg/archives/dev/
|
||||
mv $ARCHIVE pkg/archives/dev/
|
||||
|
||||
# apkg expects stdout to list archive files
|
||||
echo pkg/archives/dev/$ARCHIVE
|
7
distro/scripts/upstream-version.sh
Executable file
7
distro/scripts/upstream-version.sh
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/bin/bash
|
||||
# get latest upstream libyang version from github
|
||||
|
||||
RLS_URL=https://api.github.com/repos/CESNET/libyang/releases
|
||||
VERSION=$(curl -s $RLS_URL | grep tag_name | cut -d '"' -f 4 | sort --version-sort | tail -n 1)
|
||||
VERSION=${VERSION#v}
|
||||
echo $VERSION
|
1
distro/tests/control
Normal file
1
distro/tests/control
Normal file
|
@ -0,0 +1 @@
|
|||
Tests: test-pkg-config.sh test-yanglint.sh
|
5
distro/tests/test-pkg-config.sh
Executable file
5
distro/tests/test-pkg-config.sh
Executable file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
version=`pkg-config --modversion libyang`
|
||||
echo "$version" | grep '2\.[0-9.]\+'
|
5
distro/tests/test-yanglint.sh
Executable file
5
distro/tests/test-yanglint.sh
Executable file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
version=`yanglint --version`
|
||||
echo "$version" | grep '2\.[0-9.]\+'
|
139
doc/build.dox
Normal file
139
doc/build.dox
Normal file
|
@ -0,0 +1,139 @@
|
|||
/**
|
||||
* @page build Building libyang
|
||||
*
|
||||
* [TOC]
|
||||
*
|
||||
* libyang utilizes CMake build system to detect necessary dependencies, checkout the build environment and prepare Makefiles
|
||||
* for the compilation of the library and acompanied tools.
|
||||
*
|
||||
* @section buildRequirements Requirements
|
||||
*
|
||||
* @subsection buildRequirementsCompile Building Requirements
|
||||
*
|
||||
* - C compiler (gcc, clang, ...)
|
||||
* - CMake >= 2.8.12
|
||||
* - libpcre2 (including headers - devel package) >= 10.30
|
||||
*
|
||||
* @subsubsection buildRequirementsCompileOptional Optional Requirements
|
||||
*
|
||||
* - doxygen (for generating documentation)
|
||||
* - cmocka >= 1.0.0 (for tests)
|
||||
* - valgrind (for enhanced testing)
|
||||
* - gcov (for code coverage)
|
||||
* - lcov (for code coverage)
|
||||
* - genhtml (for code coverage)
|
||||
*
|
||||
* @subsection buildRequirementsRun Runtime Requirements
|
||||
*
|
||||
* - libpcre2 (runtime package) >= 10.30
|
||||
*
|
||||
* @section buildCommands Building
|
||||
*
|
||||
* To simply build libyang library and the accompanied tools with the default settings, follow these steps (the `#` character
|
||||
* indicates command(s) to run with `root` privileges):
|
||||
*
|
||||
* $ mkdir build; cd build
|
||||
* $ cmake ..
|
||||
* $ make
|
||||
* # make install
|
||||
*
|
||||
* The default settings can be changed with various CMake variables set via command line or using e.g. `ccmake(1)` tool.
|
||||
* The following sections introduces those variables and explain their meaning.
|
||||
*
|
||||
* @section buildTypes Build Types
|
||||
*
|
||||
* There are several build types according to the primary goal of using the built binaries.
|
||||
*
|
||||
* @subsection buildTypesRelese Release
|
||||
*
|
||||
* Build type to produce final binaries for production use without any debug option. The compiler flags are set as follows:
|
||||
*
|
||||
* -Wall -Wextra -Wno-missing-field-initializers -std=c99 -O3 -DNDEBUG
|
||||
*
|
||||
* Here is the list of the selected additional options available in the *Release* build type.
|
||||
*
|
||||
* Option | Description | Default
|
||||
* ----------------------|------------------------------------------------------------------------------------|--------
|
||||
* ENABLE_BUILD_TESTS | Build tests. | OFF
|
||||
* ENABLE_VALGRIND_TESTS | Build tests with valgrind. | OFF
|
||||
* ENABLE_COVERAGE | Build code coverage report from tests. | OFF
|
||||
* ENABLE_FUZZ_TARGETS | Build target programs suitable for fuzzing with AFL. | OFF
|
||||
* BUILD_SHARED_LIBS | Build shared (.so) instead of static (.a) library | ON
|
||||
* INTERNAL_DOCS | Include developers notes and internal API description into generated Documentation | OFF
|
||||
*
|
||||
* Here is the list of available important targets for the `make(1)` tool:
|
||||
*
|
||||
* Target | Description
|
||||
* -------|------------------------------------------------------------------------------------------------------------
|
||||
* all | Default target, builds libyang library (.so), `yanglint(1)` and `yangre(1)`.
|
||||
* clean | Removes files generated by the make process.
|
||||
* cclean | Extends the `clean` target by removing all the cmake generated files.
|
||||
* doc | Generate HTML documentation. Requires `doxygen(1)`.
|
||||
*
|
||||
* @subsection buildTypesDebug Debug
|
||||
*
|
||||
* `Debug` is the default build type, the produced binaries include additional debug information and the prepared tests are
|
||||
* also built. The compiler flags are set as follows:
|
||||
*
|
||||
* -Wall -Wextra -Wno-missing-field-initializers -std=c99 -g3 -O0
|
||||
*
|
||||
* Here is the list of the selected additional options available in the *Debug* build type.
|
||||
*
|
||||
* Option | Description | Default
|
||||
* ----------------------|------------------------------------------------------------------------------------|--------
|
||||
* ENABLE_BUILD_TESTS | Build tests. | ON
|
||||
* ENABLE_VALGRIND_TESTS | Build tests with valgrind. | ON
|
||||
* ENABLE_COVERAGE | Build code coverage report from tests. | OFF
|
||||
* ENABLE_FUZZ_TARGETS | Build target programs suitable for fuzzing with AFL. | OFF
|
||||
* BUILD_SHARED_LIBS | Build shared (.so) instead of static (.a) library | ON
|
||||
* INTERNAL_DOCS | Include developers notes and internal API description into generated Documentation | OFF
|
||||
*
|
||||
* Here is the list of available important targets for the `make(1)` tool:
|
||||
*
|
||||
* Target | Description
|
||||
* -------------|------------------------------------------------------------------------------------------------------
|
||||
* all | Default target, builds libyang library (.so), `yanglint(1)` and `yangre(1)`.
|
||||
* clean | Removes files generated by the make process.
|
||||
* cclean | Extends the `clean` target by removing all the cmake generated files.
|
||||
* doc | Generate HTML documentation. Requires `doxygen(1)`.
|
||||
* test | Run implementation tests. Requires `cmocka` (and `valgrind(1)` for part of the tests).
|
||||
* format | Reformat source codes using `uncrustify(1)`.
|
||||
* format-check | Dry-run of the `format` target.
|
||||
*
|
||||
* @subsection buildTypesABICheck ABICheck
|
||||
*
|
||||
* Special build type to perform check of the ABI/API compatibility and generate reports. In addition to the basic
|
||||
* requirements, the build type requires some of the <a href="https://abi-laboratory.pro/">ABI Laboratory tools</a>:
|
||||
* `abi-dumper(1)` and `abi-compliance-checker(1)`.
|
||||
*
|
||||
* The compiler flags are set as follows:
|
||||
*
|
||||
* -Wall -Wextra -Wno-missing-field-initializers -std=c99 -g -Og
|
||||
*
|
||||
* All the additional options are switched OFF and the settings should not be changed.
|
||||
*
|
||||
* Here is the list of available important targets for the `make(1)` tool:
|
||||
*
|
||||
* Target | Description
|
||||
* -------------|------------------------------------------------------------------------------------------------------
|
||||
* all | Default target, builds libyang library (.so), `yanglint(1)` and `yangre(1)`.
|
||||
* clean | Removes files generated by the make process.
|
||||
* cclean | Extends the `clean` target by removing all the cmake generated files.
|
||||
* doc | Generate HTML documentation. Requires `doxygen(1)`.
|
||||
* abi-check | Check the backward compatibility of the API/ABI changes. Requires `abi-compliance-checker(1)` and `abi-dump(1)`.
|
||||
* abi-dump | Helper target for `abi-check` generating API/ABI reports. Requires `abi-dump(1)`.
|
||||
|
||||
* @subsection buildTypesDocOnly DocOnly
|
||||
*
|
||||
* Special build type to avoid any requirements except those for building documentation. There are no compiler flags set
|
||||
* since the build type does not allow building any binary output. The settings of the additional options should not be
|
||||
* changed.
|
||||
*
|
||||
* Here is the list of available important targets for the `make(1)` tool:
|
||||
*
|
||||
* Target | Description
|
||||
* -------------|------------------------------------------------------------------------------------------------------
|
||||
* all | Default target, does nothing.
|
||||
* doc | Generate HTML documentation. Requires `doxygen(1)`.
|
||||
*
|
||||
*/
|
106
doc/cesnet-style.css
Normal file
106
doc/cesnet-style.css
Normal file
|
@ -0,0 +1,106 @@
|
|||
/* CESNET blue: #0068a2 */
|
||||
|
||||
body {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
div.header {
|
||||
background-image: none;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
div.contents {
|
||||
background-color: #fff;
|
||||
padding: 1.618em 3.236em;
|
||||
max-width: 60em;
|
||||
margin: auto;
|
||||
margin-left: 0;
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
.sm-dox {
|
||||
background-image: none;
|
||||
background-color: #0068a2;
|
||||
border-bottom: 1px solid white;
|
||||
}
|
||||
|
||||
.sm-dox a {
|
||||
background-image: none;
|
||||
border-right: 1px solid white;
|
||||
color: white;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.sm-dox a:hover {
|
||||
background-image: none;
|
||||
background-color: rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.sm-dox ul a:hover {
|
||||
background-image: none;
|
||||
background-color: #ddd;
|
||||
text-shadow: none;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.navpath ul {
|
||||
background-image: none;
|
||||
background-color: #0068a2;
|
||||
}
|
||||
|
||||
.navpath li.footer {
|
||||
color: white;
|
||||
}
|
||||
img.footer {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.navpath li.navelem a {
|
||||
color: white;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
#side-nav {
|
||||
background-color: #343131;
|
||||
}
|
||||
|
||||
#nav-tree::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
}
|
||||
|
||||
#nav-tree::-webkit-scrollbar-track {
|
||||
background: #333;
|
||||
border-radius: 50px;
|
||||
}
|
||||
|
||||
#nav-tree::-webkit-scrollbar-thumb {
|
||||
background: #ccc;
|
||||
border-radius: 50px;
|
||||
}
|
||||
|
||||
#nav-tree {
|
||||
background: none;
|
||||
}
|
||||
|
||||
#nav-tree .item {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
#nav-tree .item:hover {
|
||||
background-color: rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
#nav-tree a {
|
||||
color: #fff;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
#nav-tree .selected {
|
||||
background-image: none;
|
||||
background-color: #0068a2;
|
||||
}
|
||||
|
||||
#nav-tree-contents {
|
||||
margin: 0;
|
||||
}
|
406
doc/transition_1_2.dox
Normal file
406
doc/transition_1_2.dox
Normal file
|
@ -0,0 +1,406 @@
|
|||
/**
|
||||
* @page transition1_2 Transition Manual (1.x -> 2.0)
|
||||
*
|
||||
* [TOC]
|
||||
*
|
||||
* Rewriting libyang codebase and creating libyang version 2.0 was motivated mainly by improving long term maintainability.
|
||||
* Especially some of the features and design decisions become killers for further development and maintaining the libyang
|
||||
* codebase. On the other hand, most of the principles introduced in libyang 1.x to handle YANG schemas and manipulate
|
||||
* instantiated data have proved successful. Therefore, we have decided to keep the basic mechanisms from version 1.x and
|
||||
* remove the problematic features and modify the improper design decisions. Despite the vision to keep with the mechanisms
|
||||
* also the API, the new version became a great opportunity to clean up the API and improve its usability mainly by unifying
|
||||
* how the libyang functions are used. So, in the end, this manual is not just a description of the removed features listing
|
||||
* removed, modified or added functions. The API should be even better prepared for adding new features and functions.
|
||||
* Shortly, almost everything has changed at least a little, so you cannot move from version 1.x to 2.0 just by replacing
|
||||
* code snippets. However, we believe that the change is good and libyang 2.0 is simply better.
|
||||
*
|
||||
* In this Manual, we want to introduce the differences between libyang 1.x and 2.0. It is intended for the transition
|
||||
* from 1.x to 2.0, so if you are new to libyang, simply go to the @ref howto section, this Manual is not for you.
|
||||
*
|
||||
* The complete generated list of changes (without any additional notes) can be found in
|
||||
* <a href="../compat_report_1_2.html">the compatibility report</a>.
|
||||
*
|
||||
* @section transition1_2General General Changes
|
||||
*
|
||||
*
|
||||
* @subsection transition1_2GeneralErros Errors Handling
|
||||
*
|
||||
* The most visible change is probably the changed approach to handling errors. While libyang 1.x was using variable
|
||||
* *ly_errno* to provide error information in case the called function failed, there is no such variable in libyang 2.0.
|
||||
* On the other hand, most API functions now return ::LY_ERR values directly stating the result. In addition, in case
|
||||
* the error is somehow connected with the [context](@ref howtoContext), more detailed error information can be obtained
|
||||
* from the context handler itself. Mainly this change is responsible for the backward incompatibility of almost all
|
||||
* functions between versions 1.x and 2.0.
|
||||
*
|
||||
* Here is the overview of the changed / removed / added functions connected with errors and logging.
|
||||
*
|
||||
* libyang 1.x | libyang 2.0 | Notes
|
||||
* :-------------------------|:-------------------------------------|:-------------------------------------------------------
|
||||
* - | ::ly_err_last() | New API for handling errors.
|
||||
* ly_verb_dbg() | ::ly_log_dbg_groups() | Rename to align with the names of the accepted values.
|
||||
* ly_verb() | ::ly_log_level() | ^
|
||||
*
|
||||
* More information about error handling in libyang 2.0 can be found at @ref howtoErrors page.
|
||||
*
|
||||
* @subsection transition1_2GeneralInOut Input / Output Processing
|
||||
*
|
||||
* libyang 2.0 introduces input (::ly_in) and output (::ly_out) handlers covering the specific input sources for parsers and
|
||||
* output targets for printers. They are supposed mainly to simplify parser's and printer's API to avoid the need for
|
||||
* separate functions for each source/target. The handlers can be used repeatedly to split the inputs or join the outputs.
|
||||
*
|
||||
* More information can be found at @ref howtoInput and @ref howtoOutput pages.
|
||||
*
|
||||
*
|
||||
* @subsection transition1_2GeneralOutputFormatting Output Formatting
|
||||
*
|
||||
* In libyang 1.x, there was an inconsistency in printing schemas and data. While the schemas were always printed formatted,
|
||||
* the data were printed by default without additional indentation. It is clearly visible in the YIN format of the schema,
|
||||
* which is XML, and the XML encoding of the data. While there was a possibility to format data output with the LYP_FORMAT
|
||||
* flag, it wasn't possible to change schema output formatting.
|
||||
*
|
||||
* libyang 2.0 unifies the behavior of all printers. By default, all the output formats are formatted now. Both, the data as
|
||||
* well as the schema printers, accept the option to remove additional formatting (different for the specific format, usually
|
||||
* indentations and blank lines): ::LYD_PRINT_SHRINK for the data printer and ::LYS_PRINT_SHRINK for the schema printer.
|
||||
*
|
||||
*
|
||||
* @subsection transition1_2GeneralXPath Addressing
|
||||
*
|
||||
* If you compare the @ref howtoXPath page from libyang 1.x and 2.0 documentation, you will be probably confused since they
|
||||
* seem very different. In fact, we have tried to simplify the API by removing the original Schema path format from the
|
||||
* public API. Since this format is used in YANG format, libyang still supports it internally, but it is not possible to use
|
||||
* it anywhere in the API. The new formats XPath and Path, mentioned at the @ref howtoXPath page, are both the Data paths
|
||||
* used in libyang 1.x. The Path format is a subset of XPath format limited to refer to a single node.
|
||||
*
|
||||
* This change was reflected in functions serving to get a node based on the specified path. Unfortunately, when comparing
|
||||
* old and new API, the transition can be confusing since the names are sometimes overloaded (be careful mainly of
|
||||
* ::lys_find_path()). The following table depicts the changes, but probably a better approach is to handle the functions as
|
||||
* a completely new API.
|
||||
*
|
||||
* libyang 1.x | libyang 2.0 | Notes
|
||||
* :-------------------------|:-------------------------------------|:-------------------------------------------------------
|
||||
* ly_ctx_find_path() | - | To simplify the different [types of paths](@ref howtoXPath), the Schema path format is not supported for now. If there will be use cases for it, it can be re-added later, but for now try using ::lys_find_xpath().
|
||||
* %lys_find_path() | - | To simplify the different [types of paths](@ref howtoXPath), the Schema path format is not supported for now. If there will be use cases for it, it can be re-added later, but for now try using ::lys_find_xpath().
|
||||
* ly_ctx_get_node() | ::lys_find_path() | Renamed to unify API functions, note that there was lys_find_path in libyang 1.x with different functionality in comparison to the function of the same name from libyang 2.0.
|
||||
* - | ::lys_find_path_atoms() | Extension of ::lys_find_path().
|
||||
* - | ::lys_find_lypath_atoms() | ^
|
||||
* - | ::lys_find_xpath() | New function reflecting updated @ref howtoXPath\.
|
||||
* lys_xpath_atomize() | ::lys_find_xpath_atoms() | Rename to unify with the new API, extends ::lys_find_xpath().
|
||||
* - | ::lys_find_expr_atoms() | Extension of ::lys_find_xpath().
|
||||
* %lyd_path() | ::lyd_path() | Same purpose, just extended functionality.
|
||||
* lyd_find_path() | ::lyd_find_xpath() | Rename to unify with the new API.
|
||||
* - | ::lyd_find_path() | Simplified version of ::lyd_find_path().
|
||||
* - | ::lyxp_get_expr() | Added functionality due to the changed representation of XPath expressions.
|
||||
* ly_path_data2schema() | - | Removed since the schema path is not available in API.
|
||||
* ly_path_xml2json() | - | Removed since done internally, note that even the generic XML parser is not available now.
|
||||
* lys_node_xpath_atomize() | - | Removed as useless/redundant, use ::lys_find_xpath_atoms().
|
||||
*
|
||||
* @section transition1_2Context Context
|
||||
*
|
||||
* Context, as a concept of a storage interconnecting YANG modules into a YANG schema and YANG schema with the instantiated
|
||||
* data, was preserved. However, it is now more supposed to be prepared just once before connecting it with any instantiated
|
||||
* data. The possibility of removing YANG modules from the context was completely dropped. Furthermore, we would like to
|
||||
* introduce some kind of context lock to completely abandon any change of the YANG modules after starting work with the
|
||||
* instantiated data.
|
||||
*
|
||||
* Another change to note is the removed destructor of private data (::lysc_node.priv) in ::ly_ctx_destroy(). The mechanism
|
||||
* was not reliable with the context recompilation and the splitted parsed and compiled schema trees or the complexity of
|
||||
* YANG extensions. It is better to let the caller maintain the allocated data directly via some memory pool or using
|
||||
* ::lysc_tree_dfs_full() since he is the best to know where the additional data were added.
|
||||
*
|
||||
* The meaining of the ::lysc_node.priv pointer can be now also changed by ::LY_CTX_SET_PRIV_PARSED context option, which
|
||||
* makes libyang to connect the original parsed schema node structure (::lysp_node) into the compiled nodes via their 'priv'
|
||||
* pointer.
|
||||
*
|
||||
* Other significant changes connected with the context are depicted in the following table.
|
||||
*
|
||||
* libyang 1.x | libyang 2.0 | Notes
|
||||
* :-------------------------|:-------------------------------------|:-------------------------------------------------------
|
||||
* ly_ctx_clean() | - | Removed functionality of manipulating with the context and the modules already placed in the context.
|
||||
* ly_ctx_remove_module() | - | ^
|
||||
* ly_ctx_set_module_data_clb() and the associated ly_module_data_clb type. | - | ^
|
||||
* ly_ctx_get_disabled_module() and the associated ly_ctx_get_disabled_module_iter() | - | ^
|
||||
* ly_ctx_info() | ::ly_ctx_get_yanglib_data() | Clarification of what to expect as the output of the function and possibility to specify custom content ID.
|
||||
* ly_ctx_get_module_set_id() | ::ly_ctx_get_change_count() | The functionality is the same but the exact meaning of the value was clarified.
|
||||
* - | ::ly_ctx_unset_searchdir_last() | Extend the functionality of the ::ly_ctx_unset_searchdir() to make its use easier.
|
||||
* ly_ctx_get_module_older() | - | Removed functionality.
|
||||
* - | ::ly_ctx_get_module_implemented() | Supplement for ::ly_ctx_get_module()
|
||||
* - | ::ly_ctx_get_module_latest() | ^
|
||||
* - | ::ly_ctx_get_module_implemented_ns() | Supplement for ::ly_ctx_get_module_ns()
|
||||
* - | ::ly_ctx_get_module_latest_ns() | ^
|
||||
* - | ::ly_ctx_get_submodule_latest() | Supplement for ::ly_ctx_get_submodule()
|
||||
* - | ::ly_ctx_get_submodule2_latest() | Supplement for ::ly_ctx_get_submodule2()
|
||||
* ly_ctx_get_module_by_ns() | ::ly_ctx_get_module_ns () | Redesign the API - replace some of the parameters with standalone supplement functions.
|
||||
* ly_ctx_unset_searchdirs() | ::ly_ctx_unset_searchdir() | Simplify API and instead of index numbers, work with the values themselves.
|
||||
* ly_ctx_set*() | ::ly_ctx_set_options() | API simplification.
|
||||
* ly_ctx_unset*() | ::ly_ctx_unset_options() | ^
|
||||
* ly_ctx_destroy() | ::ly_ctx_destroy() | The destructor callback parameter was removed, see the notes above.
|
||||
*
|
||||
*
|
||||
* @section transition1_2Schemas YANG Modules (Schema)
|
||||
*
|
||||
* The most significant change between libyang 1.x and 2.0 can be found in schema structures. The schema tree now has two
|
||||
* different forms - parsed and compiled trees. While the parsed tree reflects the source of the YANG module, the compiled
|
||||
* tree represents the final tree used to validate the instantiated data. Both formats can be found inside the covering
|
||||
* ::lys_module structure. More about the new structures can be found at @ref howtoSchema page.
|
||||
*
|
||||
* This is an essential change allowing speed up and simplification of data validation, but requiring carefully determine
|
||||
* which format is more suitable for the specific use case. As mentioned, the compiled trees are better for data validation
|
||||
* and getting information about the intentioned structure of the schema with all the applied groupings, type modifications,
|
||||
* augments, deviations, and any defined if-features. On the other hand, the parsed trees are useful for the schema format conversions since they
|
||||
* provide the original structure of the modules. There is a number of new functions intended to work only with the
|
||||
* parsed or the compiled tree. These functions are prefixed with `lysp_` and `lysp_` prefixes.
|
||||
*
|
||||
* Schema parser, as well as printer functions, are now extended to accept new
|
||||
* [input / output handlers](@ref transition1_2GeneralInOut). The previous API working directly with inputs and outputs is
|
||||
* preserved (or slightly changed), but the functions can be limited in the functionality of the new API. More information
|
||||
* can be found at @ref howtoSchemaParsers and @ref howtoSchemaPrinters pages.
|
||||
*
|
||||
* libyang 1.x | libyang 2.0 | Notes
|
||||
* :----------------------------|:--------------------------------|:---------------------------------------------------------
|
||||
* - | ::lys_parse() | New generic schema parser API using [generic input handler](@ref howtoInput).
|
||||
* - | ::lys_print_module() | New generic schema printer API using [generic output handler](@ref howtoOutput).
|
||||
* - | ::lys_print_node() | ^
|
||||
* - | ::lys_print_submodule() | ^
|
||||
*
|
||||
*
|
||||
* The following table introduces other significant changes in the API functions connected with the schema.
|
||||
*
|
||||
* libyang 1.x | libyang 2.0 | Notes
|
||||
* :----------------------------|:--------------------------------|:---------------------------------------------------------
|
||||
* lys_set_private() | - | Not needed, all ::lysc_node compatible structures have this pointer so it can be accessed directly.
|
||||
* lys_is_disabled() | - | Make no sense since the nodes disabled by if-feature are not present in the compiled tree.
|
||||
* lys_features_list() | - | Not needed, the list of features is available in the parsed tree of the module and submodule.
|
||||
* lys_features_enable(), lys_features_enable_force() | ::lys_set_implemented() | Set of enabled features can be changed but it causes the whole context (all the modules) to recompile.
|
||||
* lys_features_disable(), lys_features_disable_force() | - | ^
|
||||
* lys_features_state() | - | Redesign of the features handling in the schema tree, the feature's status is newly directly visible as ::LYS_FENABLED flag (in parsed feature structure).
|
||||
* - | ::lys_feature_value() | Simplified API to get feature's state only based on a feature name string.
|
||||
* - | ::lysp_feature_next() | After redesigning features handling, this function helps to iterate over all features connected with the module.
|
||||
* lys_iffeature_value() | ::lysc_iffeature_value() | Renamed, but note that after features handling redesign, the compiled if-feature structure to evaluate is only in ::lysp_feature.iffeatures_c.
|
||||
* lys_iffeature_value() | - | Not needed since the if-feature statements are directly applied onto the compiled tree.
|
||||
* lys_is_disabled() | - | ^
|
||||
* lys_parent() | - | The compiled tree is more straightforward without the need to take care of nodes added via augments.
|
||||
* lys_main_module() | - | The compiled tree does not include submodules, so there is always only the main module.
|
||||
* lys_node_module() | - | ^
|
||||
* lys_set_enabled() | - | It is not possible to change context this way (remove or disable modules).
|
||||
* lys_set_disabled() | - | ^
|
||||
* - | ::lys_find_child() | Helpers wrapper around ::lys_getnext().
|
||||
* - | ::lys_getnext_ext() | Alternative to ::lys_getnext() allowing processing schema trees inside extension instances.
|
||||
* - | ::lys_nodetype2str() | New functionality.
|
||||
* lys_is_key() | ::lysc_is_key() | Renamed to connect with the compiled schema tree.
|
||||
* - | ::lysc_is_userordered() | Added functionality to simplify the examination of generic compiled schema nodes.
|
||||
* - | ::lysc_is_np_cont() | ^
|
||||
* - | ::lysc_node_child() | ^
|
||||
* - | ::lysc_node_actions() | ^
|
||||
* - | ::lysc_node_notifs() | ^
|
||||
* - | ::lysp_node_child() | Added functionality to simplify the examination of generic parsed schema nodes.
|
||||
* - | ::lysp_node_actions() | ^
|
||||
* - | ::lysp_node_notifs() | ^
|
||||
* - | ::lysp_node_groupings() | ^
|
||||
* - | ::lysp_node_typedefs() | ^
|
||||
* - | ::lysc_tree_dfs_full() | Alternative DFS passing implementation to ::LYSC_TREE_DFS_BEGIN macro.
|
||||
* - | ::lysc_module_dfs_full() | Supplement functionality to ::lysc_tree_dfs_full().
|
||||
* lys_path(), lys_data_path() | ::lysc_path() | Redesigned functionality.
|
||||
* lys_data_path_pattern() | - | Removed as useless
|
||||
* lys_implemented_module() | ::ly_ctx_get_module_implemented() | Removed, the same result can be simply achieved using ::ly_ctx_get_module_implemented().
|
||||
*
|
||||
* There is a set of functions available to implement data type plugins for storing and manipulating data values in a more
|
||||
* natural way to the specific data type. For example, IPv4 address type is defined as a string with a pattern, but it is
|
||||
* more effective and usual to store and handle IPv4 as a 32-bit number.
|
||||
*
|
||||
* libyang 1.x | libyang 2.0 | Notes
|
||||
* :----------------------------|:---------------------------------|:--------------------------------------------------------
|
||||
* lys_getnext_union_type() | - | Removed after the type representation redesign.
|
||||
* - | ::lyplg_type_identity_isderived()| Helper functions for base types.
|
||||
* - | ::lyplg_type_parse_dec64() | ^
|
||||
* - | ::lyplg_type_parse_int() | ^
|
||||
* - | ::lyplg_type_parse_uint() | ^
|
||||
* - | ::lyplg_type_validate_patterns() | ^
|
||||
* - | ::lyplg_type_validate_range() | ^
|
||||
* - | ::lyplg_type_get_prefix() | Helper functions for processing prefixes in data values.
|
||||
* - | ::lyplg_type_prefix_data_new() | ^
|
||||
* - | ::lyplg_type_prefix_data_dup() | ^
|
||||
* - | ::lyplg_type_prefix_data_free() | ^
|
||||
*
|
||||
*
|
||||
* YANG extensions are supported via [extension plugins API](@ref pluginsExtensions) allowing to implement specific extension
|
||||
* and load its support into libyang as a shared module. libyang implements several extensions on its own (see
|
||||
* @ref howtoPluginsExtensions), but even these internal implementations use the same API. The API and [mechanism of loading
|
||||
* external plugins](@ref howtoPlugins) changed a lot in contrast to libyang 1.x. The plugins are now loaded automatically
|
||||
* with creating the first libyang context. The only public function to handle external plugins is ::lyplg_add().
|
||||
*
|
||||
*
|
||||
* libyang 1.x | libyang 2.0 | Notes
|
||||
* :----------------------------|:--------------------------------|:---------------------------------------------------------
|
||||
* lys_ext_complex_get_substmt()| lysc_ext_substmt() | Changed design of the extensions and the way how it's substatements are accessed.
|
||||
* lys_ext_instance_presence() | lysc_ext_substmt() | ^
|
||||
* lys_ext_instance_substmt() | lysc_ext_substmt() | ^
|
||||
* ly_clean_plugins() | - | Manipulating external plugins (from plugins directories) is now automatically connected with creating (first) and destroying (last) libyang contexts.
|
||||
* ly_get_loaded_plugins() | - | ^
|
||||
* ly_load_plugins() | - | ^
|
||||
* ly_register_exts() | ::lyplg_add() | Redesigned to a common function for any plugin type.
|
||||
* ly_register_types() | ::lyplg_add() | ^
|
||||
*
|
||||
*
|
||||
* @section transition1_2Data Data Instances
|
||||
*
|
||||
* Conceptually, the data tree did not change as much as the schema tree. There is still a generic ::lyd_node structure that
|
||||
* maps according to the schema node's nodetype to some of the other lyd_node_* structures. All the data nodes were extended
|
||||
* by hashes to improve performance when searching and processing data trees. The hashes are used for example in the
|
||||
* lyd_find_* functions.
|
||||
*
|
||||
* All the data nodes are also implicitly ordered following the order of the schema nodes. This is the
|
||||
* reason to change the insertion function. Only the user-ordered lists and leaf-lists can be now placed relative to other
|
||||
* instances of the same list/leaf-list. Otherwise, the data instance is always inserted/created at the correct place beside
|
||||
* the right sibling nodes.
|
||||
*
|
||||
* For any functions that are available on inputs of different scale (node, subtree, all siblings, whole data tree),
|
||||
* there are several variants of the specific function with suffix specifying what exactly the processed input will be
|
||||
* (_single, _tree, _siblings, _all). This way the behavior is always clear in the code.
|
||||
*
|
||||
* libyang 1.x | libyang 2.0 | Notes
|
||||
* :----------------------------|:--------------------------------|:---------------------------------------------------------
|
||||
* %lyd_insert_after() | ::lyd_insert_after() | Changed meaning by limiting applicability only to user-ordered list and leaf-list instances.
|
||||
* %lyd_insert_before() | ::lyd_insert_before() | ^
|
||||
* lyd_schema_sort() | - | Not necessary since the nodes are sorted implicitly.
|
||||
*
|
||||
*
|
||||
* Parsing data instances in XML format is newly done directly, without any interstep. Therefore, complete XML API
|
||||
* (lyxml_*() functions) from libyang 1.x was removed.
|
||||
*
|
||||
* Parser's API was simplified to avoid variadic parameters. The functions are newly split to parsed data, notifications,
|
||||
* RPCs and replies to the RPCs. Similarly to the schema parsers, also the new data parser API works with
|
||||
* [input handlers](@ref transition1_2GeneralInOut). The data printer's API was also extended to use new
|
||||
* [output handlers](@ref transition1_2GeneralInOut). However, part of the previous API working directly with inputs
|
||||
* and outputs was preserved. More information about the data parser and printer can be found at
|
||||
* @ref howtoDataParsers and @ref howtoDataPrinters pages.
|
||||
*
|
||||
* libyang 1.x | libyang 2.0 | Notes
|
||||
* :----------------------------|:--------------------------------|:---------------------------------------------------------
|
||||
* - | ::lyd_parse_data() | Redesigned data tree parser.
|
||||
* lyd_parse_xml() | - | XML tree format was removed.
|
||||
* lyd_parse_fd() | ::lyd_parse_data_fd() | Renamed and limited to data trees only.
|
||||
* lyd_parse_mem() | ::lyd_parse_data_mem() | ^
|
||||
* lyd_parse_path() | ::lyd_parse_data_path() | ^
|
||||
* - | ::lyd_parse_ext_data() | Separated function for parsing data trees matching a schema tree of the given extension instance.
|
||||
* - | ::lyd_parse_op() | Separated function for parsing RPCs, actions, replies, and notifications.
|
||||
* - | ::lyd_parse_ext_op() | Separated function for parsing RPCs, actions, replies, and notifications of the given extension instance.
|
||||
* - | ::lyd_print_all() | New API accepting ::ly_out.
|
||||
* - | ::lyd_print_tree() | ^
|
||||
*
|
||||
*
|
||||
* Data validation is still done as part of the parser's process. The standalone functionality is available to check the
|
||||
* result of data manipulation with the values of the terminal nodes or with the structure of the data tree. In contrast to
|
||||
* libyang 1.x, adding the default nodes was made available as a standalone function to simplify the data manipulation
|
||||
* process before the final validation.
|
||||
*
|
||||
* Many validation flags were removed because they became obsolete (LYD_OPT_DESTRUCT, LYD_OPT_WHENAUTODEL,
|
||||
* LYD_OPT_NOEXTDEPS, LYD_OPT_DATA_NO_YANGLIB, LYD_OPT_VAL_DIFF) or we consider them redundant (LYD_OPT_OBSOLETE,
|
||||
* LYD_OPT_NOSIBLINGS, LYD_OPT_DATA_ADD_YANGLIB). As for LYD_OPT_TRUSTED, this option was mostly replaced with
|
||||
* ::LYD_PARSE_ONLY because both skip validation but with the significant difference that LYD_OPT_TRUSTED also sets
|
||||
* the data node flags to be considered validated. The current option ::LYD_PARSE_ONLY does not do this because
|
||||
* there is now much better support for working with non-validated data trees. Also, in case an invalid tree was marked
|
||||
* as validated, it could lead to some undesired behavior, which is now avoided.
|
||||
*
|
||||
* Worth mentioning is a difference in the LYB format, which now also stores its validation flags. So, in case
|
||||
* a validated data tree is stored, it is also loaded as validated.
|
||||
*
|
||||
* libyang 1.x | libyang 2.0 | Notes
|
||||
* :----------------------------|:--------------------------------|:---------------------------------------------------------
|
||||
* lyd_validate() | ::lyd_validate_all(), ::lyd_validate_op() | Redesigned functionality.
|
||||
* lyd_validate_modules() | ::lyd_validate_module() | ^
|
||||
* lyd_validate_value(), lyd_value_type() | ::lyd_value_validate() | Redesigned functionality.
|
||||
* - | ::lyd_new_implicit_all() | New in API to explicitly add default nodes, previously done only as part of the validation process.
|
||||
* - | ::lyd_new_implicit_module() | Supplement functionality to ::lyd_new_implicit_all().
|
||||
* - | ::lyd_new_implicit_tree() | ^
|
||||
*
|
||||
*
|
||||
* The `diff` functionality was completely redesigned. Instead of the array of operations to transform one tree into another,
|
||||
* the difference between two data trees has newly a form of the annotated data tree describing the differences. A number of
|
||||
* functions to use the diff tree was added into API. To simply compare just nodes, there are the `compare` functions.
|
||||
*
|
||||
* libyang 1.x | libyang 2.0 | Notes
|
||||
* :----------------------------|:--------------------------------|:---------------------------------------------------------
|
||||
* lyd_diff() | ::lyd_diff_tree() | Redesigned functionality.
|
||||
* - | ::lyd_diff_siblings() | Supplement functionality to ::lyd_diff_tree().
|
||||
* - | ::lyd_diff_apply_all() | ^
|
||||
* - | ::lyd_diff_apply_module() | ^
|
||||
* - | ::lyd_diff_merge_all() | ^
|
||||
* - | ::lyd_diff_merge_module() | ^
|
||||
* - | ::lyd_diff_merge_tree() | ^
|
||||
* - | ::lyd_diff_reverse_all() | ^
|
||||
* lyd_free_diff() | - | Removed.
|
||||
* lyd_free_val_diff() | - | Removed.
|
||||
* - | ::lyd_compare_single() | Added functionality.
|
||||
* - | ::lyd_compare_meta() | Supplement functionality to ::lyd_compare_single()
|
||||
* - | ::lyd_compare_siblings() | ^
|
||||
*
|
||||
*
|
||||
* For now, the functionality of moving data between two different contexts is not implemented. If you have a real use case
|
||||
* for this functionality, let us know.
|
||||
*
|
||||
* libyang 1.x | libyang 2.0 | Notes
|
||||
* :----------------------------|:--------------------------------|:---------------------------------------------------------
|
||||
* lyd_dup() | ::lyd_dup_single() | Redesigned functionality.
|
||||
* lyd_dup_withsiblings() | ::lyd_dup_siblings() | ^
|
||||
* - | ::lyd_dup_meta_single() | Supplement functionality to ::lyd_dup_single().
|
||||
* lyd_dup_to_ctx() | - | Transferring data from one context to another is not supported.
|
||||
* lyd_merge() | ::lyd_merge_tree() | Renamed.
|
||||
* - | ::lyd_merge_siblings() | Supplement functionality to ::lyd_merge_tree()
|
||||
* lyd_merge_to_ctx() | - | Transferring data from one context to another is not supported.
|
||||
*
|
||||
*
|
||||
* There is a significant change in the value structure in terminal nodes. Thanks to the changes in the schema tree,
|
||||
* it is now much more straightforward to get the type of the value and work with the alternative representation of the value
|
||||
* fitting better to its type. There is also a new API for the type plugins (see @ref howtoPluginsTypes). Even the base YANG
|
||||
* data types are now implemented using this API and can be taken as examples for implementing derived data types.
|
||||
*
|
||||
* libyang 1.x | libyang 2.0 | Notes
|
||||
* :----------------------------|:--------------------------------|:---------------------------------------------------------
|
||||
* lyd_new(), lyd_new_output() | ::lyd_new_inner(), ::lyd_new_list(), ::lyd_new_list2() | Redesigned functionality to better fit new lyd_node structures, creating RPC's output data is now done via a flag parameter of the functions.
|
||||
* lyd_new_leaf(), lyd_new_output_leaf() | ::lyd_new_term() | ^
|
||||
* lyd_new_anydata(), lyd_new_output_anydata() | ::lyd_new_any() | ^
|
||||
* lyd_new_yangdata() | ::lyd_new_ext_inner(), ::lyd_new_ext_list(), ::lyd_new_ext_term(), ::lyd_new_ext_any() | Additional functionality to lyd_new_* functions to cover top-level nodes in extension instances.
|
||||
* lyd_insert_attr() | ::lyd_new_meta() | Unify naming used in other functions with the similar functionality.
|
||||
* - | ::lyd_new_attr() | Added functionality to store the data (temporarily) not connected with schema definitions.
|
||||
* - | ::lyd_new_attr2() | ^
|
||||
* - | ::lyd_new_opaq() | ^
|
||||
* - | ::lyd_new_opaq2() | ^
|
||||
* - | ::lyd_new_path2() | Supplement functionality to ::lyd_new_path().
|
||||
* LYD_PATH_OPT_NOPARENTRET | ::lyd_new_path2() | ::lyd_new_path2() returns both the first parent and the wanted node.
|
||||
* LYD_PATH_OPT_EDIT | ::LYD_NEW_PATH_OPAQ | This functionality was replaced by opaq nodes.
|
||||
* - | ::lyd_new_ext_path() | Supplement functionality to ::lyd_new_path() covering data defined in extension instances.
|
||||
* lyd_insert() | ::lyd_insert_child() | Renamed to better distinguish from ::lyd_insert_sibling().
|
||||
* lyd_change_leaf() | ::lyd_change_term() | Align naming with changed names of data structures.
|
||||
* - | ::lyd_change_meta() | Transferred functionality of ::lyd_change_term() to metadata.
|
||||
* - | ::lyd_any_copy_value() | Added functionality.
|
||||
* lyd_free() | ::lyd_free_tree() | Renamed.
|
||||
* lyd_free_withsiblings() | ::lyd_free_all() | ^
|
||||
* - | ::lyd_free_siblings() | Supplement functionality to ::lyd_free_siblings().
|
||||
* lyd_free_attr() | ::lyd_free_attr_single() | Renamed.
|
||||
* - | ::lyd_free_attr_siblings() | Supplement functionality to ::lyd_free_attr_single().
|
||||
* - | ::lyd_free_meta_single() | Added functionality.
|
||||
* - | ::lyd_free_meta_siblings() | ^
|
||||
* lyd_unlink() | ::lyd_unlink_tree() | Renamed.
|
||||
*
|
||||
*
|
||||
* Here is the table of other changes in data API.
|
||||
*
|
||||
* libyang 1.x | libyang 2.0 | Notes
|
||||
* :----------------------------|:--------------------------------|:---------------------------------------------------------
|
||||
* lyd_find_instance() | - | Removed.
|
||||
* lyd_find_sibling() | - | Removed, functionality can be replaced by ::lyd_find_sibling_val().
|
||||
* lyd_find_sibling_set() | - | ^
|
||||
* - | ::lyd_find_sibling_first() | Alternative function to ::lyd_find_sibling_val().
|
||||
* - | ::lyd_find_meta() | New functionality.
|
||||
* lyd_wd_default() | ::lyd_is_default() | Renamed to unlink from with-default capability.
|
||||
* - | ::lyd_parent() | New wrapper to get generic ::lyd_node pointer of the parent.
|
||||
* - | ::lyd_child(), ::lyd_child_no_keys() | New wrapper to cover all children possibilities hidden behind a generic ::lyd_node structure.
|
||||
* - | ::lyd_owner_module() | Added functionality.
|
||||
* - | ::lyd_value_compare() | Added Functionality.
|
||||
* - | ::lyd_find_target() | Added functionality for the instance-identifier representation.
|
||||
* lyd_node_module() | - | Not necessary since the connection with the compiled modules is much more straightforward.
|
||||
* lyd_leaf_type() | - | Not necessary since the real type information is much more clear from the new ::lyd_value.
|
||||
* lyd_dec64_to_double() | - | Removed as useless.
|
||||
* lyd_node_should_print() | - | ^
|
||||
|
||||
*/
|
74
doc/transition_2_3.dox
Normal file
74
doc/transition_2_3.dox
Normal file
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* @page transition2_3 Transition Manual (2.x -> 3.0)
|
||||
*
|
||||
* [TOC]
|
||||
*
|
||||
* Non-backwards-compatible changes between libyang version 2 and 3 are rather minor and can be summarized as providing
|
||||
* structured error information (instead of a single message), unifying **lyd_new_*()** function options, and some
|
||||
* minor changes such as removing deprecated functions or making a few functions inlined. However, there is another
|
||||
* large change that has not affected the API, specifically configuration system-ordered lists and leaf-lists are now
|
||||
* ordered based on their keys/values, respectively. Except for moderately slower performance and negligible increased
|
||||
* memory requirements, it should not affect existing applications (assuming they do not rely on the previous order of
|
||||
* these instances).
|
||||
*
|
||||
* The complete generated list of changes (without any additional notes) can be found in
|
||||
* <a href="../compat_report_2_3.html">the compatibility report</a>.
|
||||
*
|
||||
* @section transition2_3Logging Logging
|
||||
*
|
||||
* Except for some function adjustments, ::ly_err_item has been changed to provide every piece of error information in a
|
||||
* separate member to allow for easier processing.
|
||||
*
|
||||
* Here is the overview of the changed / removed / added functions connected to logging.
|
||||
*
|
||||
* libyang 2.x | libyang 3.0 | Notes
|
||||
* :-------------------------|:-------------------------------------|:-------------------------------------------------------
|
||||
* ly_last_errmsg() | ::ly_last_logmsg() | Function renamed with the same functionality.
|
||||
* ly_strerrcode() | ::ly_strerr() | Function renamed with the same functionality.
|
||||
* ly_errcode() | - | Now requires ::ly_err_last() call.
|
||||
* ly_errmsg() | - | ^
|
||||
* ly_errpath() | - | ^
|
||||
* ly_vecode() | - | ^
|
||||
*
|
||||
*
|
||||
*
|
||||
* @section transition2_3New Data Creation
|
||||
*
|
||||
* libyang 2.x | libyang 3.0 | Notes
|
||||
* :-------------------------|:-------------------------------------|:-------------------------------------------------------
|
||||
* lyd_find_xpath3() | ::lyd_find_xpath3() | Optional prefix data parameter added.
|
||||
* LYD_NEW_PATH_OUTPUT | ::LYD_NEW_VAL_OUTPUT | Some LYD_NEW_PATH_* options now also used for other lyd_new_* functions.
|
||||
* LYD_NEW_PATH_BIN_VALUE | ::LYD_NEW_VAL_BIN | ^
|
||||
* LYD_NEW_PATH_CANON_VALUE | ::LYD_NEW_VAL_CANON | ^
|
||||
* lyd_new_path() | ::lyd_new_path() | All options now in a single bitmap parameter of @ref newvaloptions.
|
||||
* lyd_new_any() | ::lyd_new_any() | ^
|
||||
* lyd_new_list() | ::lyd_new_list() | ^
|
||||
* lyd_new_list2() | ::lyd_new_list2() | ^
|
||||
* lyd_new_list3() | ::lyd_new_list3() | ^
|
||||
* lyd_new_meta() | ::lyd_new_meta() | ^
|
||||
* lyd_new_meta2() | ::lyd_new_meta2() | ^
|
||||
* lyd_new_term() | ::lyd_new_term() | ^
|
||||
* lyd_new_list3_bin() | ::lyd_new_list3() | Functionality now merged into the single function.
|
||||
* lyd_new_list3_canon() | ^ | ^
|
||||
* lyd_new_list_bin() | ::lyd_new_list() | Functionality now merged into the single function.
|
||||
* lyd_new_list_canon() | ^ | ^
|
||||
* lyd_new_term_canon() | ::lyd_new_term() | Functionality now merged into the single function.
|
||||
*
|
||||
*
|
||||
*
|
||||
* @section transition2_3Minor Other Minor Changes
|
||||
*
|
||||
* Except for the function changes below, ::lysc_type now has a copy of the typedef name, if applicable. There
|
||||
* are use-cases when this information is needed even in the compiled schema tree such as checking the real type of
|
||||
* a union value.
|
||||
*
|
||||
* libyang 2.x | libyang 3.0 | Notes
|
||||
* :-------------------------|:-------------------------------------|:-------------------------------------------------------
|
||||
* lyd_child() | ::lyd_child() | Now an inlined function for better performance.
|
||||
* lyd_get_value() | ::lyd_get_value() | ^
|
||||
* lyd_parent() | ::lyd_parent() | ^
|
||||
* lyd_find_xpath4() | ::lyd_find_xpath3() | Previous lyd_find_xpath3 was removed to reduce symbols.
|
||||
* lyd_target() | - | Deprecated.
|
||||
* ly_ctx_reset_latests() | - | ^
|
||||
*
|
||||
*/
|
11
libyang.pc.in
Normal file
11
libyang.pc.in
Normal file
|
@ -0,0 +1,11 @@
|
|||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
||||
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
|
||||
|
||||
Name: @PROJECT_NAME@
|
||||
Description: @LIBYANG_DESCRIPTION@
|
||||
Version: @LIBYANG_VERSION@
|
||||
Requires.private: libpcre2-8
|
||||
Libs: -L${libdir} -lyang
|
||||
Libs.private: -lpcre2-8
|
||||
Cflags: -I${includedir}
|
226
models/ietf-datastores@2018-02-14.h
Normal file
226
models/ietf-datastores@2018-02-14.h
Normal file
|
@ -0,0 +1,226 @@
|
|||
unsigned char ietf_datastores_2018_02_14_yang[] = {
|
||||
0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x69, 0x65, 0x74, 0x66, 0x2d,
|
||||
0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x7b,
|
||||
0x0a, 0x20, 0x20, 0x79, 0x61, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x20, 0x31, 0x2e, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x22, 0x75, 0x72,
|
||||
0x6e, 0x3a, 0x69, 0x65, 0x74, 0x66, 0x3a, 0x70, 0x61, 0x72, 0x61, 0x6d,
|
||||
0x73, 0x3a, 0x78, 0x6d, 0x6c, 0x3a, 0x6e, 0x73, 0x3a, 0x79, 0x61, 0x6e,
|
||||
0x67, 0x3a, 0x69, 0x65, 0x74, 0x66, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x73,
|
||||
0x74, 0x6f, 0x72, 0x65, 0x73, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x70, 0x72,
|
||||
0x65, 0x66, 0x69, 0x78, 0x20, 0x64, 0x73, 0x3b, 0x0a, 0x0a, 0x20, 0x20,
|
||||
0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x49, 0x45, 0x54, 0x46, 0x20, 0x4e,
|
||||
0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x4d, 0x6f, 0x64, 0x65, 0x6c,
|
||||
0x69, 0x6e, 0x67, 0x20, 0x28, 0x4e, 0x45, 0x54, 0x4d, 0x4f, 0x44, 0x29,
|
||||
0x20, 0x57, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x47, 0x72, 0x6f,
|
||||
0x75, 0x70, 0x22, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74,
|
||||
0x61, 0x63, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x57, 0x47, 0x20,
|
||||
0x57, 0x65, 0x62, 0x3a, 0x20, 0x20, 0x20, 0x3c, 0x68, 0x74, 0x74, 0x70,
|
||||
0x73, 0x3a, 0x2f, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x74, 0x72, 0x61, 0x63,
|
||||
0x6b, 0x65, 0x72, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x6f, 0x72, 0x67,
|
||||
0x2f, 0x77, 0x67, 0x2f, 0x6e, 0x65, 0x74, 0x6d, 0x6f, 0x64, 0x2f, 0x3e,
|
||||
0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x57, 0x47, 0x20, 0x4c, 0x69,
|
||||
0x73, 0x74, 0x3a, 0x20, 0x20, 0x3c, 0x6d, 0x61, 0x69, 0x6c, 0x74, 0x6f,
|
||||
0x3a, 0x6e, 0x65, 0x74, 0x6d, 0x6f, 0x64, 0x40, 0x69, 0x65, 0x74, 0x66,
|
||||
0x2e, 0x6f, 0x72, 0x67, 0x3e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x3a, 0x20, 0x20, 0x20, 0x4d, 0x61,
|
||||
0x72, 0x74, 0x69, 0x6e, 0x20, 0x42, 0x6a, 0x6f, 0x72, 0x6b, 0x6c, 0x75,
|
||||
0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x6d, 0x61, 0x69, 0x6c, 0x74,
|
||||
0x6f, 0x3a, 0x6d, 0x62, 0x6a, 0x40, 0x74, 0x61, 0x69, 0x6c, 0x2d, 0x66,
|
||||
0x2e, 0x63, 0x6f, 0x6d, 0x3e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x3a, 0x20, 0x20, 0x20, 0x4a, 0x75,
|
||||
0x65, 0x72, 0x67, 0x65, 0x6e, 0x20, 0x53, 0x63, 0x68, 0x6f, 0x65, 0x6e,
|
||||
0x77, 0x61, 0x65, 0x6c, 0x64, 0x65, 0x72, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c,
|
||||
0x6d, 0x61, 0x69, 0x6c, 0x74, 0x6f, 0x3a, 0x6a, 0x2e, 0x73, 0x63, 0x68,
|
||||
0x6f, 0x65, 0x6e, 0x77, 0x61, 0x65, 0x6c, 0x64, 0x65, 0x72, 0x40, 0x6a,
|
||||
0x61, 0x63, 0x6f, 0x62, 0x73, 0x2d, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72,
|
||||
0x73, 0x69, 0x74, 0x79, 0x2e, 0x64, 0x65, 0x3e, 0x0a, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x3a, 0x20, 0x20,
|
||||
0x20, 0x50, 0x68, 0x69, 0x6c, 0x20, 0x53, 0x68, 0x61, 0x66, 0x65, 0x72,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x3c, 0x6d, 0x61, 0x69, 0x6c, 0x74, 0x6f, 0x3a,
|
||||
0x70, 0x68, 0x69, 0x6c, 0x40, 0x6a, 0x75, 0x6e, 0x69, 0x70, 0x65, 0x72,
|
||||
0x2e, 0x6e, 0x65, 0x74, 0x3e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x3a, 0x20, 0x20, 0x20, 0x4b, 0x65,
|
||||
0x6e, 0x74, 0x20, 0x57, 0x61, 0x74, 0x73, 0x65, 0x6e, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x3c, 0x6d, 0x61, 0x69, 0x6c, 0x74, 0x6f, 0x3a, 0x6b, 0x77, 0x61,
|
||||
0x74, 0x73, 0x65, 0x6e, 0x40, 0x6a, 0x75, 0x6e, 0x69, 0x70, 0x65, 0x72,
|
||||
0x2e, 0x6e, 0x65, 0x74, 0x3e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x3a, 0x20, 0x20, 0x20, 0x52, 0x6f,
|
||||
0x62, 0x20, 0x57, 0x69, 0x6c, 0x74, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x3c, 0x72, 0x77, 0x69, 0x6c, 0x74, 0x6f, 0x6e, 0x40, 0x63, 0x69, 0x73,
|
||||
0x63, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x3e, 0x22, 0x3b, 0x0a, 0x0a, 0x20,
|
||||
0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x54, 0x68, 0x69, 0x73, 0x20, 0x59,
|
||||
0x41, 0x4e, 0x47, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x64,
|
||||
0x65, 0x66, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x65, 0x74,
|
||||
0x20, 0x6f, 0x66, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69,
|
||||
0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74,
|
||||
0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x2e, 0x0a,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69,
|
||||
0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x31, 0x38,
|
||||
0x20, 0x49, 0x45, 0x54, 0x46, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20,
|
||||
0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, 0x72, 0x73,
|
||||
0x6f, 0x6e, 0x73, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69,
|
||||
0x65, 0x64, 0x20, 0x61, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61,
|
||||
0x75, 0x74, 0x68, 0x6f, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x20, 0x20, 0x41, 0x6c, 0x6c,
|
||||
0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x72, 0x65, 0x73, 0x65,
|
||||
0x72, 0x76, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x52, 0x65, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x73, 0x65, 0x20, 0x69,
|
||||
0x6e, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x61, 0x6e, 0x64,
|
||||
0x20, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x6d,
|
||||
0x73, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x72, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20,
|
||||
0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x2c, 0x20, 0x69, 0x73, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x74,
|
||||
0x65, 0x64, 0x20, 0x70, 0x75, 0x72, 0x73, 0x75, 0x61, 0x6e, 0x74, 0x20,
|
||||
0x74, 0x6f, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x75, 0x62, 0x6a,
|
||||
0x65, 0x63, 0x74, 0x20, 0x74, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20,
|
||||
0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
|
||||
0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20,
|
||||
0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x42,
|
||||
0x53, 0x44, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x73,
|
||||
0x65, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x74,
|
||||
0x68, 0x20, 0x69, 0x6e, 0x20, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x20, 0x34, 0x2e, 0x63, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
|
||||
0x49, 0x45, 0x54, 0x46, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x27, 0x73,
|
||||
0x20, 0x4c, 0x65, 0x67, 0x61, 0x6c, 0x20, 0x50, 0x72, 0x6f, 0x76, 0x69,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52,
|
||||
0x65, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x49,
|
||||
0x45, 0x54, 0x46, 0x20, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74,
|
||||
0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70,
|
||||
0x73, 0x3a, 0x2f, 0x2f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, 0x2e,
|
||||
0x69, 0x65, 0x74, 0x66, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x69, 0x63,
|
||||
0x65, 0x6e, 0x73, 0x65, 0x2d, 0x69, 0x6e, 0x66, 0x6f, 0x29, 0x2e, 0x0a,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x76,
|
||||
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
|
||||
0x69, 0x73, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x6d, 0x6f, 0x64, 0x75,
|
||||
0x6c, 0x65, 0x20, 0x69, 0x73, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f,
|
||||
0x66, 0x20, 0x52, 0x46, 0x43, 0x20, 0x38, 0x33, 0x34, 0x32, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f,
|
||||
0x2f, 0x77, 0x77, 0x77, 0x2e, 0x72, 0x66, 0x63, 0x2d, 0x65, 0x64, 0x69,
|
||||
0x74, 0x6f, 0x72, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x69, 0x6e, 0x66, 0x6f,
|
||||
0x2f, 0x72, 0x66, 0x63, 0x38, 0x33, 0x34, 0x32, 0x29, 0x3b, 0x20, 0x73,
|
||||
0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x52, 0x46, 0x43, 0x20, 0x69,
|
||||
0x74, 0x73, 0x65, 0x6c, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66,
|
||||
0x6f, 0x72, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x6c, 0x65, 0x67, 0x61,
|
||||
0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x22, 0x3b,
|
||||
0x0a, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x20, 0x32, 0x30, 0x31, 0x38, 0x2d, 0x30, 0x32, 0x2d, 0x31, 0x34, 0x20,
|
||||
0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
|
||||
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x22, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x76,
|
||||
0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x52, 0x46, 0x43, 0x20, 0x38, 0x33,
|
||||
0x34, 0x32, 0x3a, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20,
|
||||
0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x44,
|
||||
0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x41, 0x72, 0x63,
|
||||
0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x20, 0x28, 0x4e,
|
||||
0x4d, 0x44, 0x41, 0x29, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a,
|
||||
0x20, 0x20, 0x2f, 0x2a, 0x0a, 0x20, 0x20, 0x20, 0x2a, 0x20, 0x49, 0x64,
|
||||
0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x2a, 0x2f, 0x0a, 0x0a, 0x20, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69,
|
||||
0x74, 0x79, 0x20, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65,
|
||||
0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72,
|
||||
0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x22, 0x41, 0x62, 0x73, 0x74, 0x72, 0x61, 0x63, 0x74, 0x20, 0x62,
|
||||
0x61, 0x73, 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79,
|
||||
0x20, 0x66, 0x6f, 0x72, 0x20, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f,
|
||||
0x72, 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65,
|
||||
0x73, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20,
|
||||
0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x63, 0x6f, 0x6e,
|
||||
0x76, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x7b, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x73, 0x65, 0x20, 0x64, 0x61, 0x74,
|
||||
0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x62, 0x73, 0x74, 0x72,
|
||||
0x61, 0x63, 0x74, 0x20, 0x62, 0x61, 0x73, 0x65, 0x20, 0x69, 0x64, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x6f,
|
||||
0x6e, 0x76, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x63,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x61, 0x74, 0x61,
|
||||
0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74,
|
||||
0x79, 0x20, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x7b, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x73, 0x65, 0x20, 0x63, 0x6f, 0x6e,
|
||||
0x76, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x3b, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x54, 0x68,
|
||||
0x65, 0x20, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
|
||||
0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x22, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x69, 0x64, 0x65, 0x6e,
|
||||
0x74, 0x69, 0x74, 0x79, 0x20, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61,
|
||||
0x74, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x73,
|
||||
0x65, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x61, 0x6c, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63,
|
||||
0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x22, 0x54, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6e, 0x64, 0x69,
|
||||
0x64, 0x61, 0x74, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75,
|
||||
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64, 0x61, 0x74, 0x61, 0x73,
|
||||
0x74, 0x6f, 0x72, 0x65, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a,
|
||||
0x0a, 0x20, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20,
|
||||
0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x20, 0x7b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x62, 0x61, 0x73, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x3b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x54, 0x68, 0x65, 0x20,
|
||||
0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x20, 0x63, 0x6f, 0x6e, 0x66,
|
||||
0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64, 0x61,
|
||||
0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x22, 0x3b, 0x0a, 0x20,
|
||||
0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69,
|
||||
0x74, 0x79, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20,
|
||||
0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x73, 0x65, 0x20, 0x63,
|
||||
0x6f, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
|
||||
0x54, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64,
|
||||
0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x20, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65,
|
||||
0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x69,
|
||||
0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x64, 0x79, 0x6e, 0x61,
|
||||
0x6d, 0x69, 0x63, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61,
|
||||
0x73, 0x65, 0x20, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65,
|
||||
0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
|
||||
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x22, 0x41, 0x62, 0x73, 0x74, 0x72, 0x61, 0x63, 0x74, 0x20, 0x62, 0x61,
|
||||
0x73, 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20,
|
||||
0x66, 0x6f, 0x72, 0x20, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x20,
|
||||
0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x20, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73,
|
||||
0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x69,
|
||||
0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x70, 0x65, 0x72,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x7b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x62, 0x61, 0x73, 0x65, 0x20, 0x64, 0x61, 0x74, 0x61, 0x73,
|
||||
0x74, 0x6f, 0x72, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65,
|
||||
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x22, 0x54, 0x68, 0x65, 0x20, 0x6f, 0x70, 0x65,
|
||||
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x73, 0x74, 0x61,
|
||||
0x74, 0x65, 0x20, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65,
|
||||
0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x2f,
|
||||
0x2a, 0x0a, 0x20, 0x20, 0x20, 0x2a, 0x20, 0x54, 0x79, 0x70, 0x65, 0x20,
|
||||
0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x2a, 0x2f, 0x0a, 0x0a, 0x20, 0x20, 0x74, 0x79, 0x70,
|
||||
0x65, 0x64, 0x65, 0x66, 0x20, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f,
|
||||
0x72, 0x65, 0x2d, 0x72, 0x65, 0x66, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69,
|
||||
0x74, 0x79, 0x72, 0x65, 0x66, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x62, 0x61, 0x73, 0x65, 0x20, 0x64, 0x61, 0x74, 0x61, 0x73,
|
||||
0x74, 0x6f, 0x72, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41,
|
||||
0x20, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x69,
|
||||
0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x72, 0x65, 0x66, 0x65,
|
||||
0x72, 0x65, 0x6e, 0x63, 0x65, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x7d,
|
||||
0x0a, 0x7d, 0x0a, 0x00
|
||||
};
|
117
models/ietf-datastores@2018-02-14.yang
Normal file
117
models/ietf-datastores@2018-02-14.yang
Normal file
|
@ -0,0 +1,117 @@
|
|||
module ietf-datastores {
|
||||
yang-version 1.1;
|
||||
namespace "urn:ietf:params:xml:ns:yang:ietf-datastores";
|
||||
prefix ds;
|
||||
|
||||
organization
|
||||
"IETF Network Modeling (NETMOD) Working Group";
|
||||
|
||||
contact
|
||||
"WG Web: <https://datatracker.ietf.org/wg/netmod/>
|
||||
|
||||
WG List: <mailto:netmod@ietf.org>
|
||||
|
||||
Author: Martin Bjorklund
|
||||
<mailto:mbj@tail-f.com>
|
||||
|
||||
Author: Juergen Schoenwaelder
|
||||
<mailto:j.schoenwaelder@jacobs-university.de>
|
||||
|
||||
Author: Phil Shafer
|
||||
<mailto:phil@juniper.net>
|
||||
|
||||
Author: Kent Watsen
|
||||
<mailto:kwatsen@juniper.net>
|
||||
|
||||
Author: Rob Wilton
|
||||
<rwilton@cisco.com>";
|
||||
|
||||
description
|
||||
"This YANG module defines a set of identities for identifying
|
||||
datastores.
|
||||
|
||||
Copyright (c) 2018 IETF Trust and the persons identified as
|
||||
authors of the code. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, is permitted pursuant to, and subject to
|
||||
the license terms contained in, the Simplified BSD License set
|
||||
forth in Section 4.c of the IETF Trust's Legal Provisions
|
||||
Relating to IETF Documents
|
||||
(https://trustee.ietf.org/license-info).
|
||||
|
||||
This version of this YANG module is part of RFC 8342
|
||||
(https://www.rfc-editor.org/info/rfc8342); see the RFC itself
|
||||
for full legal notices.";
|
||||
|
||||
revision 2018-02-14 {
|
||||
description
|
||||
"Initial revision.";
|
||||
reference
|
||||
"RFC 8342: Network Management Datastore Architecture (NMDA)";
|
||||
}
|
||||
|
||||
/*
|
||||
* Identities
|
||||
*/
|
||||
|
||||
identity datastore {
|
||||
description
|
||||
"Abstract base identity for datastore identities.";
|
||||
}
|
||||
|
||||
identity conventional {
|
||||
base datastore;
|
||||
description
|
||||
"Abstract base identity for conventional configuration
|
||||
datastores.";
|
||||
}
|
||||
|
||||
identity running {
|
||||
base conventional;
|
||||
description
|
||||
"The running configuration datastore.";
|
||||
}
|
||||
|
||||
identity candidate {
|
||||
base conventional;
|
||||
description
|
||||
"The candidate configuration datastore.";
|
||||
}
|
||||
|
||||
identity startup {
|
||||
base conventional;
|
||||
description
|
||||
"The startup configuration datastore.";
|
||||
}
|
||||
|
||||
identity intended {
|
||||
base conventional;
|
||||
description
|
||||
"The intended configuration datastore.";
|
||||
}
|
||||
|
||||
identity dynamic {
|
||||
base datastore;
|
||||
description
|
||||
"Abstract base identity for dynamic configuration datastores.";
|
||||
}
|
||||
|
||||
identity operational {
|
||||
base datastore;
|
||||
description
|
||||
"The operational state datastore.";
|
||||
}
|
||||
|
||||
/*
|
||||
* Type definitions
|
||||
*/
|
||||
|
||||
typedef datastore-ref {
|
||||
type identityref {
|
||||
base datastore;
|
||||
}
|
||||
description
|
||||
"A datastore identity reference.";
|
||||
}
|
||||
}
|
1189
models/ietf-inet-types@2013-07-15.h
Normal file
1189
models/ietf-inet-types@2013-07-15.h
Normal file
File diff suppressed because it is too large
Load diff
457
models/ietf-inet-types@2013-07-15.yang
Normal file
457
models/ietf-inet-types@2013-07-15.yang
Normal file
|
@ -0,0 +1,457 @@
|
|||
module ietf-inet-types {
|
||||
|
||||
namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types";
|
||||
prefix "inet";
|
||||
|
||||
organization
|
||||
"IETF NETMOD (NETCONF Data Modeling Language) Working Group";
|
||||
|
||||
contact
|
||||
"WG Web: <http://tools.ietf.org/wg/netmod/>
|
||||
WG List: <mailto:netmod@ietf.org>
|
||||
|
||||
WG Chair: David Kessens
|
||||
<mailto:david.kessens@nsn.com>
|
||||
|
||||
WG Chair: Juergen Schoenwaelder
|
||||
<mailto:j.schoenwaelder@jacobs-university.de>
|
||||
|
||||
Editor: Juergen Schoenwaelder
|
||||
<mailto:j.schoenwaelder@jacobs-university.de>";
|
||||
|
||||
description
|
||||
"This module contains a collection of generally useful derived
|
||||
YANG data types for Internet addresses and related things.
|
||||
|
||||
Copyright (c) 2013 IETF Trust and the persons identified as
|
||||
authors of the code. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, is permitted pursuant to, and subject
|
||||
to the license terms contained in, the Simplified BSD License
|
||||
set forth in Section 4.c of the IETF Trust's Legal Provisions
|
||||
Relating to IETF Documents
|
||||
(http://trustee.ietf.org/license-info).
|
||||
|
||||
This version of this YANG module is part of RFC 6991; see
|
||||
the RFC itself for full legal notices.";
|
||||
|
||||
revision 2013-07-15 {
|
||||
description
|
||||
"This revision adds the following new data types:
|
||||
- ip-address-no-zone
|
||||
- ipv4-address-no-zone
|
||||
- ipv6-address-no-zone";
|
||||
reference
|
||||
"RFC 6991: Common YANG Data Types";
|
||||
}
|
||||
|
||||
revision 2010-09-24 {
|
||||
description
|
||||
"Initial revision.";
|
||||
reference
|
||||
"RFC 6021: Common YANG Data Types";
|
||||
}
|
||||
|
||||
/*** collection of types related to protocol fields ***/
|
||||
|
||||
typedef ip-version {
|
||||
type enumeration {
|
||||
enum unknown {
|
||||
value "0";
|
||||
description
|
||||
"An unknown or unspecified version of the Internet
|
||||
protocol.";
|
||||
}
|
||||
enum ipv4 {
|
||||
value "1";
|
||||
description
|
||||
"The IPv4 protocol as defined in RFC 791.";
|
||||
}
|
||||
enum ipv6 {
|
||||
value "2";
|
||||
description
|
||||
"The IPv6 protocol as defined in RFC 2460.";
|
||||
}
|
||||
}
|
||||
description
|
||||
"This value represents the version of the IP protocol.
|
||||
|
||||
In the value set and its semantics, this type is equivalent
|
||||
to the InetVersion textual convention of the SMIv2.";
|
||||
reference
|
||||
"RFC 791: Internet Protocol
|
||||
RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
|
||||
RFC 4001: Textual Conventions for Internet Network Addresses";
|
||||
}
|
||||
|
||||
typedef dscp {
|
||||
type uint8 {
|
||||
range "0..63";
|
||||
}
|
||||
description
|
||||
"The dscp type represents a Differentiated Services Code Point
|
||||
that may be used for marking packets in a traffic stream.
|
||||
In the value set and its semantics, this type is equivalent
|
||||
to the Dscp textual convention of the SMIv2.";
|
||||
reference
|
||||
"RFC 3289: Management Information Base for the Differentiated
|
||||
Services Architecture
|
||||
RFC 2474: Definition of the Differentiated Services Field
|
||||
(DS Field) in the IPv4 and IPv6 Headers
|
||||
RFC 2780: IANA Allocation Guidelines For Values In
|
||||
the Internet Protocol and Related Headers";
|
||||
}
|
||||
|
||||
typedef ipv6-flow-label {
|
||||
type uint32 {
|
||||
range "0..1048575";
|
||||
}
|
||||
description
|
||||
"The ipv6-flow-label type represents the flow identifier or Flow
|
||||
Label in an IPv6 packet header that may be used to
|
||||
discriminate traffic flows.
|
||||
|
||||
In the value set and its semantics, this type is equivalent
|
||||
to the IPv6FlowLabel textual convention of the SMIv2.";
|
||||
reference
|
||||
"RFC 3595: Textual Conventions for IPv6 Flow Label
|
||||
RFC 2460: Internet Protocol, Version 6 (IPv6) Specification";
|
||||
}
|
||||
|
||||
typedef port-number {
|
||||
type uint16 {
|
||||
range "0..65535";
|
||||
}
|
||||
description
|
||||
"The port-number type represents a 16-bit port number of an
|
||||
Internet transport-layer protocol such as UDP, TCP, DCCP, or
|
||||
SCTP. Port numbers are assigned by IANA. A current list of
|
||||
all assignments is available from <http://www.iana.org/>.
|
||||
|
||||
Note that the port number value zero is reserved by IANA. In
|
||||
situations where the value zero does not make sense, it can
|
||||
be excluded by subtyping the port-number type.
|
||||
In the value set and its semantics, this type is equivalent
|
||||
to the InetPortNumber textual convention of the SMIv2.";
|
||||
reference
|
||||
"RFC 768: User Datagram Protocol
|
||||
RFC 793: Transmission Control Protocol
|
||||
RFC 4960: Stream Control Transmission Protocol
|
||||
RFC 4340: Datagram Congestion Control Protocol (DCCP)
|
||||
RFC 4001: Textual Conventions for Internet Network Addresses";
|
||||
}
|
||||
|
||||
/*** collection of types related to autonomous systems ***/
|
||||
|
||||
typedef as-number {
|
||||
type uint32;
|
||||
description
|
||||
"The as-number type represents autonomous system numbers
|
||||
which identify an Autonomous System (AS). An AS is a set
|
||||
of routers under a single technical administration, using
|
||||
an interior gateway protocol and common metrics to route
|
||||
packets within the AS, and using an exterior gateway
|
||||
protocol to route packets to other ASes. IANA maintains
|
||||
the AS number space and has delegated large parts to the
|
||||
regional registries.
|
||||
|
||||
Autonomous system numbers were originally limited to 16
|
||||
bits. BGP extensions have enlarged the autonomous system
|
||||
number space to 32 bits. This type therefore uses an uint32
|
||||
base type without a range restriction in order to support
|
||||
a larger autonomous system number space.
|
||||
|
||||
In the value set and its semantics, this type is equivalent
|
||||
to the InetAutonomousSystemNumber textual convention of
|
||||
the SMIv2.";
|
||||
reference
|
||||
"RFC 1930: Guidelines for creation, selection, and registration
|
||||
of an Autonomous System (AS)
|
||||
RFC 4271: A Border Gateway Protocol 4 (BGP-4)
|
||||
RFC 4001: Textual Conventions for Internet Network Addresses
|
||||
RFC 6793: BGP Support for Four-Octet Autonomous System (AS)
|
||||
Number Space";
|
||||
}
|
||||
|
||||
/*** collection of types related to IP addresses and hostnames ***/
|
||||
|
||||
typedef ip-address {
|
||||
type union {
|
||||
type inet:ipv4-address;
|
||||
type inet:ipv6-address;
|
||||
}
|
||||
description
|
||||
"The ip-address type represents an IP address and is IP
|
||||
version neutral. The format of the textual representation
|
||||
implies the IP version. This type supports scoped addresses
|
||||
by allowing zone identifiers in the address format.";
|
||||
reference
|
||||
"RFC 4007: IPv6 Scoped Address Architecture";
|
||||
}
|
||||
|
||||
typedef ipv4-address {
|
||||
type string {
|
||||
pattern
|
||||
'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
|
||||
+ '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
|
||||
+ '(%[\p{N}\p{L}]+)?';
|
||||
}
|
||||
description
|
||||
"The ipv4-address type represents an IPv4 address in
|
||||
dotted-quad notation. The IPv4 address may include a zone
|
||||
index, separated by a % sign.
|
||||
|
||||
The zone index is used to disambiguate identical address
|
||||
values. For link-local addresses, the zone index will
|
||||
typically be the interface index number or the name of an
|
||||
interface. If the zone index is not present, the default
|
||||
zone of the device will be used.
|
||||
|
||||
The canonical format for the zone index is the numerical
|
||||
format";
|
||||
}
|
||||
|
||||
typedef ipv6-address {
|
||||
type string {
|
||||
pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
|
||||
+ '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
|
||||
+ '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
|
||||
+ '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
|
||||
+ '(%[\p{N}\p{L}]+)?';
|
||||
pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
|
||||
+ '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
|
||||
+ '(%.+)?';
|
||||
}
|
||||
description
|
||||
"The ipv6-address type represents an IPv6 address in full,
|
||||
mixed, shortened, and shortened-mixed notation. The IPv6
|
||||
address may include a zone index, separated by a % sign.
|
||||
|
||||
The zone index is used to disambiguate identical address
|
||||
values. For link-local addresses, the zone index will
|
||||
typically be the interface index number or the name of an
|
||||
interface. If the zone index is not present, the default
|
||||
zone of the device will be used.
|
||||
|
||||
The canonical format of IPv6 addresses uses the textual
|
||||
representation defined in Section 4 of RFC 5952. The
|
||||
canonical format for the zone index is the numerical
|
||||
format as described in Section 11.2 of RFC 4007.";
|
||||
reference
|
||||
"RFC 4291: IP Version 6 Addressing Architecture
|
||||
RFC 4007: IPv6 Scoped Address Architecture
|
||||
RFC 5952: A Recommendation for IPv6 Address Text
|
||||
Representation";
|
||||
}
|
||||
|
||||
typedef ip-address-no-zone {
|
||||
type union {
|
||||
type inet:ipv4-address-no-zone;
|
||||
type inet:ipv6-address-no-zone;
|
||||
}
|
||||
description
|
||||
"The ip-address-no-zone type represents an IP address and is
|
||||
IP version neutral. The format of the textual representation
|
||||
implies the IP version. This type does not support scoped
|
||||
addresses since it does not allow zone identifiers in the
|
||||
address format.";
|
||||
reference
|
||||
"RFC 4007: IPv6 Scoped Address Architecture";
|
||||
}
|
||||
|
||||
typedef ipv4-address-no-zone {
|
||||
type inet:ipv4-address {
|
||||
pattern '[0-9\.]*';
|
||||
}
|
||||
description
|
||||
"An IPv4 address without a zone index. This type, derived from
|
||||
ipv4-address, may be used in situations where the zone is
|
||||
known from the context and hence no zone index is needed.";
|
||||
}
|
||||
|
||||
typedef ipv6-address-no-zone {
|
||||
type inet:ipv6-address {
|
||||
pattern '[0-9a-fA-F:\.]*';
|
||||
}
|
||||
description
|
||||
"An IPv6 address without a zone index. This type, derived from
|
||||
ipv6-address, may be used in situations where the zone is
|
||||
known from the context and hence no zone index is needed.";
|
||||
reference
|
||||
"RFC 4291: IP Version 6 Addressing Architecture
|
||||
RFC 4007: IPv6 Scoped Address Architecture
|
||||
RFC 5952: A Recommendation for IPv6 Address Text
|
||||
Representation";
|
||||
}
|
||||
|
||||
typedef ip-prefix {
|
||||
type union {
|
||||
type inet:ipv4-prefix;
|
||||
type inet:ipv6-prefix;
|
||||
}
|
||||
description
|
||||
"The ip-prefix type represents an IP prefix and is IP
|
||||
version neutral. The format of the textual representations
|
||||
implies the IP version.";
|
||||
}
|
||||
|
||||
typedef ipv4-prefix {
|
||||
type string {
|
||||
pattern
|
||||
'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
|
||||
+ '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
|
||||
+ '/(([0-9])|([1-2][0-9])|(3[0-2]))';
|
||||
}
|
||||
description
|
||||
"The ipv4-prefix type represents an IPv4 address prefix.
|
||||
The prefix length is given by the number following the
|
||||
slash character and must be less than or equal to 32.
|
||||
|
||||
A prefix length value of n corresponds to an IP address
|
||||
mask that has n contiguous 1-bits from the most
|
||||
significant bit (MSB) and all other bits set to 0.
|
||||
|
||||
The canonical format of an IPv4 prefix has all bits of
|
||||
the IPv4 address set to zero that are not part of the
|
||||
IPv4 prefix.";
|
||||
}
|
||||
|
||||
typedef ipv6-prefix {
|
||||
type string {
|
||||
pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
|
||||
+ '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
|
||||
+ '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
|
||||
+ '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
|
||||
+ '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))';
|
||||
pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
|
||||
+ '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
|
||||
+ '(/.+)';
|
||||
}
|
||||
description
|
||||
"The ipv6-prefix type represents an IPv6 address prefix.
|
||||
The prefix length is given by the number following the
|
||||
slash character and must be less than or equal to 128.
|
||||
|
||||
A prefix length value of n corresponds to an IP address
|
||||
mask that has n contiguous 1-bits from the most
|
||||
significant bit (MSB) and all other bits set to 0.
|
||||
|
||||
The IPv6 address should have all bits that do not belong
|
||||
to the prefix set to zero.
|
||||
|
||||
The canonical format of an IPv6 prefix has all bits of
|
||||
the IPv6 address set to zero that are not part of the
|
||||
IPv6 prefix. Furthermore, the IPv6 address is represented
|
||||
as defined in Section 4 of RFC 5952.";
|
||||
reference
|
||||
"RFC 5952: A Recommendation for IPv6 Address Text
|
||||
Representation";
|
||||
}
|
||||
|
||||
/*** collection of domain name and URI types ***/
|
||||
|
||||
typedef domain-name {
|
||||
type string {
|
||||
length "1..253";
|
||||
pattern
|
||||
'((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
|
||||
+ '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
|
||||
+ '|\.';
|
||||
}
|
||||
description
|
||||
"The domain-name type represents a DNS domain name. The
|
||||
name SHOULD be fully qualified whenever possible.
|
||||
|
||||
Internet domain names are only loosely specified. Section
|
||||
3.5 of RFC 1034 recommends a syntax (modified in Section
|
||||
2.1 of RFC 1123). The pattern above is intended to allow
|
||||
for current practice in domain name use, and some possible
|
||||
future expansion. It is designed to hold various types of
|
||||
domain names, including names used for A or AAAA records
|
||||
(host names) and other records, such as SRV records. Note
|
||||
that Internet host names have a stricter syntax (described
|
||||
in RFC 952) than the DNS recommendations in RFCs 1034 and
|
||||
1123, and that systems that want to store host names in
|
||||
schema nodes using the domain-name type are recommended to
|
||||
adhere to this stricter standard to ensure interoperability.
|
||||
|
||||
The encoding of DNS names in the DNS protocol is limited
|
||||
to 255 characters. Since the encoding consists of labels
|
||||
prefixed by a length bytes and there is a trailing NULL
|
||||
byte, only 253 characters can appear in the textual dotted
|
||||
notation.
|
||||
|
||||
The description clause of schema nodes using the domain-name
|
||||
type MUST describe when and how these names are resolved to
|
||||
IP addresses. Note that the resolution of a domain-name value
|
||||
may require to query multiple DNS records (e.g., A for IPv4
|
||||
and AAAA for IPv6). The order of the resolution process and
|
||||
which DNS record takes precedence can either be defined
|
||||
explicitly or may depend on the configuration of the
|
||||
resolver.
|
||||
|
||||
Domain-name values use the US-ASCII encoding. Their canonical
|
||||
format uses lowercase US-ASCII characters. Internationalized
|
||||
domain names MUST be A-labels as per RFC 5890.";
|
||||
reference
|
||||
"RFC 952: DoD Internet Host Table Specification
|
||||
RFC 1034: Domain Names - Concepts and Facilities
|
||||
RFC 1123: Requirements for Internet Hosts -- Application
|
||||
and Support
|
||||
RFC 2782: A DNS RR for specifying the location of services
|
||||
(DNS SRV)
|
||||
RFC 5890: Internationalized Domain Names in Applications
|
||||
(IDNA): Definitions and Document Framework";
|
||||
}
|
||||
|
||||
typedef host {
|
||||
type union {
|
||||
type inet:ip-address;
|
||||
type inet:domain-name;
|
||||
}
|
||||
description
|
||||
"The host type represents either an IP address or a DNS
|
||||
domain name.";
|
||||
}
|
||||
|
||||
typedef uri {
|
||||
type string;
|
||||
description
|
||||
"The uri type represents a Uniform Resource Identifier
|
||||
(URI) as defined by STD 66.
|
||||
|
||||
Objects using the uri type MUST be in US-ASCII encoding,
|
||||
and MUST be normalized as described by RFC 3986 Sections
|
||||
6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary
|
||||
percent-encoding is removed, and all case-insensitive
|
||||
characters are set to lowercase except for hexadecimal
|
||||
digits, which are normalized to uppercase as described in
|
||||
Section 6.2.2.1.
|
||||
|
||||
The purpose of this normalization is to help provide
|
||||
unique URIs. Note that this normalization is not
|
||||
sufficient to provide uniqueness. Two URIs that are
|
||||
textually distinct after this normalization may still be
|
||||
equivalent.
|
||||
|
||||
Objects using the uri type may restrict the schemes that
|
||||
they permit. For example, 'data:' and 'urn:' schemes
|
||||
might not be appropriate.
|
||||
|
||||
A zero-length URI is not a valid URI. This can be used to
|
||||
express 'URI absent' where required.
|
||||
|
||||
In the value set and its semantics, this type is equivalent
|
||||
to the Uri SMIv2 textual convention defined in RFC 5017.";
|
||||
reference
|
||||
"RFC 3986: Uniform Resource Identifier (URI): Generic Syntax
|
||||
RFC 3305: Report from the Joint W3C/IETF URI Planning Interest
|
||||
Group: Uniform Resource Identifiers (URIs), URLs,
|
||||
and Uniform Resource Names (URNs): Clarifications
|
||||
and Recommendations
|
||||
RFC 5017: MIB Textual Conventions for Uniform Resource
|
||||
Identifiers (URIs)";
|
||||
}
|
||||
|
||||
}
|
1497
models/ietf-yang-library@2019-01-04.h
Normal file
1497
models/ietf-yang-library@2019-01-04.h
Normal file
File diff suppressed because it is too large
Load diff
544
models/ietf-yang-library@2019-01-04.yang
Normal file
544
models/ietf-yang-library@2019-01-04.yang
Normal file
|
@ -0,0 +1,544 @@
|
|||
module ietf-yang-library {
|
||||
yang-version 1.1;
|
||||
namespace "urn:ietf:params:xml:ns:yang:ietf-yang-library";
|
||||
prefix yanglib;
|
||||
|
||||
import ietf-yang-types {
|
||||
prefix yang;
|
||||
reference
|
||||
"RFC 6991: Common YANG Data Types";
|
||||
}
|
||||
import ietf-inet-types {
|
||||
prefix inet;
|
||||
reference
|
||||
"RFC 6991: Common YANG Data Types";
|
||||
}
|
||||
import ietf-datastores {
|
||||
prefix ds;
|
||||
reference
|
||||
"RFC 8342: Network Management Datastore Architecture
|
||||
(NMDA)";
|
||||
}
|
||||
|
||||
organization
|
||||
"IETF NETCONF (Network Configuration) Working Group";
|
||||
contact
|
||||
"WG Web: <https://datatracker.ietf.org/wg/netconf/>
|
||||
WG List: <mailto:netconf@ietf.org>
|
||||
|
||||
Author: Andy Bierman
|
||||
<mailto:andy@yumaworks.com>
|
||||
|
||||
Author: Martin Bjorklund
|
||||
<mailto:mbj@tail-f.com>
|
||||
|
||||
Author: Juergen Schoenwaelder
|
||||
<mailto:j.schoenwaelder@jacobs-university.de>
|
||||
|
||||
Author: Kent Watsen
|
||||
<mailto:kent+ietf@watsen.net>
|
||||
|
||||
Author: Robert Wilton
|
||||
<mailto:rwilton@cisco.com>";
|
||||
description
|
||||
"This module provides information about the YANG modules,
|
||||
datastores, and datastore schemas used by a network
|
||||
management server.
|
||||
|
||||
The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL
|
||||
NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED',
|
||||
'MAY', and 'OPTIONAL' in this document are to be interpreted as
|
||||
described in BCP 14 (RFC 2119) (RFC 8174) when, and only when,
|
||||
they appear in all capitals, as shown here.
|
||||
|
||||
Copyright (c) 2019 IETF Trust and the persons identified as
|
||||
authors of the code. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, is permitted pursuant to, and subject
|
||||
to the license terms contained in, the Simplified BSD License
|
||||
set forth in Section 4.c of the IETF Trust's Legal Provisions
|
||||
Relating to IETF Documents
|
||||
(https://trustee.ietf.org/license-info).
|
||||
|
||||
This version of this YANG module is part of RFC 8525; see
|
||||
the RFC itself for full legal notices.";
|
||||
|
||||
revision 2019-01-04 {
|
||||
description
|
||||
"Added support for multiple datastores according to the
|
||||
Network Management Datastore Architecture (NMDA).";
|
||||
reference
|
||||
"RFC 8525: YANG Library";
|
||||
}
|
||||
revision 2016-04-09 {
|
||||
description
|
||||
"Initial revision.";
|
||||
reference
|
||||
"RFC 7895: YANG Module Library";
|
||||
}
|
||||
|
||||
/*
|
||||
* Typedefs
|
||||
*/
|
||||
|
||||
typedef revision-identifier {
|
||||
type string {
|
||||
pattern '\d{4}-\d{2}-\d{2}';
|
||||
}
|
||||
description
|
||||
"Represents a specific date in YYYY-MM-DD format.";
|
||||
}
|
||||
|
||||
/*
|
||||
* Groupings
|
||||
*/
|
||||
|
||||
grouping module-identification-leafs {
|
||||
description
|
||||
"Parameters for identifying YANG modules and submodules.";
|
||||
leaf name {
|
||||
type yang:yang-identifier;
|
||||
mandatory true;
|
||||
description
|
||||
"The YANG module or submodule name.";
|
||||
}
|
||||
leaf revision {
|
||||
type revision-identifier;
|
||||
description
|
||||
"The YANG module or submodule revision date. If no revision
|
||||
statement is present in the YANG module or submodule, this
|
||||
leaf is not instantiated.";
|
||||
}
|
||||
}
|
||||
|
||||
grouping location-leaf-list {
|
||||
description
|
||||
"Common leaf-list parameter for the locations of modules and
|
||||
submodules.";
|
||||
leaf-list location {
|
||||
type inet:uri;
|
||||
description
|
||||
"Contains a URL that represents the YANG schema
|
||||
resource for this module or submodule.
|
||||
|
||||
This leaf will only be present if there is a URL
|
||||
available for retrieval of the schema for this entry.";
|
||||
}
|
||||
}
|
||||
|
||||
grouping module-implementation-parameters {
|
||||
description
|
||||
"Parameters for describing the implementation of a module.";
|
||||
leaf-list feature {
|
||||
type yang:yang-identifier;
|
||||
description
|
||||
"List of all YANG feature names from this module that are
|
||||
supported by the server, regardless whether they are defined
|
||||
in the module or any included submodule.";
|
||||
}
|
||||
leaf-list deviation {
|
||||
type leafref {
|
||||
path "../../module/name";
|
||||
}
|
||||
description
|
||||
"List of all YANG deviation modules used by this server to
|
||||
modify the conformance of the module associated with this
|
||||
entry. Note that the same module can be used for deviations
|
||||
for multiple modules, so the same entry MAY appear within
|
||||
multiple 'module' entries.
|
||||
|
||||
This reference MUST NOT (directly or indirectly)
|
||||
refer to the module being deviated.
|
||||
|
||||
Robust clients may want to make sure that they handle a
|
||||
situation where a module deviates itself (directly or
|
||||
indirectly) gracefully.";
|
||||
}
|
||||
}
|
||||
|
||||
grouping module-set-parameters {
|
||||
description
|
||||
"A set of parameters that describe a module set.";
|
||||
leaf name {
|
||||
type string;
|
||||
description
|
||||
"An arbitrary name of the module set.";
|
||||
}
|
||||
list module {
|
||||
key "name";
|
||||
description
|
||||
"An entry in this list represents a module implemented by the
|
||||
server, as per Section 5.6.5 of RFC 7950, with a particular
|
||||
set of supported features and deviations.";
|
||||
reference
|
||||
"RFC 7950: The YANG 1.1 Data Modeling Language";
|
||||
uses module-identification-leafs;
|
||||
leaf namespace {
|
||||
type inet:uri;
|
||||
mandatory true;
|
||||
description
|
||||
"The XML namespace identifier for this module.";
|
||||
}
|
||||
uses location-leaf-list;
|
||||
list submodule {
|
||||
key "name";
|
||||
description
|
||||
"Each entry represents one submodule within the
|
||||
parent module.";
|
||||
uses module-identification-leafs;
|
||||
uses location-leaf-list;
|
||||
}
|
||||
uses module-implementation-parameters;
|
||||
}
|
||||
list import-only-module {
|
||||
key "name revision";
|
||||
description
|
||||
"An entry in this list indicates that the server imports
|
||||
reusable definitions from the specified revision of the
|
||||
module but does not implement any protocol-accessible
|
||||
objects from this revision.
|
||||
|
||||
Multiple entries for the same module name MAY exist. This
|
||||
can occur if multiple modules import the same module but
|
||||
specify different revision dates in the import statements.";
|
||||
leaf name {
|
||||
type yang:yang-identifier;
|
||||
description
|
||||
"The YANG module name.";
|
||||
}
|
||||
leaf revision {
|
||||
type union {
|
||||
type revision-identifier;
|
||||
type string {
|
||||
length "0";
|
||||
}
|
||||
}
|
||||
description
|
||||
"The YANG module revision date.
|
||||
A zero-length string is used if no revision statement
|
||||
is present in the YANG module.";
|
||||
}
|
||||
leaf namespace {
|
||||
type inet:uri;
|
||||
mandatory true;
|
||||
description
|
||||
"The XML namespace identifier for this module.";
|
||||
}
|
||||
uses location-leaf-list;
|
||||
list submodule {
|
||||
key "name";
|
||||
description
|
||||
"Each entry represents one submodule within the
|
||||
parent module.";
|
||||
uses module-identification-leafs;
|
||||
uses location-leaf-list;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grouping yang-library-parameters {
|
||||
description
|
||||
"The YANG library data structure is represented as a grouping
|
||||
so it can be reused in configuration or another monitoring
|
||||
data structure.";
|
||||
list module-set {
|
||||
key "name";
|
||||
description
|
||||
"A set of modules that may be used by one or more schemas.
|
||||
|
||||
A module set does not have to be referentially complete,
|
||||
i.e., it may define modules that contain import statements
|
||||
for other modules not included in the module set.";
|
||||
uses module-set-parameters;
|
||||
}
|
||||
list schema {
|
||||
key "name";
|
||||
description
|
||||
"A datastore schema that may be used by one or more
|
||||
datastores.
|
||||
|
||||
The schema must be valid and referentially complete, i.e.,
|
||||
it must contain modules to satisfy all used import
|
||||
statements for all modules specified in the schema.";
|
||||
leaf name {
|
||||
type string;
|
||||
description
|
||||
"An arbitrary name of the schema.";
|
||||
}
|
||||
leaf-list module-set {
|
||||
type leafref {
|
||||
path "../../module-set/name";
|
||||
}
|
||||
description
|
||||
"A set of module-sets that are included in this schema.
|
||||
If a non-import-only module appears in multiple module
|
||||
sets, then the module revision and the associated features
|
||||
and deviations must be identical.";
|
||||
}
|
||||
}
|
||||
list datastore {
|
||||
key "name";
|
||||
description
|
||||
"A datastore supported by this server.
|
||||
|
||||
Each datastore indicates which schema it supports.
|
||||
|
||||
The server MUST instantiate one entry in this list per
|
||||
specific datastore it supports.
|
||||
Each datastore entry with the same datastore schema SHOULD
|
||||
reference the same schema.";
|
||||
leaf name {
|
||||
type ds:datastore-ref;
|
||||
description
|
||||
"The identity of the datastore.";
|
||||
}
|
||||
leaf schema {
|
||||
type leafref {
|
||||
path "../../schema/name";
|
||||
}
|
||||
mandatory true;
|
||||
description
|
||||
"A reference to the schema supported by this datastore.
|
||||
All non-import-only modules of the schema are implemented
|
||||
with their associated features and deviations.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Top-level container
|
||||
*/
|
||||
|
||||
container yang-library {
|
||||
config false;
|
||||
description
|
||||
"Container holding the entire YANG library of this server.";
|
||||
uses yang-library-parameters;
|
||||
leaf content-id {
|
||||
type string;
|
||||
mandatory true;
|
||||
description
|
||||
"A server-generated identifier of the contents of the
|
||||
'/yang-library' tree. The server MUST change the value of
|
||||
this leaf if the information represented by the
|
||||
'/yang-library' tree, except '/yang-library/content-id', has
|
||||
changed.";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Notifications
|
||||
*/
|
||||
|
||||
notification yang-library-update {
|
||||
description
|
||||
"Generated when any YANG library information on the
|
||||
server has changed.";
|
||||
leaf content-id {
|
||||
type leafref {
|
||||
path "/yanglib:yang-library/yanglib:content-id";
|
||||
}
|
||||
mandatory true;
|
||||
description
|
||||
"Contains the YANG library content identifier for the updated
|
||||
YANG library at the time the notification is generated.";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Legacy groupings
|
||||
*/
|
||||
|
||||
grouping module-list {
|
||||
status deprecated;
|
||||
description
|
||||
"The module data structure is represented as a grouping
|
||||
so it can be reused in configuration or another monitoring
|
||||
data structure.";
|
||||
|
||||
grouping common-leafs {
|
||||
status deprecated;
|
||||
description
|
||||
"Common parameters for YANG modules and submodules.";
|
||||
leaf name {
|
||||
type yang:yang-identifier;
|
||||
status deprecated;
|
||||
description
|
||||
"The YANG module or submodule name.";
|
||||
}
|
||||
leaf revision {
|
||||
type union {
|
||||
type revision-identifier;
|
||||
type string {
|
||||
length "0";
|
||||
}
|
||||
}
|
||||
status deprecated;
|
||||
description
|
||||
"The YANG module or submodule revision date.
|
||||
A zero-length string is used if no revision statement
|
||||
is present in the YANG module or submodule.";
|
||||
}
|
||||
}
|
||||
|
||||
grouping schema-leaf {
|
||||
status deprecated;
|
||||
description
|
||||
"Common schema leaf parameter for modules and submodules.";
|
||||
leaf schema {
|
||||
type inet:uri;
|
||||
description
|
||||
"Contains a URL that represents the YANG schema
|
||||
resource for this module or submodule.
|
||||
|
||||
This leaf will only be present if there is a URL
|
||||
available for retrieval of the schema for this entry.";
|
||||
}
|
||||
}
|
||||
list module {
|
||||
key "name revision";
|
||||
status deprecated;
|
||||
description
|
||||
"Each entry represents one revision of one module
|
||||
currently supported by the server.";
|
||||
uses common-leafs {
|
||||
status deprecated;
|
||||
}
|
||||
uses schema-leaf {
|
||||
status deprecated;
|
||||
}
|
||||
leaf namespace {
|
||||
type inet:uri;
|
||||
mandatory true;
|
||||
status deprecated;
|
||||
description
|
||||
"The XML namespace identifier for this module.";
|
||||
}
|
||||
leaf-list feature {
|
||||
type yang:yang-identifier;
|
||||
status deprecated;
|
||||
description
|
||||
"List of YANG feature names from this module that are
|
||||
supported by the server, regardless of whether they are
|
||||
defined in the module or any included submodule.";
|
||||
}
|
||||
list deviation {
|
||||
key "name revision";
|
||||
status deprecated;
|
||||
description
|
||||
"List of YANG deviation module names and revisions
|
||||
used by this server to modify the conformance of
|
||||
the module associated with this entry. Note that
|
||||
the same module can be used for deviations for
|
||||
multiple modules, so the same entry MAY appear
|
||||
within multiple 'module' entries.
|
||||
|
||||
The deviation module MUST be present in the 'module'
|
||||
list, with the same name and revision values.
|
||||
The 'conformance-type' value will be 'implement' for
|
||||
the deviation module.";
|
||||
uses common-leafs {
|
||||
status deprecated;
|
||||
}
|
||||
}
|
||||
leaf conformance-type {
|
||||
type enumeration {
|
||||
enum implement {
|
||||
description
|
||||
"Indicates that the server implements one or more
|
||||
protocol-accessible objects defined in the YANG module
|
||||
identified in this entry. This includes deviation
|
||||
statements defined in the module.
|
||||
|
||||
For YANG version 1.1 modules, there is at most one
|
||||
'module' entry with conformance type 'implement' for a
|
||||
particular module name, since YANG 1.1 requires that
|
||||
at most one revision of a module is implemented.
|
||||
|
||||
For YANG version 1 modules, there SHOULD NOT be more
|
||||
than one 'module' entry for a particular module
|
||||
name.";
|
||||
}
|
||||
enum import {
|
||||
description
|
||||
"Indicates that the server imports reusable definitions
|
||||
from the specified revision of the module but does
|
||||
not implement any protocol-accessible objects from
|
||||
this revision.
|
||||
|
||||
Multiple 'module' entries for the same module name MAY
|
||||
exist. This can occur if multiple modules import the
|
||||
same module but specify different revision dates in
|
||||
the import statements.";
|
||||
}
|
||||
}
|
||||
mandatory true;
|
||||
status deprecated;
|
||||
description
|
||||
"Indicates the type of conformance the server is claiming
|
||||
for the YANG module identified by this entry.";
|
||||
}
|
||||
list submodule {
|
||||
key "name revision";
|
||||
status deprecated;
|
||||
description
|
||||
"Each entry represents one submodule within the
|
||||
parent module.";
|
||||
uses common-leafs {
|
||||
status deprecated;
|
||||
}
|
||||
uses schema-leaf {
|
||||
status deprecated;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Legacy operational state data nodes
|
||||
*/
|
||||
|
||||
container modules-state {
|
||||
config false;
|
||||
status deprecated;
|
||||
description
|
||||
"Contains YANG module monitoring information.";
|
||||
leaf module-set-id {
|
||||
type string;
|
||||
mandatory true;
|
||||
status deprecated;
|
||||
description
|
||||
"Contains a server-specific identifier representing
|
||||
the current set of modules and submodules. The
|
||||
server MUST change the value of this leaf if the
|
||||
information represented by the 'module' list instances
|
||||
has changed.";
|
||||
}
|
||||
uses module-list {
|
||||
status deprecated;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Legacy notifications
|
||||
*/
|
||||
|
||||
notification yang-library-change {
|
||||
status deprecated;
|
||||
description
|
||||
"Generated when the set of modules and submodules supported
|
||||
by the server has changed.";
|
||||
leaf module-set-id {
|
||||
type leafref {
|
||||
path "/yanglib:modules-state/yanglib:module-set-id";
|
||||
}
|
||||
mandatory true;
|
||||
status deprecated;
|
||||
description
|
||||
"Contains the module-set-id value representing the
|
||||
set of modules and submodules supported at the server
|
||||
at the time the notification is generated.";
|
||||
}
|
||||
}
|
||||
}
|
220
models/ietf-yang-metadata@2016-08-05.h
Normal file
220
models/ietf-yang-metadata@2016-08-05.h
Normal file
|
@ -0,0 +1,220 @@
|
|||
unsigned char ietf_yang_metadata_2016_08_05_yang[] = {
|
||||
0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x69, 0x65, 0x74, 0x66, 0x2d,
|
||||
0x79, 0x61, 0x6e, 0x67, 0x2d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
|
||||
0x61, 0x20, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
|
||||
0x20, 0x22, 0x75, 0x72, 0x6e, 0x3a, 0x69, 0x65, 0x74, 0x66, 0x3a, 0x70,
|
||||
0x61, 0x72, 0x61, 0x6d, 0x73, 0x3a, 0x78, 0x6d, 0x6c, 0x3a, 0x6e, 0x73,
|
||||
0x3a, 0x79, 0x61, 0x6e, 0x67, 0x3a, 0x69, 0x65, 0x74, 0x66, 0x2d, 0x79,
|
||||
0x61, 0x6e, 0x67, 0x2d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
|
||||
0x22, 0x3b, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x6d, 0x64, 0x3b,
|
||||
0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x20, 0x22, 0x49, 0x45, 0x54, 0x46, 0x20, 0x4e, 0x45, 0x54, 0x4d, 0x4f,
|
||||
0x44, 0x20, 0x28, 0x4e, 0x45, 0x54, 0x43, 0x4f, 0x4e, 0x46, 0x20, 0x44,
|
||||
0x61, 0x74, 0x61, 0x20, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x69, 0x6e, 0x67,
|
||||
0x20, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x29, 0x20, 0x57,
|
||||
0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70,
|
||||
0x22, 0x3b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x0a, 0x22, 0x57,
|
||||
0x47, 0x20, 0x57, 0x65, 0x62, 0x3a, 0x20, 0x20, 0x20, 0x3c, 0x68, 0x74,
|
||||
0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x74, 0x72,
|
||||
0x61, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x6f,
|
||||
0x72, 0x67, 0x2f, 0x77, 0x67, 0x2f, 0x6e, 0x65, 0x74, 0x6d, 0x6f, 0x64,
|
||||
0x2f, 0x3e, 0x0a, 0x0a, 0x57, 0x47, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x3a,
|
||||
0x20, 0x20, 0x3c, 0x6d, 0x61, 0x69, 0x6c, 0x74, 0x6f, 0x3a, 0x6e, 0x65,
|
||||
0x74, 0x6d, 0x6f, 0x64, 0x40, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x6f, 0x72,
|
||||
0x67, 0x3e, 0x0a, 0x0a, 0x57, 0x47, 0x20, 0x43, 0x68, 0x61, 0x69, 0x72,
|
||||
0x3a, 0x20, 0x4c, 0x6f, 0x75, 0x20, 0x42, 0x65, 0x72, 0x67, 0x65, 0x72,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x3c, 0x6d, 0x61, 0x69, 0x6c, 0x74, 0x6f, 0x3a, 0x6c, 0x62, 0x65, 0x72,
|
||||
0x67, 0x65, 0x72, 0x40, 0x6c, 0x61, 0x62, 0x6e, 0x2e, 0x6e, 0x65, 0x74,
|
||||
0x3e, 0x0a, 0x0a, 0x57, 0x47, 0x20, 0x43, 0x68, 0x61, 0x69, 0x72, 0x3a,
|
||||
0x20, 0x4b, 0x65, 0x6e, 0x74, 0x20, 0x57, 0x61, 0x74, 0x73, 0x65, 0x6e,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x3c, 0x6d, 0x61, 0x69, 0x6c, 0x74, 0x6f, 0x3a, 0x6b, 0x77, 0x61, 0x74,
|
||||
0x73, 0x65, 0x6e, 0x40, 0x6a, 0x75, 0x6e, 0x69, 0x70, 0x65, 0x72, 0x2e,
|
||||
0x6e, 0x65, 0x74, 0x3e, 0x0a, 0x0a, 0x45, 0x64, 0x69, 0x74, 0x6f, 0x72,
|
||||
0x3a, 0x20, 0x20, 0x20, 0x4c, 0x61, 0x64, 0x69, 0x73, 0x6c, 0x61, 0x76,
|
||||
0x20, 0x4c, 0x68, 0x6f, 0x74, 0x6b, 0x61, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x6d, 0x61, 0x69, 0x6c,
|
||||
0x74, 0x6f, 0x3a, 0x6c, 0x68, 0x6f, 0x74, 0x6b, 0x61, 0x40, 0x6e, 0x69,
|
||||
0x63, 0x2e, 0x63, 0x7a, 0x3e, 0x22, 0x3b, 0x64, 0x65, 0x73, 0x63, 0x72,
|
||||
0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x22, 0x54, 0x68, 0x69, 0x73,
|
||||
0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
|
||||
0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x20,
|
||||
0x27, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x27, 0x20,
|
||||
0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68,
|
||||
0x61, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x0a, 0x66, 0x6f,
|
||||
0x72, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x6d,
|
||||
0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x20, 0x61, 0x6e, 0x6e, 0x6f,
|
||||
0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x0a, 0x0a, 0x43, 0x6f,
|
||||
0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20,
|
||||
0x32, 0x30, 0x31, 0x36, 0x20, 0x49, 0x45, 0x54, 0x46, 0x20, 0x54, 0x72,
|
||||
0x75, 0x73, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
|
||||
0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x69, 0x64, 0x65, 0x6e,
|
||||
0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x61, 0x73, 0x0a, 0x61, 0x75,
|
||||
0x74, 0x68, 0x6f, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
|
||||
0x20, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x20, 0x20, 0x41, 0x6c, 0x6c, 0x20,
|
||||
0x72, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x72, 0x65, 0x73, 0x65, 0x72,
|
||||
0x76, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x52, 0x65, 0x64, 0x69, 0x73, 0x74,
|
||||
0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6e, 0x64,
|
||||
0x20, 0x75, 0x73, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x6f, 0x75, 0x72,
|
||||
0x63, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x69, 0x6e, 0x61, 0x72,
|
||||
0x79, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2c, 0x20, 0x77, 0x69, 0x74,
|
||||
0x68, 0x20, 0x6f, 0x72, 0x0a, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74,
|
||||
0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x2c, 0x20, 0x69, 0x73, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74,
|
||||
0x74, 0x65, 0x64, 0x20, 0x70, 0x75, 0x72, 0x73, 0x75, 0x61, 0x6e, 0x74,
|
||||
0x20, 0x74, 0x6f, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x75, 0x62,
|
||||
0x6a, 0x65, 0x63, 0x74, 0x20, 0x74, 0x6f, 0x0a, 0x74, 0x68, 0x65, 0x20,
|
||||
0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d,
|
||||
0x73, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x20,
|
||||
0x69, 0x6e, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x69, 0x6d, 0x70,
|
||||
0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x42, 0x53, 0x44, 0x20, 0x4c,
|
||||
0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x73, 0x65, 0x74, 0x0a, 0x66,
|
||||
0x6f, 0x72, 0x74, 0x68, 0x20, 0x69, 0x6e, 0x20, 0x53, 0x65, 0x63, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x20, 0x34, 0x2e, 0x63, 0x20, 0x6f, 0x66, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x49, 0x45, 0x54, 0x46, 0x20, 0x54, 0x72, 0x75, 0x73,
|
||||
0x74, 0x27, 0x73, 0x20, 0x4c, 0x65, 0x67, 0x61, 0x6c, 0x20, 0x50, 0x72,
|
||||
0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x52, 0x65, 0x6c,
|
||||
0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x49, 0x45, 0x54,
|
||||
0x46, 0x20, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x0a,
|
||||
0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x74, 0x72, 0x75, 0x73,
|
||||
0x74, 0x65, 0x65, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x6f, 0x72, 0x67,
|
||||
0x2f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2d, 0x69, 0x6e, 0x66,
|
||||
0x6f, 0x29, 0x2e, 0x0a, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x76, 0x65,
|
||||
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69,
|
||||
0x73, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
|
||||
0x65, 0x20, 0x69, 0x73, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
|
||||
0x20, 0x52, 0x46, 0x43, 0x20, 0x37, 0x39, 0x35, 0x32, 0x0a, 0x28, 0x68,
|
||||
0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x72, 0x66,
|
||||
0x63, 0x2d, 0x65, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x6f, 0x72, 0x67,
|
||||
0x2f, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x72, 0x66, 0x63, 0x37, 0x39, 0x35,
|
||||
0x32, 0x29, 0x3b, 0x20, 0x73, 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
|
||||
0x52, 0x46, 0x43, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6c, 0x66, 0x0a, 0x66,
|
||||
0x6f, 0x72, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x6c, 0x65, 0x67, 0x61,
|
||||
0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x22, 0x3b,
|
||||
0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x32, 0x30, 0x31,
|
||||
0x36, 0x2d, 0x30, 0x38, 0x2d, 0x30, 0x35, 0x20, 0x7b, 0x64, 0x65, 0x73,
|
||||
0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x22, 0x49, 0x6e,
|
||||
0x69, 0x74, 0x69, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x2e, 0x22, 0x3b, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e,
|
||||
0x63, 0x65, 0x20, 0x22, 0x52, 0x46, 0x43, 0x20, 0x37, 0x39, 0x35, 0x32,
|
||||
0x3a, 0x20, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61,
|
||||
0x6e, 0x64, 0x20, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x4d, 0x65, 0x74,
|
||||
0x61, 0x64, 0x61, 0x74, 0x61, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x59,
|
||||
0x41, 0x4e, 0x47, 0x22, 0x3b, 0x7d, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x20, 0x7b, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74,
|
||||
0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
|
||||
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x22, 0x54, 0x68, 0x69, 0x73, 0x20,
|
||||
0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6c,
|
||||
0x6c, 0x6f, 0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64, 0x65, 0x66,
|
||||
0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61,
|
||||
0x74, 0x61, 0x20, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x73, 0x20, 0x69, 0x6e, 0x0a, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x6d,
|
||||
0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x65,
|
||||
0x20, 0x27, 0x6d, 0x64, 0x3a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x27, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65,
|
||||
0x6e, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61,
|
||||
0x72, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x0a, 0x61, 0x74, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x74, 0x6f, 0x70, 0x20, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x20,
|
||||
0x6f, 0x66, 0x20, 0x61, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x6d, 0x6f,
|
||||
0x64, 0x75, 0x6c, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x73, 0x75, 0x62, 0x6d,
|
||||
0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2c, 0x20, 0x69, 0x2e, 0x65, 0x2e, 0x2c,
|
||||
0x20, 0x69, 0x74, 0x0a, 0x62, 0x65, 0x63, 0x6f, 0x6d, 0x65, 0x73, 0x20,
|
||||
0x61, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x6e,
|
||||
0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
|
||||
0x20, 0x41, 0x42, 0x4e, 0x46, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x66, 0x6f,
|
||||
0x72, 0x0a, 0x27, 0x62, 0x6f, 0x64, 0x79, 0x2d, 0x73, 0x74, 0x6d, 0x74,
|
||||
0x73, 0x27, 0x20, 0x28, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20,
|
||||
0x31, 0x34, 0x20, 0x69, 0x6e, 0x20, 0x52, 0x46, 0x43, 0x20, 0x37, 0x39,
|
||||
0x35, 0x30, 0x29, 0x2e, 0x0a, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x61, 0x72,
|
||||
0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x27, 0x6d, 0x64, 0x3a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x27, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d,
|
||||
0x65, 0x6e, 0x74, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x73, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x0a, 0x6f, 0x66, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x2e, 0x20, 0x20, 0x53, 0x79, 0x6e, 0x74, 0x61, 0x63, 0x74,
|
||||
0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69,
|
||||
0x73, 0x20, 0x61, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x69, 0x64, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x20, 0x61, 0x73, 0x0a, 0x64,
|
||||
0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x53, 0x65,
|
||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x36, 0x2e, 0x32, 0x20, 0x6f, 0x66,
|
||||
0x20, 0x52, 0x46, 0x43, 0x20, 0x37, 0x39, 0x35, 0x30, 0x2e, 0x0a, 0x0a,
|
||||
0x41, 0x6e, 0x20, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x77, 0x69,
|
||||
0x74, 0x68, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x27, 0x65, 0x78, 0x74,
|
||||
0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x27, 0x20, 0x73, 0x74, 0x61, 0x74,
|
||||
0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69,
|
||||
0x74, 0x73, 0x0a, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73,
|
||||
0x70, 0x61, 0x63, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x74, 0x68,
|
||||
0x65, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x20, 0x66,
|
||||
0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x59, 0x41, 0x4e, 0x47,
|
||||
0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x77,
|
||||
0x68, 0x69, 0x63, 0x68, 0x0a, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x64,
|
||||
0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x54, 0x68, 0x65,
|
||||
0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f,
|
||||
0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x69,
|
||||
0x73, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20,
|
||||
0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x0a,
|
||||
0x77, 0x61, 0x79, 0x20, 0x61, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61,
|
||||
0x20, 0x6c, 0x65, 0x61, 0x66, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x6e,
|
||||
0x6f, 0x64, 0x65, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x27, 0x74, 0x79, 0x70, 0x65, 0x27, 0x20, 0x73, 0x74, 0x61,
|
||||
0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x54, 0x68, 0x65,
|
||||
0x20, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x73, 0x20, 0x6f,
|
||||
0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x74, 0x68,
|
||||
0x65, 0x72, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x0a,
|
||||
0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x75, 0x73,
|
||||
0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c,
|
||||
0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61,
|
||||
0x72, 0x64, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x73, 0x75, 0x62, 0x73,
|
||||
0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x28, 0x61,
|
||||
0x6c, 0x6c, 0x0a, 0x61, 0x72, 0x65, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x61, 0x6c, 0x29, 0x3a, 0x20, 0x27, 0x64, 0x65, 0x73, 0x63, 0x72,
|
||||
0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x27, 0x2c, 0x20, 0x27, 0x69, 0x66,
|
||||
0x2d, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x27, 0x2c, 0x20, 0x27,
|
||||
0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x27, 0x2c, 0x0a,
|
||||
0x27, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x27, 0x2c, 0x20, 0x61, 0x6e,
|
||||
0x64, 0x20, 0x27, 0x75, 0x6e, 0x69, 0x74, 0x73, 0x27, 0x2e, 0x0a, 0x0a,
|
||||
0x41, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x6e,
|
||||
0x6f, 0x75, 0x6e, 0x63, 0x65, 0x73, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f,
|
||||
0x72, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x70, 0x61, 0x72,
|
||||
0x74, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x20, 0x61, 0x6e, 0x6e, 0x6f,
|
||||
0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x62, 0x79, 0x0a, 0x69, 0x6e,
|
||||
0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20,
|
||||
0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x77, 0x68,
|
||||
0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6e, 0x6e, 0x6f,
|
||||
0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x64, 0x65,
|
||||
0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x0a,
|
||||
0x74, 0x68, 0x65, 0x20, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73,
|
||||
0x65, 0x64, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x6d, 0x6f, 0x64, 0x75,
|
||||
0x6c, 0x65, 0x73, 0x2c, 0x20, 0x65, 0x2e, 0x67, 0x2e, 0x2c, 0x20, 0x69,
|
||||
0x6e, 0x20, 0x61, 0x20, 0x4e, 0x45, 0x54, 0x43, 0x4f, 0x4e, 0x46, 0x20,
|
||||
0x3c, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x3e, 0x0a, 0x6d, 0x65, 0x73, 0x73,
|
||||
0x61, 0x67, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61,
|
||||
0x72, 0x79, 0x20, 0x28, 0x52, 0x46, 0x43, 0x20, 0x37, 0x39, 0x35, 0x30,
|
||||
0x29, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x61, 0x6e, 0x6e, 0x6f,
|
||||
0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x61, 0x6e, 0x0a, 0x74,
|
||||
0x68, 0x65, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x61, 0x74, 0x74, 0x61, 0x63,
|
||||
0x68, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x69,
|
||||
0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61,
|
||||
0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x20, 0x64,
|
||||
0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x6e,
|
||||
0x79, 0x0a, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
|
||||
0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x61, 0x64,
|
||||
0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x0a,
|
||||
0x0a, 0x58, 0x4d, 0x4c, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e,
|
||||
0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x53, 0x4f, 0x4e, 0x20, 0x65,
|
||||
0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x61,
|
||||
0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61,
|
||||
0x72, 0x65, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x69,
|
||||
0x6e, 0x0a, 0x52, 0x46, 0x43, 0x20, 0x37, 0x39, 0x35, 0x32, 0x2e, 0x22,
|
||||
0x3b, 0x7d, 0x7d, 0x00
|
||||
};
|
80
models/ietf-yang-metadata@2016-08-05.yang
Normal file
80
models/ietf-yang-metadata@2016-08-05.yang
Normal file
|
@ -0,0 +1,80 @@
|
|||
module ietf-yang-metadata {
|
||||
namespace "urn:ietf:params:xml:ns:yang:ietf-yang-metadata";
|
||||
prefix md;
|
||||
|
||||
organization
|
||||
"IETF NETMOD (NETCONF Data Modeling Language) Working Group";
|
||||
contact
|
||||
"WG Web: <https://datatracker.ietf.org/wg/netmod/>
|
||||
|
||||
WG List: <mailto:netmod@ietf.org>
|
||||
|
||||
WG Chair: Lou Berger
|
||||
<mailto:lberger@labn.net>
|
||||
|
||||
WG Chair: Kent Watsen
|
||||
<mailto:kwatsen@juniper.net>
|
||||
|
||||
Editor: Ladislav Lhotka
|
||||
<mailto:lhotka@nic.cz>";
|
||||
description
|
||||
"This YANG module defines an 'extension' statement that allows
|
||||
for defining metadata annotations.
|
||||
|
||||
Copyright (c) 2016 IETF Trust and the persons identified as
|
||||
authors of the code. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, is permitted pursuant to, and subject to
|
||||
the license terms contained in, the Simplified BSD License set
|
||||
forth in Section 4.c of the IETF Trust's Legal Provisions
|
||||
Relating to IETF Documents
|
||||
(http://trustee.ietf.org/license-info).
|
||||
|
||||
This version of this YANG module is part of RFC 7952
|
||||
(http://www.rfc-editor.org/info/rfc7952); see the RFC itself
|
||||
for full legal notices.";
|
||||
|
||||
revision 2016-08-05 {
|
||||
description
|
||||
"Initial revision.";
|
||||
reference
|
||||
"RFC 7952: Defining and Using Metadata with YANG";
|
||||
}
|
||||
|
||||
extension annotation {
|
||||
argument name;
|
||||
description
|
||||
"This extension allows for defining metadata annotations in
|
||||
YANG modules. The 'md:annotation' statement can appear only
|
||||
at the top level of a YANG module or submodule, i.e., it
|
||||
becomes a new alternative in the ABNF production rule for
|
||||
'body-stmts' (Section 14 in RFC 7950).
|
||||
|
||||
The argument of the 'md:annotation' statement defines the name
|
||||
of the annotation. Syntactically, it is a YANG identifier as
|
||||
defined in Section 6.2 of RFC 7950.
|
||||
|
||||
An annotation defined with this 'extension' statement inherits
|
||||
the namespace and other context from the YANG module in which
|
||||
it is defined.
|
||||
|
||||
The data type of the annotation value is specified in the same
|
||||
way as for a leaf data node using the 'type' statement.
|
||||
|
||||
The semantics of the annotation and other documentation can be
|
||||
specified using the following standard YANG substatements (all
|
||||
are optional): 'description', 'if-feature', 'reference',
|
||||
'status', and 'units'.
|
||||
|
||||
A server announces support for a particular annotation by
|
||||
including the module in which the annotation is defined among
|
||||
the advertised YANG modules, e.g., in a NETCONF <hello>
|
||||
message or in the YANG library (RFC 7950). The annotation can
|
||||
then be attached to any instance of a data node defined in any
|
||||
YANG module that is advertised by the server.
|
||||
|
||||
XML encoding and JSON encoding of annotations are defined in
|
||||
RFC 7952.";
|
||||
}
|
||||
}
|
651
models/ietf-yang-schema-mount@2019-01-14.h
Normal file
651
models/ietf-yang-schema-mount@2019-01-14.h
Normal file
|
@ -0,0 +1,651 @@
|
|||
unsigned char ietf_yang_schema_mount_2019_01_14_yang[] = {
|
||||
0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x69, 0x65, 0x74, 0x66, 0x2d,
|
||||
0x79, 0x61, 0x6e, 0x67, 0x2d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2d,
|
||||
0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x79, 0x61,
|
||||
0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x31,
|
||||
0x2e, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70,
|
||||
0x61, 0x63, 0x65, 0x20, 0x22, 0x75, 0x72, 0x6e, 0x3a, 0x69, 0x65, 0x74,
|
||||
0x66, 0x3a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3a, 0x78, 0x6d, 0x6c,
|
||||
0x3a, 0x6e, 0x73, 0x3a, 0x79, 0x61, 0x6e, 0x67, 0x3a, 0x69, 0x65, 0x74,
|
||||
0x66, 0x2d, 0x79, 0x61, 0x6e, 0x67, 0x2d, 0x73, 0x63, 0x68, 0x65, 0x6d,
|
||||
0x61, 0x2d, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x79, 0x61, 0x6e, 0x67, 0x6d,
|
||||
0x6e, 0x74, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x69, 0x6d, 0x70, 0x6f, 0x72,
|
||||
0x74, 0x20, 0x69, 0x65, 0x74, 0x66, 0x2d, 0x69, 0x6e, 0x65, 0x74, 0x2d,
|
||||
0x74, 0x79, 0x70, 0x65, 0x73, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x69, 0x6e, 0x65, 0x74, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e,
|
||||
0x63, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x52, 0x46,
|
||||
0x43, 0x20, 0x36, 0x39, 0x39, 0x31, 0x3a, 0x20, 0x43, 0x6f, 0x6d, 0x6d,
|
||||
0x6f, 0x6e, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x44, 0x61, 0x74, 0x61,
|
||||
0x20, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x7d,
|
||||
0x0a, 0x0a, 0x20, 0x20, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x69,
|
||||
0x65, 0x74, 0x66, 0x2d, 0x79, 0x61, 0x6e, 0x67, 0x2d, 0x74, 0x79, 0x70,
|
||||
0x65, 0x73, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x72, 0x65,
|
||||
0x66, 0x69, 0x78, 0x20, 0x79, 0x61, 0x6e, 0x67, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x52, 0x46, 0x43, 0x20, 0x36,
|
||||
0x39, 0x39, 0x31, 0x3a, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x20,
|
||||
0x59, 0x41, 0x4e, 0x47, 0x20, 0x44, 0x61, 0x74, 0x61, 0x20, 0x54, 0x79,
|
||||
0x70, 0x65, 0x73, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20,
|
||||
0x20, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x49, 0x45, 0x54, 0x46, 0x20,
|
||||
0x4e, 0x45, 0x54, 0x4d, 0x4f, 0x44, 0x20, 0x28, 0x4e, 0x45, 0x54, 0x43,
|
||||
0x4f, 0x4e, 0x46, 0x20, 0x44, 0x61, 0x74, 0x61, 0x20, 0x4d, 0x6f, 0x64,
|
||||
0x65, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61,
|
||||
0x67, 0x65, 0x29, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x20,
|
||||
0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x63,
|
||||
0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22,
|
||||
0x57, 0x47, 0x20, 0x57, 0x65, 0x62, 0x3a, 0x20, 0x20, 0x20, 0x3c, 0x68,
|
||||
0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x74,
|
||||
0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e,
|
||||
0x6f, 0x72, 0x67, 0x2f, 0x77, 0x67, 0x2f, 0x6e, 0x65, 0x74, 0x6d, 0x6f,
|
||||
0x64, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x57, 0x47, 0x20,
|
||||
0x4c, 0x69, 0x73, 0x74, 0x3a, 0x20, 0x20, 0x3c, 0x6d, 0x61, 0x69, 0x6c,
|
||||
0x74, 0x6f, 0x3a, 0x6e, 0x65, 0x74, 0x6d, 0x6f, 0x64, 0x40, 0x69, 0x65,
|
||||
0x74, 0x66, 0x2e, 0x6f, 0x72, 0x67, 0x3e, 0x0a, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x45, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x3a, 0x20, 0x20, 0x20,
|
||||
0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x20, 0x42, 0x6a, 0x6f, 0x72, 0x6b,
|
||||
0x6c, 0x75, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x6d, 0x61, 0x69,
|
||||
0x6c, 0x74, 0x6f, 0x3a, 0x6d, 0x62, 0x6a, 0x40, 0x74, 0x61, 0x69, 0x6c,
|
||||
0x2d, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x3e, 0x0a, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x45, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x3a, 0x20, 0x20, 0x20,
|
||||
0x4c, 0x61, 0x64, 0x69, 0x73, 0x6c, 0x61, 0x76, 0x20, 0x4c, 0x68, 0x6f,
|
||||
0x74, 0x6b, 0x61, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x6d, 0x61, 0x69, 0x6c,
|
||||
0x74, 0x6f, 0x3a, 0x6c, 0x68, 0x6f, 0x74, 0x6b, 0x61, 0x40, 0x6e, 0x69,
|
||||
0x63, 0x2e, 0x63, 0x7a, 0x3e, 0x22, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x64,
|
||||
0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x22, 0x54, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x6f, 0x64,
|
||||
0x75, 0x6c, 0x65, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x73, 0x20,
|
||||
0x61, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65,
|
||||
0x6e, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x20,
|
||||
0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72,
|
||||
0x61, 0x74, 0x65, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x6d, 0x6f, 0x64,
|
||||
0x65, 0x6c, 0x73, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20,
|
||||
0x69, 0x6e, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x59, 0x41, 0x4e,
|
||||
0x47, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x20, 0x69, 0x6e,
|
||||
0x20, 0x61, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x6f, 0x64, 0x75,
|
||||
0x6c, 0x65, 0x2e, 0x20, 0x20, 0x49, 0x74, 0x20, 0x61, 0x6c, 0x73, 0x6f,
|
||||
0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x6f, 0x70, 0x65,
|
||||
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x73, 0x74, 0x61,
|
||||
0x74, 0x65, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x74, 0x68, 0x61, 0x74,
|
||||
0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x79, 0x20, 0x74, 0x68, 0x65,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x6c,
|
||||
0x6c, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x20,
|
||||
0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20,
|
||||
0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x54, 0x68, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x77, 0x6f, 0x72,
|
||||
0x64, 0x73, 0x20, 0x27, 0x4d, 0x55, 0x53, 0x54, 0x27, 0x2c, 0x20, 0x27,
|
||||
0x4d, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x4f, 0x54, 0x27, 0x2c, 0x20, 0x27,
|
||||
0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x27, 0x2c, 0x20, 0x27,
|
||||
0x53, 0x48, 0x41, 0x4c, 0x4c, 0x27, 0x2c, 0x20, 0x27, 0x53, 0x48, 0x41,
|
||||
0x4c, 0x4c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x4f, 0x54, 0x27,
|
||||
0x2c, 0x20, 0x27, 0x53, 0x48, 0x4f, 0x55, 0x4c, 0x44, 0x27, 0x2c, 0x20,
|
||||
0x27, 0x53, 0x48, 0x4f, 0x55, 0x4c, 0x44, 0x20, 0x4e, 0x4f, 0x54, 0x27,
|
||||
0x2c, 0x20, 0x27, 0x52, 0x45, 0x43, 0x4f, 0x4d, 0x4d, 0x45, 0x4e, 0x44,
|
||||
0x45, 0x44, 0x27, 0x2c, 0x20, 0x27, 0x4e, 0x4f, 0x54, 0x20, 0x52, 0x45,
|
||||
0x43, 0x4f, 0x4d, 0x4d, 0x45, 0x4e, 0x44, 0x45, 0x44, 0x27, 0x2c, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x27, 0x4d, 0x41, 0x59, 0x27, 0x2c, 0x20,
|
||||
0x61, 0x6e, 0x64, 0x20, 0x27, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41,
|
||||
0x4c, 0x27, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x64,
|
||||
0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20,
|
||||
0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70,
|
||||
0x72, 0x65, 0x74, 0x65, 0x64, 0x20, 0x61, 0x73, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x20,
|
||||
0x69, 0x6e, 0x20, 0x42, 0x43, 0x50, 0x20, 0x31, 0x34, 0x20, 0x28, 0x52,
|
||||
0x46, 0x43, 0x20, 0x32, 0x31, 0x31, 0x39, 0x29, 0x20, 0x28, 0x52, 0x46,
|
||||
0x43, 0x20, 0x38, 0x31, 0x37, 0x34, 0x29, 0x20, 0x77, 0x68, 0x65, 0x6e,
|
||||
0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x77,
|
||||
0x68, 0x65, 0x6e, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68,
|
||||
0x65, 0x79, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x20, 0x69, 0x6e,
|
||||
0x20, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x61, 0x70, 0x69, 0x74, 0x61, 0x6c,
|
||||
0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x73, 0x68, 0x6f, 0x77, 0x6e, 0x20,
|
||||
0x68, 0x65, 0x72, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63,
|
||||
0x29, 0x20, 0x32, 0x30, 0x31, 0x39, 0x20, 0x49, 0x45, 0x54, 0x46, 0x20,
|
||||
0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x69, 0x64,
|
||||
0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x61, 0x73, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x73,
|
||||
0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x64, 0x65,
|
||||
0x2e, 0x20, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74,
|
||||
0x73, 0x20, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x2e, 0x0a,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65, 0x64, 0x69, 0x73, 0x74,
|
||||
0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6e, 0x64,
|
||||
0x20, 0x75, 0x73, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x6f, 0x75, 0x72,
|
||||
0x63, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x69, 0x6e, 0x61, 0x72,
|
||||
0x79, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2c, 0x20, 0x77, 0x69, 0x74,
|
||||
0x68, 0x20, 0x6f, 0x72, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69,
|
||||
0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69,
|
||||
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x69, 0x73, 0x20, 0x70,
|
||||
0x65, 0x72, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x20, 0x70, 0x75, 0x72,
|
||||
0x73, 0x75, 0x61, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x2c, 0x20, 0x61, 0x6e,
|
||||
0x64, 0x20, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x74, 0x6f,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69,
|
||||
0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20,
|
||||
0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e,
|
||||
0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69,
|
||||
0x66, 0x69, 0x65, 0x64, 0x20, 0x42, 0x53, 0x44, 0x20, 0x4c, 0x69, 0x63,
|
||||
0x65, 0x6e, 0x73, 0x65, 0x20, 0x73, 0x65, 0x74, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x69, 0x6e, 0x20, 0x53,
|
||||
0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x34, 0x2e, 0x63, 0x20, 0x6f,
|
||||
0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45, 0x54, 0x46, 0x20, 0x54,
|
||||
0x72, 0x75, 0x73, 0x74, 0x27, 0x73, 0x20, 0x4c, 0x65, 0x67, 0x61, 0x6c,
|
||||
0x20, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6e,
|
||||
0x67, 0x20, 0x74, 0x6f, 0x20, 0x49, 0x45, 0x54, 0x46, 0x20, 0x44, 0x6f,
|
||||
0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x74, 0x72,
|
||||
0x75, 0x73, 0x74, 0x65, 0x65, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x6f,
|
||||
0x72, 0x67, 0x2f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2d, 0x69,
|
||||
0x6e, 0x66, 0x6f, 0x29, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x54, 0x68, 0x69, 0x73, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x59, 0x41, 0x4e,
|
||||
0x47, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x69, 0x73, 0x20,
|
||||
0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x52, 0x46, 0x43, 0x20,
|
||||
0x38, 0x35, 0x32, 0x38, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73,
|
||||
0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x52, 0x46, 0x43, 0x20, 0x69,
|
||||
0x74, 0x73, 0x65, 0x6c, 0x66, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x66, 0x75,
|
||||
0x6c, 0x6c, 0x20, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20, 0x6e, 0x6f, 0x74,
|
||||
0x69, 0x63, 0x65, 0x73, 0x2e, 0x22, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x72,
|
||||
0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x32, 0x30, 0x31, 0x39,
|
||||
0x2d, 0x30, 0x31, 0x2d, 0x31, 0x34, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x49, 0x6e, 0x69, 0x74,
|
||||
0x69, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x66, 0x65,
|
||||
0x72, 0x65, 0x6e, 0x63, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x22, 0x52, 0x46, 0x43, 0x20, 0x38, 0x35, 0x32, 0x38, 0x3a, 0x20, 0x59,
|
||||
0x41, 0x4e, 0x47, 0x20, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x20, 0x4d,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a,
|
||||
0x20, 0x20, 0x2f, 0x2a, 0x0a, 0x20, 0x20, 0x20, 0x2a, 0x20, 0x45, 0x78,
|
||||
0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x2a, 0x2f, 0x0a, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x70, 0x6f,
|
||||
0x69, 0x6e, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x72,
|
||||
0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6c, 0x61, 0x62, 0x65, 0x6c,
|
||||
0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
|
||||
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x22, 0x54, 0x68, 0x65, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x20, 0x27, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x27, 0x20, 0x69, 0x73,
|
||||
0x20, 0x61, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x69, 0x64, 0x65, 0x6e,
|
||||
0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x2c, 0x20, 0x69, 0x2e, 0x65, 0x2e,
|
||||
0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74,
|
||||
0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x79,
|
||||
0x70, 0x65, 0x20, 0x27, 0x79, 0x61, 0x6e, 0x67, 0x3a, 0x79, 0x61, 0x6e,
|
||||
0x67, 0x2d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72,
|
||||
0x27, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54,
|
||||
0x68, 0x65, 0x20, 0x27, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x70, 0x6f,
|
||||
0x69, 0x6e, 0x74, 0x27, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65,
|
||||
0x6e, 0x74, 0x20, 0x4d, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x4f, 0x54, 0x20,
|
||||
0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x61,
|
||||
0x20, 0x59, 0x41, 0x4e, 0x47, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x31, 0x20, 0x6d,
|
||||
0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2c, 0x20, 0x6e, 0x65, 0x69, 0x74, 0x68,
|
||||
0x65, 0x72, 0x20, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x6c,
|
||||
0x79, 0x20, 0x6e, 0x6f, 0x72, 0x20, 0x76, 0x69, 0x61, 0x20, 0x61, 0x20,
|
||||
0x27, 0x75, 0x73, 0x65, 0x73, 0x27, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20,
|
||||
0x27, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||
0x27, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20,
|
||||
0x4d, 0x41, 0x59, 0x20, 0x62, 0x65, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65,
|
||||
0x6e, 0x74, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x73, 0x75, 0x62, 0x73,
|
||||
0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x63, 0x6f, 0x6e, 0x74,
|
||||
0x61, 0x69, 0x6e, 0x65, 0x72, 0x27, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x27,
|
||||
0x6c, 0x69, 0x73, 0x74, 0x27, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4d, 0x55,
|
||||
0x53, 0x54, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x62, 0x65, 0x20, 0x70, 0x72,
|
||||
0x65, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x77, 0x68,
|
||||
0x65, 0x72, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x54, 0x68, 0x65, 0x72, 0x65, 0x20, 0x4d, 0x55, 0x53, 0x54, 0x20, 0x4e,
|
||||
0x4f, 0x54, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x74,
|
||||
0x68, 0x61, 0x6e, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x27, 0x6d, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x2d, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x27, 0x20, 0x73, 0x74,
|
||||
0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x61,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x67, 0x69, 0x76, 0x65,
|
||||
0x6e, 0x20, 0x27, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
|
||||
0x27, 0x20, 0x6f, 0x72, 0x20, 0x27, 0x6c, 0x69, 0x73, 0x74, 0x27, 0x20,
|
||||
0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x49, 0x66, 0x20, 0x61, 0x20,
|
||||
0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x20,
|
||||
0x69, 0x73, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x77,
|
||||
0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x67, 0x72, 0x6f, 0x75,
|
||||
0x70, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x69, 0x74, 0x73, 0x20, 0x6c, 0x61,
|
||||
0x62, 0x65, 0x6c, 0x20, 0x69, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x77, 0x68,
|
||||
0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75,
|
||||
0x70, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64,
|
||||
0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x20,
|
||||
0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x20,
|
||||
0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x61, 0x20, 0x70, 0x6c,
|
||||
0x61, 0x63, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e,
|
||||
0x6f, 0x64, 0x65, 0x20, 0x68, 0x69, 0x65, 0x72, 0x61, 0x72, 0x63, 0x68,
|
||||
0x79, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x64, 0x61, 0x74,
|
||||
0x61, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x20, 0x6d, 0x61, 0x79,
|
||||
0x20, 0x62, 0x65, 0x20, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64,
|
||||
0x2e, 0x20, 0x20, 0x41, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20,
|
||||
0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65,
|
||||
0x6e, 0x74, 0x73, 0x20, 0x61, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68,
|
||||
0x20, 0x61, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x70, 0x6f, 0x69,
|
||||
0x6e, 0x74, 0x20, 0x70, 0x6f, 0x70, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x73,
|
||||
0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x27, 0x2f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2d, 0x6d, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x73, 0x2f, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x70, 0x6f,
|
||||
0x69, 0x6e, 0x74, 0x27, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x77, 0x69,
|
||||
0x74, 0x68, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20,
|
||||
0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
|
||||
0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x68,
|
||||
0x69, 0x63, 0x68, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x6d, 0x6f, 0x64,
|
||||
0x65, 0x6c, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6d, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x65, 0x64, 0x20, 0x61, 0x74, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20,
|
||||
0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e,
|
||||
0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x74,
|
||||
0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x27,
|
||||
0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x27,
|
||||
0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x64,
|
||||
0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x64, 0x65, 0x66, 0x69,
|
||||
0x6e, 0x65, 0x20, 0x61, 0x20, 0x6e, 0x65, 0x77, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x6e, 0x6f, 0x64,
|
||||
0x65, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20,
|
||||
0x2f, 0x2a, 0x0a, 0x20, 0x20, 0x20, 0x2a, 0x20, 0x53, 0x74, 0x61, 0x74,
|
||||
0x65, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x73,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x2a, 0x2f, 0x0a, 0x0a, 0x20, 0x20, 0x63, 0x6f,
|
||||
0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x20, 0x73, 0x63, 0x68, 0x65,
|
||||
0x6d, 0x61, 0x2d, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x20, 0x7b, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x20, 0x66,
|
||||
0x61, 0x6c, 0x73, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65,
|
||||
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
|
||||
0x73, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x20, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20,
|
||||
0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x20, 0x6f, 0x66,
|
||||
0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x6c, 0x6c,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x65, 0x64, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x6d, 0x6f, 0x64,
|
||||
0x65, 0x6c, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74,
|
||||
0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65,
|
||||
0x72, 0x76, 0x65, 0x72, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x6c, 0x69, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
|
||||
0x63, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6b,
|
||||
0x65, 0x79, 0x20, 0x22, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72,
|
||||
0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x22, 0x54, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x73,
|
||||
0x74, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x73, 0x20, 0x61,
|
||||
0x20, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20,
|
||||
0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x70, 0x72,
|
||||
0x65, 0x66, 0x69, 0x78, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
|
||||
0x61, 0x72, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x58, 0x50, 0x61,
|
||||
0x74, 0x68, 0x20, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x70, 0x61, 0x72, 0x65, 0x6e,
|
||||
0x74, 0x2d, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x27,
|
||||
0x20, 0x6c, 0x65, 0x61, 0x66, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68,
|
||||
0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63,
|
||||
0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67,
|
||||
0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x55,
|
||||
0x52, 0x49, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65,
|
||||
0x73, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c,
|
||||
0x65, 0x61, 0x66, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x7b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x79, 0x70,
|
||||
0x65, 0x20, 0x79, 0x61, 0x6e, 0x67, 0x3a, 0x79, 0x61, 0x6e, 0x67, 0x2d,
|
||||
0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x3b, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63,
|
||||
0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x4e, 0x61, 0x6d, 0x65, 0x73,
|
||||
0x70, 0x61, 0x63, 0x65, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x2e,
|
||||
0x22, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x20, 0x75, 0x72,
|
||||
0x69, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x74, 0x79, 0x70, 0x65, 0x20, 0x69, 0x6e, 0x65, 0x74, 0x3a, 0x75, 0x72,
|
||||
0x69, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64,
|
||||
0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x4e, 0x61,
|
||||
0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x55, 0x52, 0x49, 0x20,
|
||||
0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x2e, 0x22, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20,
|
||||
0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x20,
|
||||
0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6b, 0x65, 0x79, 0x20,
|
||||
0x22, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x6c, 0x61, 0x62, 0x65,
|
||||
0x6c, 0x22, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64,
|
||||
0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x45, 0x61, 0x63, 0x68,
|
||||
0x20, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
|
||||
0x69, 0x73, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63,
|
||||
0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x63, 0x68, 0x65,
|
||||
0x6d, 0x61, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x70, 0x61, 0x72,
|
||||
0x74, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x70,
|
||||
0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x45, 0x61, 0x63, 0x68, 0x20, 0x6d, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x20, 0x4d, 0x55, 0x53,
|
||||
0x54, 0x20, 0x62, 0x65, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64,
|
||||
0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x27,
|
||||
0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x27,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x78,
|
||||
0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x6f,
|
||||
0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f,
|
||||
0x64, 0x75, 0x6c, 0x65, 0x73, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x64,
|
||||
0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76,
|
||||
0x65, 0x72, 0x27, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61,
|
||||
0x72, 0x79, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20,
|
||||
0x77, 0x69, 0x74, 0x68, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x72, 0x6d,
|
||||
0x61, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x27, 0x69,
|
||||
0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x27, 0x2e, 0x22, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x20,
|
||||
0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x79, 0x61,
|
||||
0x6e, 0x67, 0x3a, 0x79, 0x61, 0x6e, 0x67, 0x2d, 0x69, 0x64, 0x65, 0x6e,
|
||||
0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x22, 0x4e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61,
|
||||
0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74,
|
||||
0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x22,
|
||||
0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x20, 0x6c, 0x61, 0x62,
|
||||
0x65, 0x6c, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x79, 0x61, 0x6e, 0x67, 0x3a, 0x79,
|
||||
0x61, 0x6e, 0x67, 0x2d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69,
|
||||
0x65, 0x72, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x4c,
|
||||
0x61, 0x62, 0x65, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
|
||||
0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x20,
|
||||
0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x75, 0x73, 0x69, 0x6e,
|
||||
0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x27, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x2d, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x27, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65,
|
||||
0x61, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x20, 0x7b, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x79, 0x70, 0x65,
|
||||
0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c,
|
||||
0x74, 0x20, 0x22, 0x74, 0x72, 0x75, 0x65, 0x22, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
|
||||
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x22, 0x49, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73,
|
||||
0x20, 0x6c, 0x65, 0x61, 0x66, 0x20, 0x69, 0x73, 0x20, 0x73, 0x65, 0x74,
|
||||
0x20, 0x74, 0x6f, 0x20, 0x27, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x27, 0x2c,
|
||||
0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x64, 0x61,
|
||||
0x74, 0x61, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20,
|
||||
0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x73,
|
||||
0x63, 0x68, 0x65, 0x6d, 0x61, 0x20, 0x61, 0x72, 0x65, 0x20, 0x72, 0x65,
|
||||
0x61, 0x64, 0x2d, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x28, 0x27, 0x63, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x27, 0x29,
|
||||
0x2c, 0x20, 0x72, 0x65, 0x67, 0x61, 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x27, 0x63, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x27, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72,
|
||||
0x74, 0x79, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x68, 0x6f, 0x69,
|
||||
0x63, 0x65, 0x20, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2d, 0x72, 0x65,
|
||||
0x66, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x6d, 0x61, 0x6e, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x20, 0x74, 0x72,
|
||||
0x75, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41,
|
||||
0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x73, 0x20,
|
||||
0x66, 0x6f, 0x72, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x79, 0x69,
|
||||
0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x63, 0x68, 0x65, 0x6d,
|
||||
0x61, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x20, 0x69,
|
||||
0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e,
|
||||
0x63, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x22, 0x41, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65,
|
||||
0x74, 0x65, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x63, 0x6f, 0x6e, 0x74,
|
||||
0x61, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61,
|
||||
0x20, 0x69, 0x73, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x64, 0x20,
|
||||
0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x22, 0x3b, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73,
|
||||
0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x54, 0x68,
|
||||
0x69, 0x73, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x64, 0x69,
|
||||
0x63, 0x61, 0x74, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x68, 0x61,
|
||||
0x73, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x61, 0x74,
|
||||
0x20, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20,
|
||||
0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x27, 0x69, 0x65, 0x74, 0x66,
|
||||
0x2d, 0x79, 0x61, 0x6e, 0x67, 0x2d, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72,
|
||||
0x79, 0x27, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2c, 0x20, 0x61,
|
||||
0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x69, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x73, 0x74,
|
||||
0x61, 0x6e, 0x74, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x72,
|
||||
0x6f, 0x76, 0x69, 0x64, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69,
|
||||
0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
|
||||
0x62, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61,
|
||||
0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x44, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e,
|
||||
0x74, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x20,
|
||||
0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x68,
|
||||
0x61, 0x76, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65,
|
||||
0x6e, 0x74, 0x20, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x20, 0x6d,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x65, 0x64, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65,
|
||||
0x72, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2d, 0x73, 0x63, 0x68,
|
||||
0x65, 0x6d, 0x61, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x22, 0x54, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x65,
|
||||
0x64, 0x20, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x20, 0x74, 0x6f, 0x67,
|
||||
0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x27, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x2d, 0x72,
|
||||
0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x27, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d,
|
||||
0x61, 0x6b, 0x65, 0x20, 0x75, 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
|
||||
0x63, 0x68, 0x65, 0x6d, 0x61, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68,
|
||||
0x69, 0x73, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x70, 0x6f, 0x69,
|
||||
0x6e, 0x74, 0x2e, 0x22, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x54, 0x68, 0x69, 0x73, 0x20, 0x6e,
|
||||
0x6f, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65,
|
||||
0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
|
||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x68, 0x61, 0x73, 0x20, 0x6d, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x61, 0x74, 0x20, 0x6c, 0x65, 0x61,
|
||||
0x73, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x64, 0x75,
|
||||
0x6c, 0x65, 0x20, 0x27, 0x69, 0x65, 0x74, 0x66, 0x2d, 0x79, 0x61, 0x6e,
|
||||
0x67, 0x2d, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x27, 0x20, 0x61,
|
||||
0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20,
|
||||
0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x69, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x69,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64,
|
||||
0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72,
|
||||
0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x62, 0x6f, 0x75, 0x74,
|
||||
0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x65,
|
||||
0x64, 0x20, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x20, 0x20, 0x57,
|
||||
0x68, 0x65, 0x6e, 0x20, 0x58, 0x50, 0x61, 0x74, 0x68, 0x20, 0x65, 0x78,
|
||||
0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x69, 0x6e,
|
||||
0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x64,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x20, 0x61, 0x72, 0x65,
|
||||
0x20, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x64, 0x2c, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x27, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x2d,
|
||||
0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x27, 0x20, 0x6c,
|
||||
0x65, 0x61, 0x66, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x73,
|
||||
0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20,
|
||||
0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x44,
|
||||
0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x73,
|
||||
0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x70, 0x6f, 0x69, 0x6e,
|
||||
0x74, 0x20, 0x4d, 0x55, 0x53, 0x54, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20,
|
||||
0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x73, 0x63,
|
||||
0x68, 0x65, 0x6d, 0x61, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x64,
|
||||
0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x20,
|
||||
0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x2d, 0x72, 0x65, 0x66, 0x65, 0x72,
|
||||
0x65, 0x6e, 0x63, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20,
|
||||
0x79, 0x61, 0x6e, 0x67, 0x3a, 0x78, 0x70, 0x61, 0x74, 0x68, 0x31, 0x2e,
|
||||
0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65,
|
||||
0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x65,
|
||||
0x61, 0x66, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20,
|
||||
0x58, 0x50, 0x61, 0x74, 0x68, 0x20, 0x31, 0x2e, 0x30, 0x20, 0x65, 0x78,
|
||||
0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x65, 0x76,
|
||||
0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67,
|
||||
0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x3a, 0x0a, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x2d, 0x20, 0x54, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74,
|
||||
0x65, 0x78, 0x74, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x73, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x64,
|
||||
0x61, 0x74, 0x61, 0x20, 0x74, 0x72, 0x65, 0x65, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
|
||||
0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x20,
|
||||
0x69, 0x73, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x0a,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x54, 0x68, 0x65, 0x20, 0x61, 0x63,
|
||||
0x63, 0x65, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x72, 0x65,
|
||||
0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x61, 0x72,
|
||||
0x65, 0x6e, 0x74, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x74, 0x72, 0x65,
|
||||
0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2a, 0x77, 0x69, 0x74, 0x68,
|
||||
0x6f, 0x75, 0x74, 0x2a, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6e, 0x6f, 0x64,
|
||||
0x65, 0x73, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x69,
|
||||
0x6e, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x20, 0x74, 0x68,
|
||||
0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x73, 0x69,
|
||||
0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x61, 0x72, 0x65, 0x6e,
|
||||
0x74, 0x20, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x0a, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x2d, 0x20, 0x54, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74,
|
||||
0x65, 0x78, 0x74, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
|
||||
0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x62, 0x6f,
|
||||
0x74, 0x68, 0x20, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x74, 0x6f, 0x20, 0x31, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x2d, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x66,
|
||||
0x20, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x62, 0x69,
|
||||
0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x69, 0x73, 0x20, 0x65, 0x6d,
|
||||
0x70, 0x74, 0x79, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x54,
|
||||
0x68, 0x65, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20,
|
||||
0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x69, 0x73, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x66, 0x75, 0x6e, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65,
|
||||
0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x57, 0x33, 0x43,
|
||||
0x20, 0x58, 0x50, 0x61, 0x74, 0x68, 0x20, 0x31, 0x2e, 0x30, 0x20, 0x64,
|
||||
0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77,
|
||||
0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x54, 0x52, 0x2f, 0x31,
|
||||
0x39, 0x39, 0x39, 0x2f, 0x52, 0x45, 0x43, 0x2d, 0x78, 0x70, 0x61, 0x74,
|
||||
0x68, 0x2d, 0x31, 0x39, 0x39, 0x39, 0x31, 0x31, 0x31, 0x36, 0x29, 0x20,
|
||||
0x61, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65,
|
||||
0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x64,
|
||||
0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x53, 0x65,
|
||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x31, 0x30, 0x20, 0x6f, 0x66, 0x20,
|
||||
0x52, 0x46, 0x43, 0x20, 0x37, 0x39, 0x35, 0x30, 0x2e, 0x0a, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x2d, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x65, 0x74, 0x20,
|
||||
0x6f, 0x66, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
|
||||
0x20, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x73, 0x20, 0x69, 0x73, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64,
|
||||
0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x27, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x27,
|
||||
0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20,
|
||||
0x27, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2d, 0x6d, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x73, 0x27, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x45, 0x61, 0x63,
|
||||
0x68, 0x20, 0x58, 0x50, 0x61, 0x74, 0x68, 0x20, 0x65, 0x78, 0x70, 0x72,
|
||||
0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x4d, 0x55, 0x53, 0x54, 0x20,
|
||||
0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20,
|
||||
0x61, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x2d, 0x73, 0x65, 0x74, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x28, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x79, 0x20,
|
||||
0x65, 0x6d, 0x70, 0x74, 0x79, 0x29, 0x2e, 0x20, 0x20, 0x46, 0x6f, 0x72,
|
||||
0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x72, 0x70, 0x6f, 0x73, 0x65,
|
||||
0x73, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74,
|
||||
0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x58, 0x50, 0x61, 0x74, 0x68,
|
||||
0x20, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73,
|
||||
0x20, 0x77, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65,
|
||||
0x78, 0x74, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65,
|
||||
0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x65, 0x64, 0x20, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2c, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20,
|
||||
0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x6e, 0x6f,
|
||||
0x64, 0x65, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74,
|
||||
0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68,
|
||||
0x20, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x20, 0x6e, 0x6f,
|
||||
0x64, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x65,
|
||||
0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x64,
|
||||
0x61, 0x74, 0x61, 0x20, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x0a, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x4e, 0x6f, 0x74, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
|
||||
0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20,
|
||||
0x27, 0x69, 0x65, 0x74, 0x66, 0x2d, 0x79, 0x61, 0x6e, 0x67, 0x2d, 0x73,
|
||||
0x63, 0x68, 0x65, 0x6d, 0x61, 0x2d, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x27,
|
||||
0x20, 0x69, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6c,
|
||||
0x66, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x61,
|
||||
0x20, 0x27, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x2d, 0x72, 0x65, 0x66,
|
||||
0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x27, 0x20, 0x69, 0x6e, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x64, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x6d, 0x61, 0x79,
|
||||
0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x6e, 0x6f,
|
||||
0x64, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x72,
|
||||
0x65, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x69, 0x6e,
|
||||
0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x63,
|
||||
0x63, 0x65, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x72, 0x65,
|
||||
0x65, 0x20, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x61, 0x20,
|
||||
0x27, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x2d, 0x72, 0x65, 0x66, 0x65,
|
||||
0x72, 0x65, 0x6e, 0x63, 0x65, 0x27, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
|
||||
0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x20,
|
||||
0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20,
|
||||
0x7d, 0x0a, 0x7d, 0x0a, 0x00
|
||||
};
|
224
models/ietf-yang-schema-mount@2019-01-14.yang
Normal file
224
models/ietf-yang-schema-mount@2019-01-14.yang
Normal file
|
@ -0,0 +1,224 @@
|
|||
module ietf-yang-schema-mount {
|
||||
yang-version 1.1;
|
||||
namespace "urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount";
|
||||
prefix yangmnt;
|
||||
|
||||
import ietf-inet-types {
|
||||
prefix inet;
|
||||
reference
|
||||
"RFC 6991: Common YANG Data Types";
|
||||
}
|
||||
|
||||
import ietf-yang-types {
|
||||
prefix yang;
|
||||
reference
|
||||
"RFC 6991: Common YANG Data Types";
|
||||
}
|
||||
|
||||
organization
|
||||
"IETF NETMOD (NETCONF Data Modeling Language) Working Group";
|
||||
|
||||
contact
|
||||
"WG Web: <https://datatracker.ietf.org/wg/netmod/>
|
||||
WG List: <mailto:netmod@ietf.org>
|
||||
|
||||
Editor: Martin Bjorklund
|
||||
<mailto:mbj@tail-f.com>
|
||||
|
||||
Editor: Ladislav Lhotka
|
||||
<mailto:lhotka@nic.cz>";
|
||||
|
||||
description
|
||||
"This module defines a YANG extension statement that can be used
|
||||
to incorporate data models defined in other YANG modules in a
|
||||
module. It also defines operational state data that specify the
|
||||
overall structure of the data model.
|
||||
|
||||
The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL
|
||||
NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED',
|
||||
'MAY', and 'OPTIONAL' in this document are to be interpreted as
|
||||
described in BCP 14 (RFC 2119) (RFC 8174) when, and only when,
|
||||
they appear in all capitals, as shown here.
|
||||
|
||||
Copyright (c) 2019 IETF Trust and the persons identified as
|
||||
authors of the code. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, is permitted pursuant to, and subject to
|
||||
the license terms contained in, the Simplified BSD License set
|
||||
forth in Section 4.c of the IETF Trust's Legal Provisions
|
||||
Relating to IETF Documents
|
||||
(https://trustee.ietf.org/license-info).
|
||||
|
||||
This version of this YANG module is part of RFC 8528;
|
||||
see the RFC itself for full legal notices.";
|
||||
|
||||
revision 2019-01-14 {
|
||||
description
|
||||
"Initial revision.";
|
||||
reference
|
||||
"RFC 8528: YANG Schema Mount";
|
||||
}
|
||||
|
||||
/*
|
||||
* Extensions
|
||||
*/
|
||||
|
||||
extension mount-point {
|
||||
argument label;
|
||||
description
|
||||
"The argument 'label' is a YANG identifier, i.e., it is of the
|
||||
type 'yang:yang-identifier'.
|
||||
|
||||
The 'mount-point' statement MUST NOT be used in a YANG
|
||||
version 1 module, neither explicitly nor via a 'uses'
|
||||
statement.
|
||||
The 'mount-point' statement MAY be present as a substatement
|
||||
of 'container' and 'list' and MUST NOT be present elsewhere.
|
||||
There MUST NOT be more than one 'mount-point' statement in a
|
||||
given 'container' or 'list' statement.
|
||||
|
||||
If a mount point is defined within a grouping, its label is
|
||||
bound to the module where the grouping is used.
|
||||
|
||||
A mount point defines a place in the node hierarchy where
|
||||
other data models may be attached. A server that implements a
|
||||
module with a mount point populates the
|
||||
'/schema-mounts/mount-point' list with detailed information on
|
||||
which data models are mounted at each mount point.
|
||||
|
||||
Note that the 'mount-point' statement does not define a new
|
||||
data node.";
|
||||
}
|
||||
|
||||
/*
|
||||
* State data nodes
|
||||
*/
|
||||
|
||||
container schema-mounts {
|
||||
config false;
|
||||
description
|
||||
"Contains information about the structure of the overall
|
||||
mounted data model implemented in the server.";
|
||||
list namespace {
|
||||
key "prefix";
|
||||
description
|
||||
"This list provides a mapping of namespace prefixes that are
|
||||
used in XPath expressions of 'parent-reference' leafs to the
|
||||
corresponding namespace URI references.";
|
||||
leaf prefix {
|
||||
type yang:yang-identifier;
|
||||
description
|
||||
"Namespace prefix.";
|
||||
}
|
||||
leaf uri {
|
||||
type inet:uri;
|
||||
description
|
||||
"Namespace URI reference.";
|
||||
}
|
||||
}
|
||||
list mount-point {
|
||||
key "module label";
|
||||
|
||||
description
|
||||
"Each entry of this list specifies a schema for a particular
|
||||
mount point.
|
||||
|
||||
Each mount point MUST be defined using the 'mount-point'
|
||||
extension in one of the modules listed in the server's
|
||||
YANG library instance with conformance type 'implement'.";
|
||||
leaf module {
|
||||
type yang:yang-identifier;
|
||||
description
|
||||
"Name of a module containing the mount point.";
|
||||
}
|
||||
leaf label {
|
||||
type yang:yang-identifier;
|
||||
description
|
||||
"Label of the mount point defined using the 'mount-point'
|
||||
extension.";
|
||||
}
|
||||
leaf config {
|
||||
type boolean;
|
||||
default "true";
|
||||
description
|
||||
"If this leaf is set to 'false', then all data nodes in the
|
||||
mounted schema are read-only ('config false'), regardless
|
||||
of their 'config' property.";
|
||||
}
|
||||
choice schema-ref {
|
||||
mandatory true;
|
||||
description
|
||||
"Alternatives for specifying the schema.";
|
||||
container inline {
|
||||
presence
|
||||
"A complete self-contained schema is mounted at the
|
||||
mount point.";
|
||||
description
|
||||
"This node indicates that the server has mounted at least
|
||||
the module 'ietf-yang-library' at the mount point, and
|
||||
its instantiation provides the information about the
|
||||
mounted schema.
|
||||
|
||||
Different instances of the mount point may have
|
||||
different schemas mounted.";
|
||||
}
|
||||
container shared-schema {
|
||||
presence
|
||||
"The mounted schema together with the 'parent-reference'
|
||||
make up the schema for this mount point.";
|
||||
|
||||
description
|
||||
"This node indicates that the server has mounted at least
|
||||
the module 'ietf-yang-library' at the mount point, and
|
||||
its instantiation provides the information about the
|
||||
mounted schema. When XPath expressions in the mounted
|
||||
schema are evaluated, the 'parent-reference' leaf-list
|
||||
is taken into account.
|
||||
|
||||
Different instances of the mount point MUST have the
|
||||
same schema mounted.";
|
||||
leaf-list parent-reference {
|
||||
type yang:xpath1.0;
|
||||
description
|
||||
"Entries of this leaf-list are XPath 1.0 expressions
|
||||
that are evaluated in the following context:
|
||||
|
||||
- The context node is the node in the parent data tree
|
||||
where the mount-point is defined.
|
||||
|
||||
- The accessible tree is the parent data tree
|
||||
*without* any nodes defined in modules that are
|
||||
mounted inside the parent schema.
|
||||
|
||||
- The context position and context size are both equal
|
||||
to 1.
|
||||
|
||||
- The set of variable bindings is empty.
|
||||
|
||||
- The function library is the core function library
|
||||
defined in the W3C XPath 1.0 document
|
||||
(http://www.w3.org/TR/1999/REC-xpath-19991116) and
|
||||
the functions defined in Section 10 of RFC 7950.
|
||||
|
||||
- The set of namespace declarations is defined by the
|
||||
'namespace' list under 'schema-mounts'.
|
||||
|
||||
Each XPath expression MUST evaluate to a node-set
|
||||
(possibly empty). For the purposes of evaluating
|
||||
XPath expressions whose context nodes are defined in
|
||||
the mounted schema, the union of all these node-sets
|
||||
together with ancestor nodes are added to the
|
||||
accessible data tree.
|
||||
|
||||
Note that in the case 'ietf-yang-schema-mount' is
|
||||
itself mounted, a 'parent-reference' in the mounted
|
||||
module may refer to nodes that were brought into the
|
||||
accessible tree through a 'parent-reference' in the
|
||||
parent schema.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
635
models/ietf-yang-structure-ext@2020-06-17.h
Normal file
635
models/ietf-yang-structure-ext@2020-06-17.h
Normal file
|
@ -0,0 +1,635 @@
|
|||
char ietf_yang_structure_ext_2020_06_17_yang[] = {
|
||||
0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x69, 0x65, 0x74, 0x66, 0x2d,
|
||||
0x79, 0x61, 0x6e, 0x67, 0x2d, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75,
|
||||
0x72, 0x65, 0x2d, 0x65, 0x78, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x79,
|
||||
0x61, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20,
|
||||
0x31, 0x2e, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73,
|
||||
0x70, 0x61, 0x63, 0x65, 0x20, 0x22, 0x75, 0x72, 0x6e, 0x3a, 0x69, 0x65,
|
||||
0x74, 0x66, 0x3a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3a, 0x78, 0x6d,
|
||||
0x6c, 0x3a, 0x6e, 0x73, 0x3a, 0x79, 0x61, 0x6e, 0x67, 0x3a, 0x69, 0x65,
|
||||
0x74, 0x66, 0x2d, 0x79, 0x61, 0x6e, 0x67, 0x2d, 0x73, 0x74, 0x72, 0x75,
|
||||
0x63, 0x74, 0x75, 0x72, 0x65, 0x2d, 0x65, 0x78, 0x74, 0x22, 0x3b, 0x0a,
|
||||
0x20, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x73, 0x78, 0x3b,
|
||||
0x0a, 0x0a, 0x20, 0x20, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x49, 0x45,
|
||||
0x54, 0x46, 0x20, 0x4e, 0x45, 0x54, 0x4d, 0x4f, 0x44, 0x20, 0x28, 0x4e,
|
||||
0x45, 0x54, 0x43, 0x4f, 0x4e, 0x46, 0x20, 0x44, 0x61, 0x74, 0x61, 0x20,
|
||||
0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x6e,
|
||||
0x67, 0x75, 0x61, 0x67, 0x65, 0x29, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x69,
|
||||
0x6e, 0x67, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x3b, 0x0a, 0x20,
|
||||
0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x22, 0x57, 0x47, 0x20, 0x57, 0x65, 0x62, 0x3a, 0x20, 0x20, 0x20,
|
||||
0x3c, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x64, 0x61, 0x74,
|
||||
0x61, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x69, 0x65, 0x74,
|
||||
0x66, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x77, 0x67, 0x2f, 0x6e, 0x65, 0x74,
|
||||
0x6d, 0x6f, 0x64, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x57,
|
||||
0x47, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x3a, 0x20, 0x20, 0x3c, 0x6d, 0x61,
|
||||
0x69, 0x6c, 0x74, 0x6f, 0x3a, 0x6e, 0x65, 0x74, 0x6d, 0x6f, 0x64, 0x40,
|
||||
0x69, 0x65, 0x74, 0x66, 0x2e, 0x6f, 0x72, 0x67, 0x3e, 0x0a, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x3a, 0x20,
|
||||
0x20, 0x20, 0x41, 0x6e, 0x64, 0x79, 0x20, 0x42, 0x69, 0x65, 0x72, 0x6d,
|
||||
0x61, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x6d, 0x61, 0x69, 0x6c, 0x74,
|
||||
0x6f, 0x3a, 0x61, 0x6e, 0x64, 0x79, 0x40, 0x79, 0x75, 0x6d, 0x61, 0x77,
|
||||
0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x3e, 0x0a, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x3a, 0x20,
|
||||
0x20, 0x20, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x20, 0x42, 0x6a, 0x6f,
|
||||
0x72, 0x6b, 0x6c, 0x75, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x6d,
|
||||
0x61, 0x69, 0x6c, 0x74, 0x6f, 0x3a, 0x6d, 0x62, 0x6a, 0x2b, 0x69, 0x65,
|
||||
0x74, 0x66, 0x40, 0x34, 0x36, 0x36, 0x38, 0x2e, 0x73, 0x65, 0x3e, 0x0a,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
|
||||
0x3a, 0x20, 0x20, 0x20, 0x4b, 0x65, 0x6e, 0x74, 0x20, 0x57, 0x61, 0x74,
|
||||
0x73, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x6d, 0x61, 0x69, 0x6c,
|
||||
0x74, 0x6f, 0x3a, 0x6b, 0x65, 0x6e, 0x74, 0x2b, 0x69, 0x65, 0x74, 0x66,
|
||||
0x40, 0x77, 0x61, 0x74, 0x73, 0x65, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x3e,
|
||||
0x22, 0x3b, 0x0a, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x54, 0x68,
|
||||
0x69, 0x73, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x63, 0x6f,
|
||||
0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65,
|
||||
0x70, 0x74, 0x75, 0x61, 0x6c, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x73,
|
||||
0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69,
|
||||
0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x62, 0x73, 0x74,
|
||||
0x72, 0x61, 0x63, 0x74, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x73, 0x74,
|
||||
0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20,
|
||||
0x77, 0x6f, 0x72, 0x64, 0x73, 0x20, 0x27, 0x4d, 0x55, 0x53, 0x54, 0x27,
|
||||
0x2c, 0x20, 0x27, 0x4d, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x4f, 0x54, 0x27,
|
||||
0x2c, 0x20, 0x27, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x27,
|
||||
0x2c, 0x20, 0x27, 0x53, 0x48, 0x41, 0x4c, 0x4c, 0x27, 0x2c, 0x20, 0x27,
|
||||
0x53, 0x48, 0x41, 0x4c, 0x4c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e,
|
||||
0x4f, 0x54, 0x27, 0x2c, 0x20, 0x27, 0x53, 0x48, 0x4f, 0x55, 0x4c, 0x44,
|
||||
0x27, 0x2c, 0x20, 0x27, 0x53, 0x48, 0x4f, 0x55, 0x4c, 0x44, 0x20, 0x4e,
|
||||
0x4f, 0x54, 0x27, 0x2c, 0x20, 0x27, 0x52, 0x45, 0x43, 0x4f, 0x4d, 0x4d,
|
||||
0x45, 0x4e, 0x44, 0x45, 0x44, 0x27, 0x2c, 0x20, 0x27, 0x4e, 0x4f, 0x54,
|
||||
0x20, 0x52, 0x45, 0x43, 0x4f, 0x4d, 0x4d, 0x45, 0x4e, 0x44, 0x45, 0x44,
|
||||
0x27, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x27, 0x4d, 0x41, 0x59,
|
||||
0x27, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x27, 0x4f, 0x50, 0x54, 0x49,
|
||||
0x4f, 0x4e, 0x41, 0x4c, 0x27, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69,
|
||||
0x73, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x61,
|
||||
0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x69, 0x6e, 0x74,
|
||||
0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x20, 0x61, 0x73, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62,
|
||||
0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x42, 0x43, 0x50, 0x20, 0x31, 0x34,
|
||||
0x20, 0x28, 0x52, 0x46, 0x43, 0x20, 0x32, 0x31, 0x31, 0x39, 0x29, 0x20,
|
||||
0x28, 0x52, 0x46, 0x43, 0x20, 0x38, 0x31, 0x37, 0x34, 0x29, 0x20, 0x77,
|
||||
0x68, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x6c,
|
||||
0x79, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72,
|
||||
0x20, 0x69, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x61, 0x70, 0x69,
|
||||
0x74, 0x61, 0x6c, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x73, 0x68, 0x6f,
|
||||
0x77, 0x6e, 0x20, 0x68, 0x65, 0x72, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74,
|
||||
0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x32, 0x30, 0x20, 0x49, 0x45,
|
||||
0x54, 0x46, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x61, 0x6e, 0x64,
|
||||
0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x73,
|
||||
0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20,
|
||||
0x61, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x75, 0x74, 0x68,
|
||||
0x6f, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
|
||||
0x6f, 0x64, 0x65, 0x2e, 0x20, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x72, 0x69,
|
||||
0x67, 0x68, 0x74, 0x73, 0x20, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65,
|
||||
0x64, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65, 0x64,
|
||||
0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x20,
|
||||
0x61, 0x6e, 0x64, 0x20, 0x75, 0x73, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x73,
|
||||
0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x69,
|
||||
0x6e, 0x61, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2c, 0x20,
|
||||
0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x72, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x6d, 0x6f, 0x64,
|
||||
0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x69,
|
||||
0x73, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x20,
|
||||
0x70, 0x75, 0x72, 0x73, 0x75, 0x61, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x2c,
|
||||
0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74,
|
||||
0x20, 0x74, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65,
|
||||
0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x65, 0x72,
|
||||
0x6d, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x64,
|
||||
0x20, 0x69, 0x6e, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x69, 0x6d,
|
||||
0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x42, 0x53, 0x44, 0x20,
|
||||
0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x73, 0x65, 0x74, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x69,
|
||||
0x6e, 0x20, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x34, 0x2e,
|
||||
0x63, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45, 0x54,
|
||||
0x46, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x27, 0x73, 0x20, 0x4c, 0x65,
|
||||
0x67, 0x61, 0x6c, 0x20, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65, 0x6c, 0x61,
|
||||
0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x49, 0x45, 0x54, 0x46,
|
||||
0x20, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
|
||||
0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, 0x2e, 0x69, 0x65, 0x74, 0x66,
|
||||
0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65,
|
||||
0x2d, 0x69, 0x6e, 0x66, 0x6f, 0x29, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x59,
|
||||
0x41, 0x4e, 0x47, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x69,
|
||||
0x73, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x52, 0x46,
|
||||
0x43, 0x20, 0x38, 0x37, 0x39, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x28, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77,
|
||||
0x2e, 0x72, 0x66, 0x63, 0x2d, 0x65, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e,
|
||||
0x6f, 0x72, 0x67, 0x2f, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x72, 0x66, 0x63,
|
||||
0x38, 0x37, 0x39, 0x31, 0x29, 0x3b, 0x20, 0x73, 0x65, 0x65, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x52, 0x46, 0x43, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6c,
|
||||
0x66, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x66,
|
||||
0x75, 0x6c, 0x6c, 0x20, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20, 0x6e, 0x6f,
|
||||
0x74, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x22, 0x3b, 0x0a, 0x0a, 0x20, 0x20,
|
||||
0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x32, 0x30, 0x32,
|
||||
0x30, 0x2d, 0x30, 0x36, 0x2d, 0x31, 0x37, 0x20, 0x7b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x49, 0x6e, 0x69,
|
||||
0x74, 0x69, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x66,
|
||||
0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x22, 0x52, 0x46, 0x43, 0x20, 0x38, 0x37, 0x39, 0x31, 0x3a, 0x20,
|
||||
0x59, 0x41, 0x4e, 0x47, 0x20, 0x44, 0x61, 0x74, 0x61, 0x20, 0x53, 0x74,
|
||||
0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x20, 0x45, 0x78, 0x74, 0x65,
|
||||
0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65,
|
||||
0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d,
|
||||
0x65, 0x6e, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x7b, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x79, 0x69, 0x6e, 0x2d, 0x65, 0x6c, 0x65,
|
||||
0x6d, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x72, 0x75, 0x65, 0x3b, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73,
|
||||
0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x22, 0x54, 0x68, 0x69, 0x73, 0x20, 0x65, 0x78, 0x74,
|
||||
0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73,
|
||||
0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66,
|
||||
0x79, 0x20, 0x61, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x64, 0x61, 0x74,
|
||||
0x61, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x20,
|
||||
0x74, 0x68, 0x61, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x63,
|
||||
0x6f, 0x6e, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x20, 0x64, 0x61,
|
||||
0x74, 0x61, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x69,
|
||||
0x6e, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x2e, 0x20, 0x20, 0x49, 0x74, 0x20,
|
||||
0x69, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20,
|
||||
0x74, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65,
|
||||
0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x20, 0x68, 0x69, 0x65, 0x72, 0x61,
|
||||
0x72, 0x63, 0x68, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x61, 0x74, 0x61,
|
||||
0x20, 0x69, 0x6e, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74,
|
||||
0x20, 0x6f, 0x66, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
|
||||
0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x20, 0x6f, 0x72, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69,
|
||||
0x66, 0x69, 0x63, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20,
|
||||
0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72,
|
||||
0x6d, 0x61, 0x74, 0x2e, 0x20, 0x20, 0x44, 0x61, 0x74, 0x61, 0x20, 0x64,
|
||||
0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x74,
|
||||
0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x61,
|
||||
0x20, 0x27, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x27,
|
||||
0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x73,
|
||||
0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x70, 0x65,
|
||||
0x63, 0x69, 0x66, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e,
|
||||
0x65, 0x72, 0x69, 0x63, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20,
|
||||
0x59, 0x41, 0x4e, 0x47, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x73, 0x74,
|
||||
0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x77, 0x68, 0x6f,
|
||||
0x73, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74,
|
||||
0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x72,
|
||||
0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x27, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65,
|
||||
0x27, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20,
|
||||
0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x74, 0x65, 0x20,
|
||||
0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x65, 0x78,
|
||||
0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x64, 0x6f, 0x65, 0x73,
|
||||
0x20, 0x6e, 0x6f, 0x74, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20,
|
||||
0x61, 0x20, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x74, 0x79, 0x70, 0x65,
|
||||
0x2e, 0x20, 0x20, 0x41, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x73,
|
||||
0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x4d,
|
||||
0x55, 0x53, 0x54, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x79, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64,
|
||||
0x69, 0x6e, 0x67, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2c, 0x20, 0x69,
|
||||
0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65,
|
||||
0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x65, 0x64,
|
||||
0x69, 0x61, 0x20, 0x74, 0x79, 0x70, 0x65, 0x2c, 0x20, 0x69, 0x66, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69,
|
||||
0x63, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x64, 0x61,
|
||||
0x74, 0x6f, 0x72, 0x79, 0x20, 0x27, 0x6e, 0x61, 0x6d, 0x65, 0x27, 0x20,
|
||||
0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x20, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69,
|
||||
0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x20,
|
||||
0x64, 0x61, 0x74, 0x61, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74, 0x68,
|
||||
0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x62, 0x65, 0x69, 0x6e, 0x67, 0x20,
|
||||
0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x65, 0x78,
|
||||
0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x6f,
|
||||
0x6e, 0x6c, 0x79, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x61, 0x73,
|
||||
0x20, 0x61, 0x20, 0x74, 0x6f, 0x70, 0x2d, 0x6c, 0x65, 0x76, 0x65, 0x6c,
|
||||
0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20,
|
||||
0x69, 0x2e, 0x65, 0x2e, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20,
|
||||
0x73, 0x75, 0x62, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
|
||||
0x20, 0x74, 0x6f, 0x20, 0x27, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x27,
|
||||
0x20, 0x6f, 0x72, 0x20, 0x27, 0x73, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75,
|
||||
0x6c, 0x65, 0x27, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x75, 0x62, 0x73, 0x74, 0x61, 0x74,
|
||||
0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
|
||||
0x69, 0x73, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x20, 0x4d, 0x55, 0x53, 0x54, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77,
|
||||
0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x42, 0x4e, 0x46, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x20, 0x62,
|
||||
0x65, 0x6c, 0x6f, 0x77, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x20, 0x61, 0x72,
|
||||
0x65, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e,
|
||||
0x20, 0x52, 0x46, 0x43, 0x20, 0x37, 0x39, 0x35, 0x30, 0x3a, 0x0a, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2a,
|
||||
0x6d, 0x75, 0x73, 0x74, 0x2d, 0x73, 0x74, 0x6d, 0x74, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x73, 0x74,
|
||||
0x61, 0x74, 0x75, 0x73, 0x2d, 0x73, 0x74, 0x6d, 0x74, 0x5d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x64,
|
||||
0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73,
|
||||
0x74, 0x6d, 0x74, 0x5d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x5b, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e,
|
||||
0x63, 0x65, 0x2d, 0x73, 0x74, 0x6d, 0x74, 0x5d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2a, 0x28, 0x74, 0x79,
|
||||
0x70, 0x65, 0x64, 0x65, 0x66, 0x2d, 0x73, 0x74, 0x6d, 0x74, 0x20, 0x2f,
|
||||
0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x6e, 0x67, 0x2d, 0x73, 0x74,
|
||||
0x6d, 0x74, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x2a, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x64, 0x65, 0x66,
|
||||
0x2d, 0x73, 0x74, 0x6d, 0x74, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x41, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x64, 0x61, 0x74,
|
||||
0x61, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x20,
|
||||
0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68,
|
||||
0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x20, 0x69, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x77, 0x61, 0x79, 0x20,
|
||||
0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x27, 0x61, 0x6e, 0x79, 0x64, 0x61,
|
||||
0x74, 0x61, 0x27, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x20, 0x20, 0x54,
|
||||
0x68, 0x69, 0x73, 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x73, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x20,
|
||||
0x69, 0x73, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, 0x61,
|
||||
0x73, 0x20, 0x61, 0x20, 0x27, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
|
||||
0x65, 0x72, 0x27, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x73,
|
||||
0x74, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x74, 0x65, 0x64, 0x20, 0x63, 0x68,
|
||||
0x69, 0x6c, 0x64, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x73, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, 0x61,
|
||||
0x73, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x64, 0x65,
|
||||
0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x6f, 0x20,
|
||||
0x74, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x0a, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x6d,
|
||||
0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x61,
|
||||
0x6e, 0x64, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
|
||||
0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x6d, 0x6f, 0x64, 0x75,
|
||||
0x6c, 0x65, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x74, 0x65,
|
||||
0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d,
|
||||
0x65, 0x6e, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x73, 0x73, 0x69,
|
||||
0x67, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x61, 0x63, 0x68,
|
||||
0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x74, 0x61,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x66, 0x69,
|
||||
0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65,
|
||||
0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74,
|
||||
0x69, 0x6e, 0x67, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
|
||||
0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x73,
|
||||
0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x0a, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x58, 0x50,
|
||||
0x61, 0x74, 0x68, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74,
|
||||
0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x73, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20,
|
||||
0x69, 0x74, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x74, 0x68, 0x61, 0x74,
|
||||
0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x6e,
|
||||
0x6f, 0x64, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
|
||||
0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x65, 0x6c, 0x65,
|
||||
0x6d, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x72, 0x65, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e,
|
||||
0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
|
||||
0x61, 0x74, 0x61, 0x2d, 0x64, 0x65, 0x66, 0x2d, 0x73, 0x74, 0x6d, 0x74,
|
||||
0x20, 0x73, 0x75, 0x62, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68,
|
||||
0x69, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x78,
|
||||
0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x20, 0x54, 0x68,
|
||||
0x69, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61,
|
||||
0x6c, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69,
|
||||
0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78,
|
||||
0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69,
|
||||
0x6e, 0x67, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x73, 0x74, 0x61, 0x74,
|
||||
0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x6d, 0x75,
|
||||
0x73, 0x74, 0x2d, 0x73, 0x74, 0x6d, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x77, 0x68, 0x65,
|
||||
0x6e, 0x2d, 0x73, 0x74, 0x6d, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x70, 0x61, 0x74, 0x68,
|
||||
0x2d, 0x73, 0x74, 0x6d, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x6d, 0x69, 0x6e, 0x2d, 0x65,
|
||||
0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2d, 0x73, 0x74, 0x6d, 0x74,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x2d, 0x20, 0x6d, 0x61, 0x78, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x73, 0x2d, 0x73, 0x74, 0x6d, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x6d, 0x61, 0x6e,
|
||||
0x64, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2d, 0x73, 0x74, 0x6d, 0x74, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d,
|
||||
0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x2d, 0x73, 0x74, 0x6d, 0x74,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x2d, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x65, 0x64, 0x2d, 0x62, 0x79,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x2d, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x2d, 0x69,
|
||||
0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x20, 0x64, 0x61,
|
||||
0x74, 0x61, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c,
|
||||
0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x64,
|
||||
0x65, 0x66, 0x2d, 0x73, 0x74, 0x6d, 0x74, 0x20, 0x73, 0x75, 0x62, 0x73,
|
||||
0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x61, 0x72,
|
||||
0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x65,
|
||||
0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x68, 0x65,
|
||||
0x6e, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69,
|
||||
0x6e, 0x20, 0x61, 0x20, 0x27, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75,
|
||||
0x72, 0x65, 0x27, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e,
|
||||
0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x2d, 0x20, 0x54, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x2d, 0x73,
|
||||
0x74, 0x6d, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72,
|
||||
0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x68,
|
||||
0x61, 0x76, 0x65, 0x20, 0x61, 0x20, 0x6b, 0x65, 0x79, 0x2d, 0x73, 0x74,
|
||||
0x6d, 0x74, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20,
|
||||
0x54, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2d, 0x73,
|
||||
0x74, 0x6d, 0x74, 0x20, 0x69, 0x73, 0x20, 0x69, 0x67, 0x6e, 0x6f, 0x72,
|
||||
0x65, 0x64, 0x20, 0x69, 0x66, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e,
|
||||
0x74, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x74, 0x65,
|
||||
0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x75, 0x67, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x2d, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x20,
|
||||
0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65,
|
||||
0x6e, 0x74, 0x20, 0x70, 0x61, 0x74, 0x68, 0x20, 0x7b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x79, 0x69, 0x6e, 0x2d, 0x65, 0x6c, 0x65, 0x6d,
|
||||
0x65, 0x6e, 0x74, 0x20, 0x74, 0x72, 0x75, 0x65, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63,
|
||||
0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x22, 0x54, 0x68, 0x69, 0x73, 0x20, 0x65, 0x78, 0x74, 0x65,
|
||||
0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65,
|
||||
0x64, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x79,
|
||||
0x20, 0x61, 0x6e, 0x20, 0x61, 0x75, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x59, 0x41,
|
||||
0x4e, 0x47, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x61,
|
||||
0x74, 0x61, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65,
|
||||
0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74,
|
||||
0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x27, 0x73, 0x74, 0x72, 0x75, 0x63,
|
||||
0x74, 0x75, 0x72, 0x65, 0x27, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d,
|
||||
0x65, 0x6e, 0x74, 0x2e, 0x20, 0x20, 0x49, 0x74, 0x20, 0x69, 0x73, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
|
||||
0x64, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72,
|
||||
0x69, 0x62, 0x65, 0x20, 0x68, 0x69, 0x65, 0x72, 0x61, 0x72, 0x63, 0x68,
|
||||
0x69, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x69, 0x6e,
|
||||
0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66,
|
||||
0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
|
||||
0x20, 0x6f, 0x72, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63,
|
||||
0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x65, 0x6e, 0x63,
|
||||
0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74,
|
||||
0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x68,
|
||||
0x69, 0x73, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
|
||||
0x20, 0x68, 0x61, 0x73, 0x20, 0x61, 0x6c, 0x6d, 0x6f, 0x73, 0x74, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x73, 0x74, 0x72,
|
||||
0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68,
|
||||
0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x27, 0x61, 0x75,
|
||||
0x67, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x74, 0x6d, 0x74, 0x27, 0x2e,
|
||||
0x20, 0x20, 0x44, 0x61, 0x74, 0x61, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e,
|
||||
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d,
|
||||
0x65, 0x6e, 0x74, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20,
|
||||
0x74, 0x68, 0x69, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x70,
|
||||
0x65, 0x63, 0x69, 0x66, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65,
|
||||
0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20,
|
||||
0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x20, 0x73, 0x79, 0x6e, 0x74,
|
||||
0x61, 0x78, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x74, 0x6f,
|
||||
0x20, 0x62, 0x65, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x74, 0x6f,
|
||||
0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69,
|
||||
0x63, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x64, 0x61, 0x74, 0x61, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63,
|
||||
0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69,
|
||||
0x66, 0x69, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20,
|
||||
0x27, 0x70, 0x61, 0x74, 0x68, 0x27, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d,
|
||||
0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x54, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x64, 0x61, 0x74, 0x6f,
|
||||
0x72, 0x79, 0x20, 0x27, 0x70, 0x61, 0x74, 0x68, 0x27, 0x20, 0x70, 0x61,
|
||||
0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x20, 0x76, 0x61, 0x6c, 0x75,
|
||||
0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x73,
|
||||
0x20, 0x74, 0x68, 0x65, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x70, 0x74,
|
||||
0x75, 0x61, 0x6c, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x6e, 0x6f, 0x64,
|
||||
0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x62, 0x65,
|
||||
0x69, 0x6e, 0x67, 0x20, 0x61, 0x75, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x65,
|
||||
0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x73, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e,
|
||||
0x74, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x62,
|
||||
0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x2d, 0x73, 0x63, 0x68, 0x65, 0x6d,
|
||||
0x61, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x69, 0x64, 0x20, 0x73, 0x74, 0x72,
|
||||
0x69, 0x6e, 0x67, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74,
|
||||
0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x69,
|
||||
0x72, 0x73, 0x74, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65,
|
||||
0x2d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2d, 0x6e, 0x6f, 0x64, 0x65,
|
||||
0x69, 0x64, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x64,
|
||||
0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x59, 0x41, 0x4e, 0x47,
|
||||
0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74,
|
||||
0x75, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x75, 0x67, 0x6d, 0x65,
|
||||
0x6e, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
|
||||
0x72, 0x65, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
|
||||
0x6e, 0x6f, 0x64, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x72, 0x69,
|
||||
0x6e, 0x67, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65,
|
||||
0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x20, 0x77,
|
||||
0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x59, 0x41,
|
||||
0x4e, 0x47, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65,
|
||||
0x20, 0x74, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61,
|
||||
0x75, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x65, 0x78, 0x74,
|
||||
0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x6f, 0x6e,
|
||||
0x6c, 0x79, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x61, 0x73, 0x20,
|
||||
0x61, 0x20, 0x74, 0x6f, 0x70, 0x2d, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x20,
|
||||
0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x69,
|
||||
0x2e, 0x65, 0x2e, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x73,
|
||||
0x75, 0x62, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20,
|
||||
0x74, 0x6f, 0x20, 0x27, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x27, 0x20,
|
||||
0x6f, 0x72, 0x20, 0x27, 0x73, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
|
||||
0x65, 0x27, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x54, 0x68, 0x65, 0x20, 0x73, 0x75, 0x62, 0x73, 0x74, 0x61, 0x74, 0x65,
|
||||
0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69,
|
||||
0x73, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20,
|
||||
0x4d, 0x55, 0x53, 0x54, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x41, 0x42, 0x4e, 0x46, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x20, 0x62, 0x65,
|
||||
0x6c, 0x6f, 0x77, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65,
|
||||
0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20,
|
||||
0x52, 0x46, 0x43, 0x20, 0x37, 0x39, 0x35, 0x30, 0x3a, 0x0a, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x73,
|
||||
0x74, 0x61, 0x74, 0x75, 0x73, 0x2d, 0x73, 0x74, 0x6d, 0x74, 0x5d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b,
|
||||
0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2d,
|
||||
0x73, 0x74, 0x6d, 0x74, 0x5d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65,
|
||||
0x6e, 0x63, 0x65, 0x2d, 0x73, 0x74, 0x6d, 0x74, 0x5d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x2a, 0x28,
|
||||
0x64, 0x61, 0x74, 0x61, 0x2d, 0x64, 0x65, 0x66, 0x2d, 0x73, 0x74, 0x6d,
|
||||
0x74, 0x20, 0x2f, 0x20, 0x63, 0x61, 0x73, 0x65, 0x2d, 0x73, 0x74, 0x6d,
|
||||
0x74, 0x29, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54,
|
||||
0x68, 0x65, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x6e, 0x61,
|
||||
0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73,
|
||||
0x70, 0x61, 0x63, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x66,
|
||||
0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x20,
|
||||
0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20,
|
||||
0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x74,
|
||||
0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20,
|
||||
0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20,
|
||||
0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x64, 0x6f, 0x63,
|
||||
0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x72,
|
||||
0x6d, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20,
|
||||
0x64, 0x61, 0x74, 0x61, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68,
|
||||
0x69, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x78,
|
||||
0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x58, 0x50, 0x61,
|
||||
0x74, 0x68, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20,
|
||||
0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x61, 0x75, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64,
|
||||
0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d,
|
||||
0x65, 0x6e, 0x74, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20,
|
||||
0x73, 0x75, 0x63, 0x68, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x64, 0x65,
|
||||
0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x6f, 0x63,
|
||||
0x75, 0x6d, 0x65, 0x6e, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x72, 0x65,
|
||||
0x20, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x64,
|
||||
0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x74, 0x61,
|
||||
0x2d, 0x64, 0x65, 0x66, 0x2d, 0x73, 0x74, 0x6d, 0x74, 0x20, 0x73, 0x75,
|
||||
0x62, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69,
|
||||
0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x75, 0x67, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x65, 0x64, 0x20, 0x27, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75,
|
||||
0x72, 0x65, 0x27, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54,
|
||||
0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x20, 0x6e,
|
||||
0x6f, 0x64, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x27,
|
||||
0x61, 0x75, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x75,
|
||||
0x63, 0x74, 0x75, 0x72, 0x65, 0x27, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65,
|
||||
0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x64, 0x65, 0x72, 0x69, 0x76, 0x65, 0x64, 0x20, 0x69,
|
||||
0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x77,
|
||||
0x61, 0x79, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x27, 0x61,
|
||||
0x75, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x27, 0x20, 0x73, 0x74, 0x61, 0x74,
|
||||
0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x64, 0x65,
|
||||
0x66, 0x69, 0x6e, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x69, 0x6e, 0x20, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20,
|
||||
0x36, 0x2e, 0x34, 0x2e, 0x31, 0x20, 0x6f, 0x66, 0x20, 0x5b, 0x52, 0x46,
|
||||
0x43, 0x37, 0x39, 0x35, 0x30, 0x5d, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73,
|
||||
0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x20,
|
||||
0x6e, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x65,
|
||||
0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78,
|
||||
0x74, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67,
|
||||
0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d,
|
||||
0x65, 0x6e, 0x74, 0x73, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x6d, 0x75, 0x73, 0x74,
|
||||
0x2d, 0x73, 0x74, 0x6d, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x2d,
|
||||
0x73, 0x74, 0x6d, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x70, 0x61, 0x74, 0x68, 0x2d, 0x73,
|
||||
0x74, 0x6d, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x2d, 0x20, 0x6d, 0x69, 0x6e, 0x2d, 0x65, 0x6c, 0x65,
|
||||
0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2d, 0x73, 0x74, 0x6d, 0x74, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20,
|
||||
0x6d, 0x61, 0x78, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73,
|
||||
0x2d, 0x73, 0x74, 0x6d, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x6d, 0x61, 0x6e, 0x64, 0x61,
|
||||
0x74, 0x6f, 0x72, 0x79, 0x2d, 0x73, 0x74, 0x6d, 0x74, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x75,
|
||||
0x6e, 0x69, 0x71, 0x75, 0x65, 0x2d, 0x73, 0x74, 0x6d, 0x74, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20,
|
||||
0x6f, 0x72, 0x64, 0x65, 0x72, 0x65, 0x64, 0x2d, 0x62, 0x79, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20,
|
||||
0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x2d, 0x69, 0x64, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x20, 0x64, 0x61, 0x74, 0x61,
|
||||
0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77,
|
||||
0x69, 0x6e, 0x67, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x64, 0x65, 0x66,
|
||||
0x2d, 0x73, 0x74, 0x6d, 0x74, 0x20, 0x73, 0x75, 0x62, 0x73, 0x74, 0x61,
|
||||
0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20,
|
||||
0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20,
|
||||
0x75, 0x73, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20,
|
||||
0x61, 0x6e, 0x20, 0x27, 0x61, 0x75, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x2d,
|
||||
0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x27, 0x20, 0x65,
|
||||
0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x61,
|
||||
0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x54, 0x68,
|
||||
0x65, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x2d, 0x73, 0x74, 0x6d, 0x74, 0x20,
|
||||
0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69,
|
||||
0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20,
|
||||
0x61, 0x20, 0x6b, 0x65, 0x79, 0x2d, 0x73, 0x74, 0x6d, 0x74, 0x20, 0x64,
|
||||
0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x54, 0x68, 0x65,
|
||||
0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2d, 0x73, 0x74, 0x6d, 0x74,
|
||||
0x20, 0x69, 0x73, 0x20, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x64, 0x20,
|
||||
0x69, 0x66, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x2e, 0x0a,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x45, 0x78, 0x61, 0x6d,
|
||||
0x70, 0x6c, 0x65, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20,
|
||||
0x66, 0x6f, 0x6f, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6d, 0x70,
|
||||
0x6f, 0x72, 0x74, 0x20, 0x69, 0x65, 0x74, 0x66, 0x2d, 0x79, 0x61, 0x6e,
|
||||
0x67, 0x2d, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x2d,
|
||||
0x65, 0x78, 0x74, 0x20, 0x7b, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78,
|
||||
0x20, 0x73, 0x78, 0x3b, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73,
|
||||
0x78, 0x3a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x20,
|
||||
0x66, 0x6f, 0x6f, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x20, 0x7b, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x20,
|
||||
0x66, 0x6f, 0x6f, 0x2d, 0x63, 0x6f, 0x6e, 0x20, 0x7b, 0x20, 0x7d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
|
||||
0x20, 0x62, 0x61, 0x72, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6d,
|
||||
0x70, 0x6f, 0x72, 0x74, 0x20, 0x69, 0x65, 0x74, 0x66, 0x2d, 0x79, 0x61,
|
||||
0x6e, 0x67, 0x2d, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65,
|
||||
0x2d, 0x65, 0x78, 0x74, 0x20, 0x7b, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69,
|
||||
0x78, 0x20, 0x73, 0x78, 0x3b, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69,
|
||||
0x6d, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x66, 0x6f, 0x6f, 0x20, 0x7b, 0x20,
|
||||
0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x66, 0x6f, 0x6f, 0x3b, 0x20,
|
||||
0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x78, 0x3a, 0x61, 0x75, 0x67,
|
||||
0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75,
|
||||
0x72, 0x65, 0x20, 0x2f, 0x66, 0x6f, 0x6f, 0x3a, 0x66, 0x6f, 0x6f, 0x2d,
|
||||
0x64, 0x61, 0x74, 0x61, 0x2f, 0x66, 0x6f, 0x6f, 0x3a, 0x66, 0x6f, 0x6f,
|
||||
0x2d, 0x63, 0x6f, 0x6e, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65,
|
||||
0x61, 0x66, 0x20, 0x61, 0x64, 0x64, 0x2d, 0x6c, 0x65, 0x61, 0x66, 0x31,
|
||||
0x20, 0x7b, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x33,
|
||||
0x32, 0x3b, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x61, 0x66,
|
||||
0x20, 0x61, 0x64, 0x64, 0x2d, 0x6c, 0x65, 0x61, 0x66, 0x32, 0x20, 0x7b,
|
||||
0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
|
||||
0x3b, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a,
|
||||
0x7d, 0x0a, 0x00
|
||||
};
|
206
models/ietf-yang-structure-ext@2020-06-17.yang
Normal file
206
models/ietf-yang-structure-ext@2020-06-17.yang
Normal file
|
@ -0,0 +1,206 @@
|
|||
module ietf-yang-structure-ext {
|
||||
yang-version 1.1;
|
||||
namespace "urn:ietf:params:xml:ns:yang:ietf-yang-structure-ext";
|
||||
prefix sx;
|
||||
|
||||
organization
|
||||
"IETF NETMOD (NETCONF Data Modeling Language) Working Group";
|
||||
contact
|
||||
"WG Web: <https://datatracker.ietf.org/wg/netmod/>
|
||||
WG List: <mailto:netmod@ietf.org>
|
||||
|
||||
Author: Andy Bierman
|
||||
<mailto:andy@yumaworks.com>
|
||||
|
||||
Author: Martin Bjorklund
|
||||
<mailto:mbj+ietf@4668.se>
|
||||
|
||||
Author: Kent Watsen
|
||||
<mailto:kent+ietf@watsen.net>";
|
||||
description
|
||||
"This module contains conceptual YANG specifications for defining
|
||||
abstract data structures.
|
||||
|
||||
The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL
|
||||
NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED',
|
||||
'MAY', and 'OPTIONAL' in this document are to be interpreted as
|
||||
described in BCP 14 (RFC 2119) (RFC 8174) when, and only when,
|
||||
they appear in all capitals, as shown here.
|
||||
|
||||
Copyright (c) 2020 IETF Trust and the persons identified as
|
||||
authors of the code. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, is permitted pursuant to, and subject to
|
||||
the license terms contained in, the Simplified BSD License set
|
||||
forth in Section 4.c of the IETF Trust's Legal Provisions
|
||||
Relating to IETF Documents
|
||||
(http://trustee.ietf.org/license-info).
|
||||
|
||||
This version of this YANG module is part of RFC 8791
|
||||
(https://www.rfc-editor.org/info/rfc8791); see the RFC itself
|
||||
for full legal notices.";
|
||||
|
||||
revision 2020-06-17 {
|
||||
description
|
||||
"Initial revision.";
|
||||
reference
|
||||
"RFC 8791: YANG Data Structure Extensions.";
|
||||
}
|
||||
|
||||
extension structure {
|
||||
argument name {
|
||||
yin-element true;
|
||||
}
|
||||
description
|
||||
"This extension is used to specify a YANG data structure that
|
||||
represents conceptual data defined in YANG. It is intended to
|
||||
describe hierarchical data independent of protocol context or
|
||||
specific message encoding format. Data definition statements
|
||||
within a 'structure' extension statement specify the generic
|
||||
syntax for the specific YANG data structure, whose name is the
|
||||
argument of the 'structure' extension statement.
|
||||
|
||||
Note that this extension does not define a media type. A
|
||||
specification using this extension MUST specify the message
|
||||
encoding rules, including the content media type, if
|
||||
applicable.
|
||||
|
||||
The mandatory 'name' parameter value identifies the YANG data
|
||||
structure that is being defined.
|
||||
|
||||
This extension is only valid as a top-level statement, i.e.,
|
||||
given as a substatement to 'module' or 'submodule'.
|
||||
|
||||
The substatements of this extension MUST follow the ABNF
|
||||
rules below, where the rules are defined in RFC 7950:
|
||||
|
||||
*must-stmt
|
||||
[status-stmt]
|
||||
[description-stmt]
|
||||
[reference-stmt]
|
||||
*(typedef-stmt / grouping-stmt)
|
||||
*data-def-stmt
|
||||
|
||||
A YANG data structure defined with this extension statement is
|
||||
encoded in the same way as an 'anydata' node. This means
|
||||
that the name of the structure is encoded as a 'container',
|
||||
with the instantiated child statements encoded as child nodes
|
||||
to this node.
|
||||
|
||||
The module name and namespace value for the YANG module using
|
||||
the extension statement are assigned to each of the data
|
||||
definition statements resulting from the YANG data structure.
|
||||
|
||||
The XPath document element is the extension statement itself,
|
||||
such that the child nodes of the document element are
|
||||
represented by the data-def-stmt substatements within this
|
||||
extension. This conceptual document is the context for the
|
||||
following YANG statements:
|
||||
|
||||
- must-stmt
|
||||
- when-stmt
|
||||
- path-stmt
|
||||
- min-elements-stmt
|
||||
- max-elements-stmt
|
||||
- mandatory-stmt
|
||||
- unique-stmt
|
||||
- ordered-by
|
||||
- instance-identifier data type
|
||||
|
||||
The following data-def-stmt substatements are constrained
|
||||
when used within a 'structure' extension statement.
|
||||
|
||||
- The list-stmt is not required to have a key-stmt defined.
|
||||
- The config-stmt is ignored if present.
|
||||
";
|
||||
}
|
||||
|
||||
extension augment-structure {
|
||||
argument path {
|
||||
yin-element true;
|
||||
}
|
||||
description
|
||||
"This extension is used to specify an augmentation to a YANG
|
||||
data structure defined with the 'structure' statement. It is
|
||||
intended to describe hierarchical data independent of protocol
|
||||
context or specific message encoding format.
|
||||
|
||||
This statement has almost the same structure as the
|
||||
'augment-stmt'. Data definition statements within this
|
||||
statement specify the semantics and generic syntax for the
|
||||
additional data to be added to the specific YANG data
|
||||
structure, identified by the 'path' argument.
|
||||
|
||||
The mandatory 'path' parameter value identifies the YANG
|
||||
conceptual data node that is being augmented and is
|
||||
represented as an absolute-schema-nodeid string, where the
|
||||
first node in the absolute-schema-nodeid string identifies the
|
||||
YANG data structure to augment, and the rest of the nodes in
|
||||
the string identifies the node within the YANG structure to
|
||||
augment.
|
||||
|
||||
This extension is only valid as a top-level statement, i.e.,
|
||||
given as a substatement to 'module' or 'submodule'.
|
||||
|
||||
The substatements of this extension MUST follow the ABNF
|
||||
rules below, where the rules are defined in RFC 7950:
|
||||
|
||||
[status-stmt]
|
||||
[description-stmt]
|
||||
[reference-stmt]
|
||||
1*(data-def-stmt / case-stmt)
|
||||
|
||||
The module name and namespace value for the YANG module using
|
||||
the extension statement are assigned to instance document data
|
||||
conforming to the data definition statements within this
|
||||
extension.
|
||||
|
||||
The XPath document element is the augmented extension
|
||||
statement itself, such that the child nodes of the document
|
||||
element are represented by the data-def-stmt substatements
|
||||
within the augmented 'structure' statement.
|
||||
|
||||
The context node of the 'augment-structure' statement is
|
||||
derived in the same way as the 'augment' statement, as defined
|
||||
in Section 6.4.1 of [RFC7950]. This conceptual node is
|
||||
considered the context node for the following YANG statements:
|
||||
|
||||
- must-stmt
|
||||
- when-stmt
|
||||
- path-stmt
|
||||
- min-elements-stmt
|
||||
- max-elements-stmt
|
||||
- mandatory-stmt
|
||||
- unique-stmt
|
||||
- ordered-by
|
||||
- instance-identifier data type
|
||||
|
||||
The following data-def-stmt substatements are constrained
|
||||
when used within an 'augment-structure' extension statement.
|
||||
|
||||
- The list-stmt is not required to have a key-stmt defined.
|
||||
- The config-stmt is ignored if present.
|
||||
|
||||
Example:
|
||||
|
||||
module foo {
|
||||
import ietf-yang-structure-ext { prefix sx; }
|
||||
|
||||
sx:structure foo-data {
|
||||
container foo-con { }
|
||||
}
|
||||
}
|
||||
|
||||
module bar {
|
||||
import ietf-yang-structure-ext { prefix sx; }
|
||||
import foo { prefix foo; }
|
||||
|
||||
sx:augment-structure /foo:foo-data/foo:foo-con {
|
||||
leaf add-leaf1 { type int32; }
|
||||
leaf add-leaf2 { type string; }
|
||||
}
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
1292
models/ietf-yang-types@2013-07-15.h
Normal file
1292
models/ietf-yang-types@2013-07-15.h
Normal file
File diff suppressed because it is too large
Load diff
474
models/ietf-yang-types@2013-07-15.yang
Normal file
474
models/ietf-yang-types@2013-07-15.yang
Normal file
|
@ -0,0 +1,474 @@
|
|||
module ietf-yang-types {
|
||||
|
||||
namespace "urn:ietf:params:xml:ns:yang:ietf-yang-types";
|
||||
prefix "yang";
|
||||
|
||||
organization
|
||||
"IETF NETMOD (NETCONF Data Modeling Language) Working Group";
|
||||
|
||||
contact
|
||||
"WG Web: <http://tools.ietf.org/wg/netmod/>
|
||||
WG List: <mailto:netmod@ietf.org>
|
||||
|
||||
WG Chair: David Kessens
|
||||
<mailto:david.kessens@nsn.com>
|
||||
|
||||
WG Chair: Juergen Schoenwaelder
|
||||
<mailto:j.schoenwaelder@jacobs-university.de>
|
||||
|
||||
Editor: Juergen Schoenwaelder
|
||||
<mailto:j.schoenwaelder@jacobs-university.de>";
|
||||
|
||||
description
|
||||
"This module contains a collection of generally useful derived
|
||||
YANG data types.
|
||||
|
||||
Copyright (c) 2013 IETF Trust and the persons identified as
|
||||
authors of the code. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, is permitted pursuant to, and subject
|
||||
to the license terms contained in, the Simplified BSD License
|
||||
set forth in Section 4.c of the IETF Trust's Legal Provisions
|
||||
Relating to IETF Documents
|
||||
(http://trustee.ietf.org/license-info).
|
||||
|
||||
This version of this YANG module is part of RFC 6991; see
|
||||
the RFC itself for full legal notices.";
|
||||
|
||||
revision 2013-07-15 {
|
||||
description
|
||||
"This revision adds the following new data types:
|
||||
- yang-identifier
|
||||
- hex-string
|
||||
- uuid
|
||||
- dotted-quad";
|
||||
reference
|
||||
"RFC 6991: Common YANG Data Types";
|
||||
}
|
||||
|
||||
revision 2010-09-24 {
|
||||
description
|
||||
"Initial revision.";
|
||||
reference
|
||||
"RFC 6021: Common YANG Data Types";
|
||||
}
|
||||
|
||||
/*** collection of counter and gauge types ***/
|
||||
|
||||
typedef counter32 {
|
||||
type uint32;
|
||||
description
|
||||
"The counter32 type represents a non-negative integer
|
||||
that monotonically increases until it reaches a
|
||||
maximum value of 2^32-1 (4294967295 decimal), when it
|
||||
wraps around and starts increasing again from zero.
|
||||
|
||||
Counters have no defined 'initial' value, and thus, a
|
||||
single value of a counter has (in general) no information
|
||||
content. Discontinuities in the monotonically increasing
|
||||
value normally occur at re-initialization of the
|
||||
management system, and at other times as specified in the
|
||||
description of a schema node using this type. If such
|
||||
other times can occur, for example, the creation of
|
||||
a schema node of type counter32 at times other than
|
||||
re-initialization, then a corresponding schema node
|
||||
should be defined, with an appropriate type, to indicate
|
||||
the last discontinuity.
|
||||
|
||||
The counter32 type should not be used for configuration
|
||||
schema nodes. A default statement SHOULD NOT be used in
|
||||
combination with the type counter32.
|
||||
|
||||
In the value set and its semantics, this type is equivalent
|
||||
to the Counter32 type of the SMIv2.";
|
||||
reference
|
||||
"RFC 2578: Structure of Management Information Version 2
|
||||
(SMIv2)";
|
||||
}
|
||||
|
||||
typedef zero-based-counter32 {
|
||||
type yang:counter32;
|
||||
default "0";
|
||||
description
|
||||
"The zero-based-counter32 type represents a counter32
|
||||
that has the defined 'initial' value zero.
|
||||
|
||||
A schema node of this type will be set to zero (0) on creation
|
||||
and will thereafter increase monotonically until it reaches
|
||||
a maximum value of 2^32-1 (4294967295 decimal), when it
|
||||
wraps around and starts increasing again from zero.
|
||||
|
||||
Provided that an application discovers a new schema node
|
||||
of this type within the minimum time to wrap, it can use the
|
||||
'initial' value as a delta. It is important for a management
|
||||
station to be aware of this minimum time and the actual time
|
||||
between polls, and to discard data if the actual time is too
|
||||
long or there is no defined minimum time.
|
||||
|
||||
In the value set and its semantics, this type is equivalent
|
||||
to the ZeroBasedCounter32 textual convention of the SMIv2.";
|
||||
reference
|
||||
"RFC 4502: Remote Network Monitoring Management Information
|
||||
Base Version 2";
|
||||
}
|
||||
|
||||
typedef counter64 {
|
||||
type uint64;
|
||||
description
|
||||
"The counter64 type represents a non-negative integer
|
||||
that monotonically increases until it reaches a
|
||||
maximum value of 2^64-1 (18446744073709551615 decimal),
|
||||
when it wraps around and starts increasing again from zero.
|
||||
|
||||
Counters have no defined 'initial' value, and thus, a
|
||||
single value of a counter has (in general) no information
|
||||
content. Discontinuities in the monotonically increasing
|
||||
value normally occur at re-initialization of the
|
||||
management system, and at other times as specified in the
|
||||
description of a schema node using this type. If such
|
||||
other times can occur, for example, the creation of
|
||||
a schema node of type counter64 at times other than
|
||||
re-initialization, then a corresponding schema node
|
||||
should be defined, with an appropriate type, to indicate
|
||||
the last discontinuity.
|
||||
|
||||
The counter64 type should not be used for configuration
|
||||
schema nodes. A default statement SHOULD NOT be used in
|
||||
combination with the type counter64.
|
||||
|
||||
In the value set and its semantics, this type is equivalent
|
||||
to the Counter64 type of the SMIv2.";
|
||||
reference
|
||||
"RFC 2578: Structure of Management Information Version 2
|
||||
(SMIv2)";
|
||||
}
|
||||
|
||||
typedef zero-based-counter64 {
|
||||
type yang:counter64;
|
||||
default "0";
|
||||
description
|
||||
"The zero-based-counter64 type represents a counter64 that
|
||||
has the defined 'initial' value zero.
|
||||
|
||||
A schema node of this type will be set to zero (0) on creation
|
||||
and will thereafter increase monotonically until it reaches
|
||||
a maximum value of 2^64-1 (18446744073709551615 decimal),
|
||||
when it wraps around and starts increasing again from zero.
|
||||
|
||||
Provided that an application discovers a new schema node
|
||||
of this type within the minimum time to wrap, it can use the
|
||||
'initial' value as a delta. It is important for a management
|
||||
station to be aware of this minimum time and the actual time
|
||||
between polls, and to discard data if the actual time is too
|
||||
long or there is no defined minimum time.
|
||||
|
||||
In the value set and its semantics, this type is equivalent
|
||||
to the ZeroBasedCounter64 textual convention of the SMIv2.";
|
||||
reference
|
||||
"RFC 2856: Textual Conventions for Additional High Capacity
|
||||
Data Types";
|
||||
}
|
||||
|
||||
typedef gauge32 {
|
||||
type uint32;
|
||||
description
|
||||
"The gauge32 type represents a non-negative integer, which
|
||||
may increase or decrease, but shall never exceed a maximum
|
||||
value, nor fall below a minimum value. The maximum value
|
||||
cannot be greater than 2^32-1 (4294967295 decimal), and
|
||||
the minimum value cannot be smaller than 0. The value of
|
||||
a gauge32 has its maximum value whenever the information
|
||||
being modeled is greater than or equal to its maximum
|
||||
value, and has its minimum value whenever the information
|
||||
being modeled is smaller than or equal to its minimum value.
|
||||
If the information being modeled subsequently decreases
|
||||
below (increases above) the maximum (minimum) value, the
|
||||
gauge32 also decreases (increases).
|
||||
|
||||
In the value set and its semantics, this type is equivalent
|
||||
to the Gauge32 type of the SMIv2.";
|
||||
reference
|
||||
"RFC 2578: Structure of Management Information Version 2
|
||||
(SMIv2)";
|
||||
}
|
||||
|
||||
typedef gauge64 {
|
||||
type uint64;
|
||||
description
|
||||
"The gauge64 type represents a non-negative integer, which
|
||||
may increase or decrease, but shall never exceed a maximum
|
||||
value, nor fall below a minimum value. The maximum value
|
||||
cannot be greater than 2^64-1 (18446744073709551615), and
|
||||
the minimum value cannot be smaller than 0. The value of
|
||||
a gauge64 has its maximum value whenever the information
|
||||
being modeled is greater than or equal to its maximum
|
||||
value, and has its minimum value whenever the information
|
||||
being modeled is smaller than or equal to its minimum value.
|
||||
If the information being modeled subsequently decreases
|
||||
below (increases above) the maximum (minimum) value, the
|
||||
gauge64 also decreases (increases).
|
||||
|
||||
In the value set and its semantics, this type is equivalent
|
||||
to the CounterBasedGauge64 SMIv2 textual convention defined
|
||||
in RFC 2856";
|
||||
reference
|
||||
"RFC 2856: Textual Conventions for Additional High Capacity
|
||||
Data Types";
|
||||
}
|
||||
|
||||
/*** collection of identifier-related types ***/
|
||||
|
||||
typedef object-identifier {
|
||||
type string {
|
||||
pattern '(([0-1](\.[1-3]?[0-9]))|(2\.(0|([1-9]\d*))))'
|
||||
+ '(\.(0|([1-9]\d*)))*';
|
||||
}
|
||||
description
|
||||
"The object-identifier type represents administratively
|
||||
assigned names in a registration-hierarchical-name tree.
|
||||
|
||||
Values of this type are denoted as a sequence of numerical
|
||||
non-negative sub-identifier values. Each sub-identifier
|
||||
value MUST NOT exceed 2^32-1 (4294967295). Sub-identifiers
|
||||
are separated by single dots and without any intermediate
|
||||
whitespace.
|
||||
|
||||
The ASN.1 standard restricts the value space of the first
|
||||
sub-identifier to 0, 1, or 2. Furthermore, the value space
|
||||
of the second sub-identifier is restricted to the range
|
||||
0 to 39 if the first sub-identifier is 0 or 1. Finally,
|
||||
the ASN.1 standard requires that an object identifier
|
||||
has always at least two sub-identifiers. The pattern
|
||||
captures these restrictions.
|
||||
|
||||
Although the number of sub-identifiers is not limited,
|
||||
module designers should realize that there may be
|
||||
implementations that stick with the SMIv2 limit of 128
|
||||
sub-identifiers.
|
||||
|
||||
This type is a superset of the SMIv2 OBJECT IDENTIFIER type
|
||||
since it is not restricted to 128 sub-identifiers. Hence,
|
||||
this type SHOULD NOT be used to represent the SMIv2 OBJECT
|
||||
IDENTIFIER type; the object-identifier-128 type SHOULD be
|
||||
used instead.";
|
||||
reference
|
||||
"ISO9834-1: Information technology -- Open Systems
|
||||
Interconnection -- Procedures for the operation of OSI
|
||||
Registration Authorities: General procedures and top
|
||||
arcs of the ASN.1 Object Identifier tree";
|
||||
}
|
||||
|
||||
typedef object-identifier-128 {
|
||||
type object-identifier {
|
||||
pattern '\d*(\.\d*){1,127}';
|
||||
}
|
||||
description
|
||||
"This type represents object-identifiers restricted to 128
|
||||
sub-identifiers.
|
||||
|
||||
In the value set and its semantics, this type is equivalent
|
||||
to the OBJECT IDENTIFIER type of the SMIv2.";
|
||||
reference
|
||||
"RFC 2578: Structure of Management Information Version 2
|
||||
(SMIv2)";
|
||||
}
|
||||
|
||||
typedef yang-identifier {
|
||||
type string {
|
||||
length "1..max";
|
||||
pattern '[a-zA-Z_][a-zA-Z0-9\-_.]*';
|
||||
pattern '.|..|[^xX].*|.[^mM].*|..[^lL].*';
|
||||
}
|
||||
description
|
||||
"A YANG identifier string as defined by the 'identifier'
|
||||
rule in Section 12 of RFC 6020. An identifier must
|
||||
start with an alphabetic character or an underscore
|
||||
followed by an arbitrary sequence of alphabetic or
|
||||
numeric characters, underscores, hyphens, or dots.
|
||||
|
||||
A YANG identifier MUST NOT start with any possible
|
||||
combination of the lowercase or uppercase character
|
||||
sequence 'xml'.";
|
||||
reference
|
||||
"RFC 6020: YANG - A Data Modeling Language for the Network
|
||||
Configuration Protocol (NETCONF)";
|
||||
}
|
||||
|
||||
/*** collection of types related to date and time***/
|
||||
|
||||
typedef date-and-time {
|
||||
type string {
|
||||
pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?'
|
||||
+ '(Z|[\+\-]\d{2}:\d{2})';
|
||||
}
|
||||
description
|
||||
"The date-and-time type is a profile of the ISO 8601
|
||||
standard for representation of dates and times using the
|
||||
Gregorian calendar. The profile is defined by the
|
||||
date-time production in Section 5.6 of RFC 3339.
|
||||
|
||||
The date-and-time type is compatible with the dateTime XML
|
||||
schema type with the following notable exceptions:
|
||||
|
||||
(a) The date-and-time type does not allow negative years.
|
||||
|
||||
(b) The date-and-time time-offset -00:00 indicates an unknown
|
||||
time zone (see RFC 3339) while -00:00 and +00:00 and Z
|
||||
all represent the same time zone in dateTime.
|
||||
|
||||
(c) The canonical format (see below) of data-and-time values
|
||||
differs from the canonical format used by the dateTime XML
|
||||
schema type, which requires all times to be in UTC using
|
||||
the time-offset 'Z'.
|
||||
|
||||
This type is not equivalent to the DateAndTime textual
|
||||
convention of the SMIv2 since RFC 3339 uses a different
|
||||
separator between full-date and full-time and provides
|
||||
higher resolution of time-secfrac.
|
||||
|
||||
The canonical format for date-and-time values with a known time
|
||||
zone uses a numeric time zone offset that is calculated using
|
||||
the device's configured known offset to UTC time. A change of
|
||||
the device's offset to UTC time will cause date-and-time values
|
||||
to change accordingly. Such changes might happen periodically
|
||||
in case a server follows automatically daylight saving time
|
||||
(DST) time zone offset changes. The canonical format for
|
||||
date-and-time values with an unknown time zone (usually
|
||||
referring to the notion of local time) uses the time-offset
|
||||
-00:00.";
|
||||
reference
|
||||
"RFC 3339: Date and Time on the Internet: Timestamps
|
||||
RFC 2579: Textual Conventions for SMIv2
|
||||
XSD-TYPES: XML Schema Part 2: Datatypes Second Edition";
|
||||
}
|
||||
|
||||
typedef timeticks {
|
||||
type uint32;
|
||||
description
|
||||
"The timeticks type represents a non-negative integer that
|
||||
represents the time, modulo 2^32 (4294967296 decimal), in
|
||||
hundredths of a second between two epochs. When a schema
|
||||
node is defined that uses this type, the description of
|
||||
the schema node identifies both of the reference epochs.
|
||||
|
||||
In the value set and its semantics, this type is equivalent
|
||||
to the TimeTicks type of the SMIv2.";
|
||||
reference
|
||||
"RFC 2578: Structure of Management Information Version 2
|
||||
(SMIv2)";
|
||||
}
|
||||
|
||||
typedef timestamp {
|
||||
type yang:timeticks;
|
||||
description
|
||||
"The timestamp type represents the value of an associated
|
||||
timeticks schema node at which a specific occurrence
|
||||
happened. The specific occurrence must be defined in the
|
||||
description of any schema node defined using this type. When
|
||||
the specific occurrence occurred prior to the last time the
|
||||
associated timeticks attribute was zero, then the timestamp
|
||||
value is zero. Note that this requires all timestamp values
|
||||
to be reset to zero when the value of the associated timeticks
|
||||
attribute reaches 497+ days and wraps around to zero.
|
||||
|
||||
The associated timeticks schema node must be specified
|
||||
in the description of any schema node using this type.
|
||||
|
||||
In the value set and its semantics, this type is equivalent
|
||||
to the TimeStamp textual convention of the SMIv2.";
|
||||
reference
|
||||
"RFC 2579: Textual Conventions for SMIv2";
|
||||
}
|
||||
|
||||
/*** collection of generic address types ***/
|
||||
|
||||
typedef phys-address {
|
||||
type string {
|
||||
pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?';
|
||||
}
|
||||
|
||||
description
|
||||
"Represents media- or physical-level addresses represented
|
||||
as a sequence octets, each octet represented by two hexadecimal
|
||||
numbers. Octets are separated by colons. The canonical
|
||||
representation uses lowercase characters.
|
||||
|
||||
In the value set and its semantics, this type is equivalent
|
||||
to the PhysAddress textual convention of the SMIv2.";
|
||||
reference
|
||||
"RFC 2579: Textual Conventions for SMIv2";
|
||||
}
|
||||
|
||||
typedef mac-address {
|
||||
type string {
|
||||
pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}';
|
||||
}
|
||||
description
|
||||
"The mac-address type represents an IEEE 802 MAC address.
|
||||
The canonical representation uses lowercase characters.
|
||||
|
||||
In the value set and its semantics, this type is equivalent
|
||||
to the MacAddress textual convention of the SMIv2.";
|
||||
reference
|
||||
"IEEE 802: IEEE Standard for Local and Metropolitan Area
|
||||
Networks: Overview and Architecture
|
||||
RFC 2579: Textual Conventions for SMIv2";
|
||||
}
|
||||
|
||||
/*** collection of XML-specific types ***/
|
||||
|
||||
typedef xpath1.0 {
|
||||
type string;
|
||||
description
|
||||
"This type represents an XPATH 1.0 expression.
|
||||
|
||||
When a schema node is defined that uses this type, the
|
||||
description of the schema node MUST specify the XPath
|
||||
context in which the XPath expression is evaluated.";
|
||||
reference
|
||||
"XPATH: XML Path Language (XPath) Version 1.0";
|
||||
}
|
||||
|
||||
/*** collection of string types ***/
|
||||
|
||||
typedef hex-string {
|
||||
type string {
|
||||
pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?';
|
||||
}
|
||||
description
|
||||
"A hexadecimal string with octets represented as hex digits
|
||||
separated by colons. The canonical representation uses
|
||||
lowercase characters.";
|
||||
}
|
||||
|
||||
typedef uuid {
|
||||
type string {
|
||||
pattern '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-'
|
||||
+ '[0-9a-fA-F]{4}-[0-9a-fA-F]{12}';
|
||||
}
|
||||
description
|
||||
"A Universally Unique IDentifier in the string representation
|
||||
defined in RFC 4122. The canonical representation uses
|
||||
lowercase characters.
|
||||
|
||||
The following is an example of a UUID in string representation:
|
||||
f81d4fae-7dec-11d0-a765-00a0c91e6bf6
|
||||
";
|
||||
reference
|
||||
"RFC 4122: A Universally Unique IDentifier (UUID) URN
|
||||
Namespace";
|
||||
}
|
||||
|
||||
typedef dotted-quad {
|
||||
type string {
|
||||
pattern
|
||||
'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
|
||||
+ '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])';
|
||||
}
|
||||
description
|
||||
"An unsigned 32-bit number expressed in the dotted-quad
|
||||
notation, i.e., four octets written as decimal numbers
|
||||
and separated with the '.' (full stop) character.";
|
||||
}
|
||||
}
|
485
models/yang@2022-06-16.h
Normal file
485
models/yang@2022-06-16.h
Normal file
|
@ -0,0 +1,485 @@
|
|||
char yang_2022_06_16_yang[] = {
|
||||
0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x79, 0x61, 0x6e, 0x67, 0x20,
|
||||
0x7b, 0x0a, 0x20, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63,
|
||||
0x65, 0x20, 0x22, 0x75, 0x72, 0x6e, 0x3a, 0x69, 0x65, 0x74, 0x66, 0x3a,
|
||||
0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3a, 0x78, 0x6d, 0x6c, 0x3a, 0x6e,
|
||||
0x73, 0x3a, 0x79, 0x61, 0x6e, 0x67, 0x3a, 0x31, 0x22, 0x3b, 0x0a, 0x20,
|
||||
0x20, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x79, 0x61, 0x6e, 0x67,
|
||||
0x3b, 0x0a, 0x20, 0x20, 0x79, 0x61, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x20, 0x31, 0x2e, 0x31, 0x3b, 0x0a, 0x0a, 0x20,
|
||||
0x20, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x69, 0x65, 0x74, 0x66,
|
||||
0x2d, 0x79, 0x61, 0x6e, 0x67, 0x2d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61,
|
||||
0x74, 0x61, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x72, 0x65,
|
||||
0x66, 0x69, 0x78, 0x20, 0x6d, 0x64, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2d, 0x64, 0x61, 0x74,
|
||||
0x65, 0x20, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x38, 0x2d, 0x30, 0x35,
|
||||
0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x6f, 0x72, 0x67,
|
||||
0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x22, 0x6c, 0x69, 0x62, 0x79, 0x61, 0x6e, 0x67, 0x22, 0x3b,
|
||||
0x0a, 0x0a, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x22, 0x57, 0x65, 0x62, 0x3a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x3c, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69,
|
||||
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x45, 0x53,
|
||||
0x4e, 0x45, 0x54, 0x2f, 0x6c, 0x69, 0x62, 0x79, 0x61, 0x6e, 0x67, 0x2f,
|
||||
0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f,
|
||||
0x72, 0x3a, 0x20, 0x52, 0x61, 0x64, 0x65, 0x6b, 0x20, 0x4b, 0x72, 0x65,
|
||||
0x6a, 0x63, 0x69, 0x20, 0x3c, 0x72, 0x6b, 0x72, 0x65, 0x6a, 0x63, 0x69,
|
||||
0x40, 0x63, 0x65, 0x73, 0x6e, 0x65, 0x74, 0x2e, 0x63, 0x7a, 0x3e, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x3a,
|
||||
0x20, 0x4d, 0x69, 0x63, 0x68, 0x61, 0x6c, 0x20, 0x56, 0x61, 0x73, 0x6b,
|
||||
0x6f, 0x20, 0x3c, 0x6d, 0x76, 0x61, 0x73, 0x6b, 0x6f, 0x40, 0x63, 0x65,
|
||||
0x73, 0x6e, 0x65, 0x74, 0x2e, 0x63, 0x7a, 0x3e, 0x22, 0x3b, 0x0a, 0x0a,
|
||||
0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x54, 0x68, 0x69, 0x73, 0x20,
|
||||
0x69, 0x73, 0x20, 0x61, 0x20, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x20, 0x6d,
|
||||
0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6e,
|
||||
0x6f, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61,
|
||||
0x6c, 0x6c, 0x79, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x69, 0x6e,
|
||||
0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f,
|
||||
0x66, 0x20, 0x76, 0x61, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x20, 0x6d, 0x65,
|
||||
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e,
|
||||
0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x52, 0x46, 0x43, 0x20, 0x36, 0x30,
|
||||
0x32, 0x30, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x52, 0x46, 0x43, 0x20, 0x37,
|
||||
0x39, 0x35, 0x30, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61,
|
||||
0x72, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x64, 0x64, 0x69,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64,
|
||||
0x61, 0x74, 0x61, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20,
|
||||
0x6c, 0x69, 0x62, 0x79, 0x61, 0x6e, 0x67, 0x20, 0x64, 0x69, 0x66, 0x66,
|
||||
0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74,
|
||||
0x2e, 0x22, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x76, 0x69, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x20, 0x32, 0x30, 0x32, 0x32, 0x2d, 0x30, 0x36, 0x2d,
|
||||
0x31, 0x36, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73,
|
||||
0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x22, 0x41, 0x64, 0x64, 0x65, 0x64, 0x20, 0x74, 0x79,
|
||||
0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x65,
|
||||
0x79, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x20, 0x74,
|
||||
0x79, 0x70, 0x65, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a,
|
||||
0x20, 0x20, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x32,
|
||||
0x30, 0x32, 0x31, 0x2d, 0x30, 0x34, 0x2d, 0x30, 0x37, 0x20, 0x7b, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41,
|
||||
0x64, 0x64, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
|
||||
0x61, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x65, 0x79, 0x2d, 0x6c, 0x65,
|
||||
0x73, 0x73, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20,
|
||||
0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x2d, 0x6c,
|
||||
0x69, 0x73, 0x74, 0x20, 0x64, 0x69, 0x66, 0x66, 0x2e, 0x22, 0x3b, 0x0a,
|
||||
0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x76, 0x69, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x20, 0x32, 0x30, 0x32, 0x30, 0x2d, 0x30, 0x36, 0x2d,
|
||||
0x31, 0x37, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73,
|
||||
0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x22, 0x41, 0x64, 0x64, 0x65, 0x64, 0x20, 0x6d, 0x65,
|
||||
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64,
|
||||
0x69, 0x66, 0x66, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a,
|
||||
0x20, 0x20, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x32,
|
||||
0x30, 0x31, 0x37, 0x2d, 0x30, 0x32, 0x2d, 0x32, 0x30, 0x20, 0x7b, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41,
|
||||
0x64, 0x64, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
|
||||
0x61, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x4e, 0x45, 0x54, 0x43, 0x4f, 0x4e,
|
||||
0x46, 0x27, 0x73, 0x20, 0x65, 0x64, 0x69, 0x74, 0x2d, 0x63, 0x6f, 0x6e,
|
||||
0x66, 0x69, 0x67, 0x20, 0x6d, 0x61, 0x6e, 0x69, 0x70, 0x75, 0x6c, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x72,
|
||||
0x64, 0x65, 0x72, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x6c, 0x69, 0x73, 0x74, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c,
|
||||
0x65, 0x61, 0x66, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x73, 0x2e, 0x22, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e,
|
||||
0x63, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x52, 0x46,
|
||||
0x43, 0x20, 0x37, 0x39, 0x35, 0x30, 0x3a, 0x20, 0x54, 0x68, 0x65, 0x20,
|
||||
0x59, 0x41, 0x4e, 0x47, 0x20, 0x31, 0x2e, 0x31, 0x20, 0x44, 0x61, 0x74,
|
||||
0x61, 0x20, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x4c,
|
||||
0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x22, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x20, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x32, 0x2d, 0x31, 0x31,
|
||||
0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72,
|
||||
0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x22, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x20, 0x72, 0x65,
|
||||
0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x52, 0x46, 0x43, 0x20, 0x36, 0x30,
|
||||
0x32, 0x30, 0x3a, 0x20, 0x59, 0x41, 0x4e, 0x47, 0x20, 0x2d, 0x20, 0x41,
|
||||
0x20, 0x44, 0x61, 0x74, 0x61, 0x20, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x69,
|
||||
0x6e, 0x67, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x20,
|
||||
0x66, 0x6f, 0x72, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x43,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x20, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x28, 0x4e,
|
||||
0x45, 0x54, 0x43, 0x4f, 0x4e, 0x46, 0x29, 0x22, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66,
|
||||
0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x2d, 0x69, 0x64,
|
||||
0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x2d, 0x6b, 0x65, 0x79,
|
||||
0x73, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x79, 0x70, 0x65,
|
||||
0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x22,
|
||||
0x52, 0x46, 0x43, 0x37, 0x39, 0x35, 0x30, 0x20, 0x73, 0x65, 0x63, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x20, 0x37, 0x2e, 0x38, 0x2e, 0x36, 0x2e, 0x22, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
|
||||
0x54, 0x68, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x70, 0x72, 0x65, 0x64,
|
||||
0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61,
|
||||
0x6e, 0x63, 0x65, 0x2d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69,
|
||||
0x65, 0x72, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x2d, 0x69, 0x6e, 0x20,
|
||||
0x74, 0x79, 0x70, 0x65, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a,
|
||||
0x0a, 0x20, 0x20, 0x6d, 0x64, 0x3a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x20,
|
||||
0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x65,
|
||||
0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x7b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x75, 0x6d, 0x20,
|
||||
0x66, 0x69, 0x72, 0x73, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x65, 0x6e, 0x75, 0x6d, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x3b, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x75, 0x6d, 0x20, 0x62,
|
||||
0x65, 0x66, 0x6f, 0x72, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x65, 0x6e, 0x75, 0x6d, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72,
|
||||
0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x22, 0x52, 0x46,
|
||||
0x43, 0x37, 0x39, 0x35, 0x30, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x20, 0x37, 0x2e, 0x38, 0x2e, 0x36, 0x2e, 0x20, 0x61, 0x6e, 0x64,
|
||||
0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x37, 0x2e, 0x37,
|
||||
0x2e, 0x39, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65,
|
||||
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x22, 0x49, 0x6e, 0x20, 0x75, 0x73, 0x65, 0x72,
|
||||
0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20, 0x6c, 0x65, 0x61,
|
||||
0x66, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73,
|
||||
0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x63,
|
||||
0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74,
|
||||
0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69,
|
||||
0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x2d, 0x6c,
|
||||
0x69, 0x73, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x74, 0x72,
|
||||
0x79, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x65,
|
||||
0x64, 0x2e, 0x20, 0x49, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65,
|
||||
0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x64, 0x75, 0x72, 0x69, 0x6e, 0x67,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20,
|
||||
0x4e, 0x45, 0x54, 0x43, 0x4f, 0x4e, 0x46, 0x20, 0x3c, 0x65, 0x64, 0x69,
|
||||
0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3e, 0x20, 0x5c, 0x22,
|
||||
0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5c, 0x22, 0x20, 0x6f, 0x70, 0x65,
|
||||
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x69,
|
||||
0x6e, 0x73, 0x65, 0x72, 0x74, 0x20, 0x61, 0x20, 0x6e, 0x65, 0x77, 0x20,
|
||||
0x6c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x72, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x2d, 0x6c, 0x69, 0x73, 0x74,
|
||||
0x20, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x64,
|
||||
0x75, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x5c, 0x22, 0x6d, 0x65, 0x72, 0x67,
|
||||
0x65, 0x5c, 0x22, 0x20, 0x6f, 0x72, 0x20, 0x5c, 0x22, 0x72, 0x65, 0x70,
|
||||
0x6c, 0x61, 0x63, 0x65, 0x5c, 0x22, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x73,
|
||||
0x65, 0x72, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61,
|
||||
0x20, 0x6e, 0x65, 0x77, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x72,
|
||||
0x20, 0x6c, 0x65, 0x61, 0x66, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x65,
|
||||
0x6e, 0x74, 0x72, 0x79, 0x20, 0x6f, 0x72, 0x20, 0x6d, 0x6f, 0x76, 0x65,
|
||||
0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67,
|
||||
0x20, 0x6f, 0x6e, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x61, 0x6c,
|
||||
0x75, 0x65, 0x20, 0x69, 0x73, 0x20, 0x5c, 0x22, 0x62, 0x65, 0x66, 0x6f,
|
||||
0x72, 0x65, 0x5c, 0x22, 0x20, 0x6f, 0x72, 0x20, 0x5c, 0x22, 0x61, 0x66,
|
||||
0x74, 0x65, 0x72, 0x5c, 0x22, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x5c,
|
||||
0x22, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5c, 0x22, 0x2f, 0x5c, 0x22, 0x6b,
|
||||
0x65, 0x79, 0x5c, 0x22, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75,
|
||||
0x74, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, 0x55,
|
||||
0x53, 0x54, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x75,
|
||||
0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69,
|
||||
0x66, 0x79, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69,
|
||||
0x6e, 0x67, 0x20, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x20, 0x69, 0x6e, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x72, 0x20,
|
||||
0x6c, 0x65, 0x61, 0x66, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x0a, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f,
|
||||
0x20, 0x5c, 0x22, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x5c, 0x22, 0x20,
|
||||
0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x69, 0x73,
|
||||
0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x5c, 0x22, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
|
||||
0x5c, 0x22, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x2c, 0x20, 0x69, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20,
|
||||
0x5c, 0x22, 0x6c, 0x61, 0x73, 0x74, 0x5c, 0x22, 0x2e, 0x22, 0x3b, 0x0a,
|
||||
0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x6d, 0x64, 0x3a, 0x61, 0x6e,
|
||||
0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x76, 0x61, 0x6c,
|
||||
0x75, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x79, 0x70,
|
||||
0x65, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20,
|
||||
0x22, 0x52, 0x46, 0x43, 0x37, 0x39, 0x35, 0x30, 0x20, 0x73, 0x65, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x37, 0x2e, 0x37, 0x2e, 0x39, 0x2e, 0x22,
|
||||
0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
|
||||
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x22, 0x49, 0x6e, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x6f, 0x72, 0x64,
|
||||
0x65, 0x72, 0x65, 0x64, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x2d, 0x6c, 0x69,
|
||||
0x73, 0x74, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x61, 0x74, 0x74,
|
||||
0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20,
|
||||
0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x66, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x73, 0x65,
|
||||
0x72, 0x74, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x61,
|
||||
0x6e, 0x64, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x73,
|
||||
0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x66, 0x74, 0x65,
|
||||
0x72, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x65, 0x78, 0x69, 0x73,
|
||||
0x74, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63,
|
||||
0x65, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x6e, 0x65, 0x77, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63,
|
||||
0x65, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20,
|
||||
0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x65, 0x64, 0x2e, 0x22, 0x3b, 0x0a,
|
||||
0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x6d, 0x64, 0x3a, 0x61, 0x6e,
|
||||
0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6b, 0x65, 0x79,
|
||||
0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20,
|
||||
0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79,
|
||||
0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x79, 0x70, 0x65,
|
||||
0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x2d, 0x69, 0x64,
|
||||
0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x2d, 0x6b, 0x65, 0x79,
|
||||
0x73, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x22,
|
||||
0x52, 0x46, 0x43, 0x37, 0x39, 0x35, 0x30, 0x20, 0x73, 0x65, 0x63, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x20, 0x37, 0x2e, 0x38, 0x2e, 0x36, 0x2e, 0x22, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
|
||||
0x49, 0x6e, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x6f, 0x72, 0x64, 0x65,
|
||||
0x72, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x2c, 0x20, 0x74, 0x68,
|
||||
0x69, 0x73, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65,
|
||||
0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65,
|
||||
0x64, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x74, 0x74,
|
||||
0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x20, 0x69, 0x73, 0x20,
|
||||
0x75, 0x73, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x70, 0x65,
|
||||
0x63, 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72,
|
||||
0x65, 0x2f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x77, 0x68, 0x69, 0x63,
|
||||
0x68, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x69,
|
||||
0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x68, 0x65, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x69,
|
||||
0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x73, 0x68, 0x6f, 0x75,
|
||||
0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74,
|
||||
0x65, 0x64, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20,
|
||||
0x20, 0x6d, 0x64, 0x3a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20,
|
||||
0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x75,
|
||||
0x6e, 0x69, 0x6f, 0x6e, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x65, 0x6d, 0x70, 0x74,
|
||||
0x79, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74,
|
||||
0x79, 0x70, 0x65, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x20, 0x7b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x31, 0x2e, 0x2e, 0x6d, 0x61,
|
||||
0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64,
|
||||
0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x49, 0x6e, 0x20, 0x6b, 0x65, 0x79,
|
||||
0x2d, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x6f,
|
||||
0x72, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x6c, 0x65, 0x61, 0x66,
|
||||
0x2d, 0x6c, 0x69, 0x73, 0x74, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20,
|
||||
0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6d, 0x75,
|
||||
0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69,
|
||||
0x66, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65,
|
||||
0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x69,
|
||||
0x6e, 0x73, 0x65, 0x72, 0x74, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65,
|
||||
0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66,
|
||||
0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x73, 0x74,
|
||||
0x61, 0x6e, 0x63, 0x65, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x65, 0x66,
|
||||
0x6f, 0x72, 0x65, 0x2f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x77, 0x68,
|
||||
0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x77, 0x20,
|
||||
0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x73, 0x68, 0x6f,
|
||||
0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, 0x6e, 0x73, 0x65, 0x72,
|
||||
0x74, 0x65, 0x64, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a,
|
||||
0x20, 0x20, 0x6d, 0x64, 0x3a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x79, 0x70, 0x65,
|
||||
0x20, 0x65, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x75,
|
||||
0x6d, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x22, 0x54, 0x68, 0x65, 0x20, 0x6e, 0x6f, 0x64, 0x65,
|
||||
0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20,
|
||||
0x62, 0x6f, 0x74, 0x68, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x74, 0x72,
|
||||
0x65, 0x65, 0x73, 0x20, 0x62, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x72,
|
||||
0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x6e, 0x65, 0x73, 0x74, 0x65,
|
||||
0x64, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61,
|
||||
0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x49, 0x6e, 0x20, 0x63, 0x61, 0x73,
|
||||
0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x2c,
|
||||
0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x69, 0x74, 0x73, 0x20, 0x64, 0x65,
|
||||
0x66, 0x61, 0x75, 0x6c, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x20, 0x63, 0x68,
|
||||
0x61, 0x6e, 0x67, 0x65, 0x64, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65,
|
||||
0x6e, 0x75, 0x6d, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x7b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73,
|
||||
0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x54, 0x68, 0x65, 0x20,
|
||||
0x6e, 0x6f, 0x64, 0x65, 0x20, 0x64, 0x69, 0x64, 0x20, 0x6e, 0x6f, 0x74,
|
||||
0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x74, 0x72, 0x65, 0x65,
|
||||
0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x72, 0x65,
|
||||
0x61, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73,
|
||||
0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x22,
|
||||
0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x75, 0x6d, 0x20, 0x64, 0x65, 0x6c,
|
||||
0x65, 0x74, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x22, 0x54, 0x68, 0x65, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x20, 0x65, 0x78,
|
||||
0x69, 0x73, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
|
||||
0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20,
|
||||
0x61, 0x6e, 0x64, 0x20, 0x77, 0x61, 0x73, 0x20, 0x64, 0x65, 0x6c, 0x65,
|
||||
0x74, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
|
||||
0x65, 0x63, 0x6f, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x22, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x65, 0x6e, 0x75, 0x6d, 0x20, 0x72, 0x65, 0x70, 0x6c,
|
||||
0x61, 0x63, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x22, 0x54, 0x68, 0x65, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x20, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x68, 0x61, 0x6e,
|
||||
0x67, 0x65, 0x64, 0x20, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e,
|
||||
0x6f, 0x64, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6d, 0x6f, 0x76, 0x65,
|
||||
0x64, 0x20, 0x66, 0x6f, 0x72, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x73, 0x2f,
|
||||
0x61, 0x6e, 0x79, 0x78, 0x6d, 0x6c, 0x2f, 0x61, 0x6e, 0x79, 0x64, 0x61,
|
||||
0x74, 0x61, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x73, 0x65, 0x72, 0x2d,
|
||||
0x6f, 0x72, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x73, 0x74,
|
||||
0x73, 0x2f, 0x6c, 0x65, 0x61, 0x66, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x73,
|
||||
0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x6c,
|
||||
0x79, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72,
|
||||
0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x22, 0x52, 0x46,
|
||||
0x43, 0x36, 0x32, 0x34, 0x31, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x20, 0x37, 0x2e, 0x32, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x4f, 0x70, 0x65, 0x72,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x6e,
|
||||
0x6f, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x64, 0x69, 0x66,
|
||||
0x66, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x61, 0x20, 0x6e, 0x6f, 0x64, 0x65,
|
||||
0x20, 0x68, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x6f, 0x70, 0x65, 0x72,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x68, 0x65,
|
||||
0x72, 0x69, 0x74, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x69,
|
||||
0x74, 0x73, 0x20, 0x6e, 0x65, 0x61, 0x72, 0x65, 0x73, 0x74, 0x20, 0x70,
|
||||
0x61, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61,
|
||||
0x6e, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x6f, 0x70, 0x2d,
|
||||
0x6c, 0x65, 0x76, 0x65, 0x6c, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x20,
|
||||
0x6d, 0x75, 0x73, 0x74, 0x20, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x20,
|
||||
0x68, 0x61, 0x76, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x70, 0x65, 0x72,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x55, 0x73, 0x65, 0x72, 0x2d, 0x6f, 0x72, 0x64, 0x65,
|
||||
0x72, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x73, 0x2f, 0x6c, 0x65,
|
||||
0x61, 0x66, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x73, 0x20, 0x77, 0x69, 0x74,
|
||||
0x68, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
|
||||
0x27, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x27, 0x20, 0x61, 0x6e, 0x64,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x27, 0x72, 0x65, 0x70,
|
||||
0x6c, 0x61, 0x63, 0x65, 0x27, 0x20, 0x4d, 0x55, 0x53, 0x54, 0x20, 0x61,
|
||||
0x6c, 0x73, 0x6f, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65,
|
||||
0x20, 0x27, 0x6b, 0x65, 0x79, 0x27, 0x2c, 0x20, 0x27, 0x76, 0x61, 0x6c,
|
||||
0x75, 0x65, 0x27, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x27, 0x70, 0x6f, 0x73,
|
||||
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x27, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x20, 0x64,
|
||||
0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x20, 0x49, 0x74, 0x20, 0x73,
|
||||
0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65,
|
||||
0x20, 0x70, 0x72, 0x65, 0x63, 0x65, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x69,
|
||||
0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x49, 0x6e, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x6f, 0x66,
|
||||
0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61,
|
||||
0x74, 0x61, 0x20, 0x69, 0x73, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2c,
|
||||
0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x20, 0x77, 0x61,
|
||||
0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x72, 0x65,
|
||||
0x61, 0x74, 0x65, 0x64, 0x2f, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x6f,
|
||||
0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20,
|
||||
0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
|
||||
0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65,
|
||||
0x61, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x64, 0x69,
|
||||
0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x20, 0x6f, 0x70, 0x65,
|
||||
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x73, 0x69, 0x6d, 0x69,
|
||||
0x6c, 0x61, 0x72, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x62, 0x75,
|
||||
0x74, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x66,
|
||||
0x75, 0x72, 0x74, 0x68, 0x65, 0x72, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72,
|
||||
0x69, 0x63, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x69,
|
||||
0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68,
|
||||
0x65, 0x79, 0x20, 0x61, 0x72, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20,
|
||||
0x66, 0x6f, 0x72, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x61, 0x20, 0x73,
|
||||
0x75, 0x62, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x65,
|
||||
0x2d, 0x63, 0x61, 0x73, 0x65, 0x73, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x6d, 0x64, 0x3a, 0x61, 0x6e, 0x6e, 0x6f,
|
||||
0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x69, 0x67, 0x2d,
|
||||
0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x65,
|
||||
0x61, 0x6e, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63,
|
||||
0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x22, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x20, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65,
|
||||
0x20, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x20, 0x64, 0x65,
|
||||
0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20,
|
||||
0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x2e,
|
||||
0x22, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x6d, 0x64,
|
||||
0x3a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
|
||||
0x6f, 0x72, 0x69, 0x67, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x7b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x73, 0x74,
|
||||
0x72, 0x69, 0x6e, 0x67, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65,
|
||||
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x22, 0x50, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75,
|
||||
0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61,
|
||||
0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x20, 0x6c, 0x65, 0x61,
|
||||
0x66, 0x2e, 0x20, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69,
|
||||
0x76, 0x65, 0x6c, 0x79, 0x2c, 0x20, 0x69, 0x74, 0x73, 0x20, 0x6d, 0x65,
|
||||
0x61, 0x6e, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65,
|
||||
0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x5c, 0x22, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x5c, 0x22, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62,
|
||||
0x75, 0x74, 0x65, 0x20, 0x62, 0x75, 0x74, 0x20, 0x69, 0x64, 0x65, 0x6e,
|
||||
0x74, 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f,
|
||||
0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x2d, 0x6c, 0x69, 0x73, 0x74,
|
||||
0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x72, 0x61,
|
||||
0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x6f, 0x6e, 0x65, 0x2e, 0x22, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x6d, 0x64, 0x3a, 0x61,
|
||||
0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72,
|
||||
0x69, 0x67, 0x2d, 0x6b, 0x65, 0x79, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x20,
|
||||
0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x79, 0x70, 0x65,
|
||||
0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61,
|
||||
0x6e, 0x63, 0x65, 0x2d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69,
|
||||
0x65, 0x72, 0x2d, 0x6b, 0x65, 0x79, 0x73, 0x3b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72,
|
||||
0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x22, 0x49, 0x74, 0x73, 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x69, 0x6e,
|
||||
0x67, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d,
|
||||
0x65, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x5c, 0x22, 0x6b,
|
||||
0x65, 0x79, 0x5c, 0x22, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75,
|
||||
0x74, 0x65, 0x20, 0x62, 0x75, 0x74, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74,
|
||||
0x69, 0x66, 0x69, 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61,
|
||||
0x6c, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61,
|
||||
0x6e, 0x63, 0x65, 0x20, 0x72, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74,
|
||||
0x68, 0x61, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x77, 0x20,
|
||||
0x6f, 0x6e, 0x65, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a,
|
||||
0x20, 0x20, 0x6d, 0x64, 0x3a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x69, 0x67, 0x2d, 0x70, 0x6f, 0x73,
|
||||
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x74, 0x79, 0x70, 0x65, 0x20, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x20, 0x7b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x79, 0x70,
|
||||
0x65, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x3b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x75, 0x69,
|
||||
0x6e, 0x74, 0x33, 0x32, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x61, 0x6e, 0x67, 0x65,
|
||||
0x20, 0x31, 0x2e, 0x2e, 0x6d, 0x61, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
|
||||
0x49, 0x74, 0x73, 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x69, 0x6e, 0x67, 0x20,
|
||||
0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20,
|
||||
0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x5c, 0x22, 0x70, 0x6f, 0x73,
|
||||
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5c, 0x22, 0x20, 0x61, 0x74, 0x74, 0x72,
|
||||
0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x62, 0x75, 0x74, 0x20, 0x69, 0x64,
|
||||
0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x72, 0x69, 0x67,
|
||||
0x69, 0x6e, 0x61, 0x6c, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x69, 0x6e,
|
||||
0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x72, 0x61, 0x74, 0x68, 0x65,
|
||||
0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e,
|
||||
0x65, 0x77, 0x20, 0x6f, 0x6e, 0x65, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x7d, 0x0a, 0x7d, 0x0a, 0x00
|
||||
};
|
195
models/yang@2022-06-16.yang
Normal file
195
models/yang@2022-06-16.yang
Normal file
|
@ -0,0 +1,195 @@
|
|||
module yang {
|
||||
namespace "urn:ietf:params:xml:ns:yang:1";
|
||||
prefix yang;
|
||||
yang-version 1.1;
|
||||
|
||||
import ietf-yang-metadata {
|
||||
prefix md;
|
||||
revision-date 2016-08-05;
|
||||
}
|
||||
|
||||
organization
|
||||
"libyang";
|
||||
|
||||
contact
|
||||
"Web: <https://github.com/CESNET/libyang/>
|
||||
Author: Radek Krejci <rkrejci@cesnet.cz>
|
||||
Author: Michal Vasko <mvasko@cesnet.cz>";
|
||||
|
||||
description
|
||||
"This is a dummy module with no data formally supplying the definitions
|
||||
of various metadata defined in RFC 6020 and RFC 7950. There are
|
||||
additional metadata used in libyang diff data format.";
|
||||
|
||||
revision 2022-06-16 {
|
||||
description
|
||||
"Added typedef for key metadata type.";
|
||||
}
|
||||
|
||||
revision 2021-04-07 {
|
||||
description
|
||||
"Added metadata for key-less list and state leaf-list diff.";
|
||||
}
|
||||
|
||||
revision 2020-06-17 {
|
||||
description
|
||||
"Added metadata for diff.";
|
||||
}
|
||||
|
||||
revision 2017-02-20 {
|
||||
description
|
||||
"Added metadata for NETCONF's edit-config manipulation with ordered
|
||||
lists and leaf-lists.";
|
||||
reference
|
||||
"RFC 7950: The YANG 1.1 Data Modeling Language";
|
||||
}
|
||||
|
||||
revision 2016-02-11 {
|
||||
description
|
||||
"Initial revision";
|
||||
reference
|
||||
"RFC 6020: YANG - A Data Modeling Language for
|
||||
the Network Configuration Protocol (NETCONF)";
|
||||
}
|
||||
|
||||
typedef instance-identifier-keys {
|
||||
type string;
|
||||
reference "RFC7950 section 7.8.6.";
|
||||
description
|
||||
"The key predicates of the full instance-identifier built-in type.";
|
||||
}
|
||||
|
||||
md:annotation insert {
|
||||
type enumeration {
|
||||
enum first;
|
||||
enum last;
|
||||
enum before;
|
||||
enum after;
|
||||
}
|
||||
reference "RFC7950 section 7.8.6. and section 7.7.9.";
|
||||
description
|
||||
"In user ordered leaf-list, this attribute can be used to control
|
||||
where in the leaf-list the entry is inserted. It can be used during
|
||||
the NETCONF <edit-config> \"create\" operations to insert a new list or
|
||||
leaf-list entry, or during \"merge\" or \"replace\" operations to insert
|
||||
a new list or leaf-list entry or move an existing one.
|
||||
|
||||
If the value is \"before\" or \"after\", the \"value\"/\"key\" attribute
|
||||
MUST also be used to specify an existing entry in the list or leaf-list.
|
||||
|
||||
If no \"insert\" attribute is present in the \"create\" operation, it
|
||||
defaults to \"last\".";
|
||||
}
|
||||
|
||||
md:annotation value {
|
||||
type string;
|
||||
reference "RFC7950 section 7.7.9.";
|
||||
description
|
||||
"In user ordered leaf-list, this attribute must be used if the attribute
|
||||
insert is used and specifies before/after which existing instance the
|
||||
new instance should be inserted.";
|
||||
}
|
||||
|
||||
md:annotation key {
|
||||
type union {
|
||||
type empty;
|
||||
type instance-identifier-keys;
|
||||
}
|
||||
reference "RFC7950 section 7.8.6.";
|
||||
description
|
||||
"In user ordered list, this attribute must be used if the attribute
|
||||
insert is used and specifies before/after which existing instance the
|
||||
new instance should be inserted.";
|
||||
}
|
||||
|
||||
md:annotation position {
|
||||
type union {
|
||||
type empty;
|
||||
type uint32 {
|
||||
range 1..max;
|
||||
}
|
||||
}
|
||||
description
|
||||
"In key-less list or state leaf-list, this attribute must be used if
|
||||
the attribute insert is used and specifies the instance position
|
||||
before/after which the new instance should be inserted.";
|
||||
}
|
||||
|
||||
md:annotation operation {
|
||||
type enumeration {
|
||||
enum none {
|
||||
description
|
||||
"The node existed in both data trees but there is a nested node
|
||||
with another operation. In case of a leaf, only its default
|
||||
flag changed.";
|
||||
}
|
||||
enum create {
|
||||
description
|
||||
"The node did not exist in the first tree and was created in the
|
||||
second tree.";
|
||||
}
|
||||
enum delete {
|
||||
description
|
||||
"The node existed in the first tree and was deleted in the second
|
||||
tree.";
|
||||
}
|
||||
enum replace {
|
||||
description
|
||||
"The node value was changed or the node was moved for
|
||||
leaves/anyxml/anydata and user-ordered lists/leaf-lists,
|
||||
respectively.";
|
||||
}
|
||||
}
|
||||
reference "RFC6241 section 7.2.";
|
||||
description
|
||||
"Operation of a node in a diff. If a node has no operation,
|
||||
it is inherited from its nearest parent with an operation.
|
||||
Top-level nodes must always have an operation.
|
||||
|
||||
User-ordered lists/leaf-lists with operation 'create' and
|
||||
'replace' MUST also have the 'key', 'value', or 'position'
|
||||
metadata defined. It specifies the preceding instance.
|
||||
In case the value of this metadata is empty, the node was
|
||||
created/moved on the first position.
|
||||
|
||||
All the operations keep the meaning of edit-config operations
|
||||
with similar names but some are further restricted, meaning
|
||||
they are used for only a subset of use-cases.";
|
||||
}
|
||||
|
||||
md:annotation orig-default {
|
||||
type boolean;
|
||||
description
|
||||
"Information about the previous default state of the node.";
|
||||
}
|
||||
|
||||
md:annotation orig-value {
|
||||
type string;
|
||||
description
|
||||
"Previous value of a changed leaf. Alternatively, its meaning
|
||||
is the same as the \"value\" attribute but identifies the original
|
||||
leaf-list instance rather than the new one.";
|
||||
}
|
||||
|
||||
md:annotation orig-key {
|
||||
type union {
|
||||
type empty;
|
||||
type instance-identifier-keys;
|
||||
}
|
||||
description
|
||||
"Its meaning is the same as the \"key\" attribute but identifies
|
||||
the original list instance rather than the new one.";
|
||||
}
|
||||
|
||||
md:annotation orig-position {
|
||||
type union {
|
||||
type empty;
|
||||
type uint32 {
|
||||
range 1..max;
|
||||
}
|
||||
}
|
||||
description
|
||||
"Its meaning is the same as the \"position\" attribute but identifies
|
||||
the original list instance rather than the new one.";
|
||||
}
|
||||
}
|
1413
src/context.c
Normal file
1413
src/context.c
Normal file
File diff suppressed because it is too large
Load diff
673
src/context.h
Normal file
673
src/context.h
Normal file
|
@ -0,0 +1,673 @@
|
|||
/**
|
||||
* @file context.h
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief internal context structures and functions
|
||||
*
|
||||
* Copyright (c) 2015 - 2023 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef LY_CONTEXT_H_
|
||||
#define LY_CONTEXT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "parser_schema.h"
|
||||
#include "tree_data.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct lys_module;
|
||||
|
||||
/**
|
||||
* @page howtoContext Context
|
||||
*
|
||||
* The context concept allows callers to work in environments with different sets of YANG modules.
|
||||
*
|
||||
* The first step with libyang is to create a new context using ::ly_ctx_new(). It returns a handler used in the following work.
|
||||
* Note that the context is supposed to provide a stable environment for work with the data. Therefore the caller should prepare
|
||||
* a complete context and after starting working with the data, the context and its content should not change. If it does,
|
||||
* in most cases it leads to the context being recompiled and any parsed data invalid. Despite the API not enforcing this
|
||||
* approach, it may change in future versions in the form of a locking mechanism which would allow further
|
||||
* optimization of data manipulation. Also note that modules cannot be removed from their context. If you need to change the set
|
||||
* of the schema modules in the context, the recommended way is to create a new context. To remove the context, there is ::ly_ctx_destroy() function.
|
||||
*
|
||||
* The context has [several options](@ref contextoptions) changing behavior when processing YANG modules being inserted. The
|
||||
* specific behavior is mentioned below. All the options can be set as a parameter when the context is being created or later
|
||||
* with ::ly_ctx_set_options().
|
||||
*
|
||||
* When creating a new context, another optional parameter is search_dir It provide directory where libyang
|
||||
* will automatically search for YANG modules being imported or included. There is actually a set of search paths which can be later
|
||||
* modified using ::ly_ctx_set_searchdir(), ::ly_ctx_unset_searchdir() and ::ly_ctx_unset_searchdir_last() functions. Before the values
|
||||
* in the set are used, also the current working directory is (non-recursively) searched. For the case of the explicitly set
|
||||
* search directories, they are searched recursively - all their subdirectories (and symlinks) are taken into account. Searching
|
||||
* in the current working directory can be avoided with the context's ::LY_CTX_DISABLE_SEARCHDIR_CWD option.
|
||||
* Searching in all the context's search dirs (without removing them) can be avoided with the context's
|
||||
* ::LY_CTX_DISABLE_SEARCHDIRS option (or via ::ly_ctx_set_options()). This automatic searching can be preceded
|
||||
* by a custom module searching callback (::ly_module_imp_clb) set via ::ly_ctx_set_module_imp_clb(). The algorithm of
|
||||
* searching in search dirs is also available via API as ::lys_search_localfile() function.
|
||||
*
|
||||
* YANG modules are added into the context using [parser functions](@ref howtoSchemaParsers) - \b lys_parse*().
|
||||
* Alternatively, also ::ly_ctx_load_module() can be used - in that case the ::ly_module_imp_clb or automatic
|
||||
* search in search directories and in the current working directory is used, as described above. YANG submodules cannot be loaded
|
||||
* or even validated directly, they are loaded always only as includes of YANG modules. Explicitly parsed/loaded modules are
|
||||
* handled as implemented - libyang is able to instantiate data representing such a module. The modules loaded implicitly, are
|
||||
* not implemented and serve only as a source of grouping or typedef definitions. Context can hold multiple revisions of the same
|
||||
* YANG module, but only one of them can be implemented. Details about the difference between implemented and imported modules
|
||||
* can be found on @ref howtoSchema page. This behavior can be changed with the context's ::LY_CTX_ALL_IMPLEMENTED option, which
|
||||
* causes that all the parsed modules, whether loaded explicitly or implicitly, are set to be implemented. Note, that as
|
||||
* a consequence of this option, only a single revision of any module can be present in the context in this case. Also, a less
|
||||
* crude option ::LY_CTX_REF_IMPLEMENTED can be used to implement only referenced modules that should also be implemented.
|
||||
*
|
||||
* When loading/importing a module without revision, the latest revision of the required module is supposed to load.
|
||||
* For a context, the first time the latest revision of a module is requested, it is properly searched for and loaded.
|
||||
* However, when this module is requested (without revision) the second time, the one found previously is returned.
|
||||
* This has the advantage of not searching for the module repeatedly but there is a drawback in case the content of search
|
||||
* directories is updated and a later revision become available.
|
||||
*
|
||||
* Context holds all the schema modules internally. To get a specific module, use ::ly_ctx_get_module() (or some of its
|
||||
* variants). If you need to do something with all the modules in the context, it is advised to iterate over them using
|
||||
* ::ly_ctx_get_module_iter(). Alternatively, the ::ly_ctx_get_yanglib_data() function can be used to get complex information about the schemas in the context
|
||||
* in the form of data tree defined by <a href="https://tools.ietf.org/html/rfc7895">ietf-yang-library</a> module.
|
||||
*
|
||||
* YANG data can be parsed by \b lyd_parse_*() functions. Note, that functions for schema have \b lys_
|
||||
* prefix (or \b lysp_ for the parsed and \b lysc_ for the compiled schema - for details see @ref howtoSchema page) while
|
||||
* functions for instance data have \b lyd_ prefix. Details about data formats or handling data without the appropriate
|
||||
* YANG module in context can be found on @ref howtoData page.
|
||||
*
|
||||
* Besides the YANG modules, context holds also [error information](@ref howtoErrors) and
|
||||
* [database of strings](@ref howtoContextDict), both connected with the processed YANG modules and data.
|
||||
*
|
||||
* - @subpage howtoErrors
|
||||
* - @subpage howtoContextDict
|
||||
*
|
||||
* \note API for this group of functions is available in the [context module](@ref context).
|
||||
*
|
||||
* Functions List
|
||||
* --------------
|
||||
*
|
||||
* - ::ly_ctx_new()
|
||||
* - ::ly_ctx_destroy()
|
||||
*
|
||||
* - ::ly_ctx_set_searchdir()
|
||||
* - ::ly_ctx_get_searchdirs()
|
||||
* - ::ly_ctx_unset_searchdir()
|
||||
* - ::ly_ctx_unset_searchdir_last()
|
||||
*
|
||||
* - ::ly_ctx_set_options()
|
||||
* - ::ly_ctx_get_options()
|
||||
* - ::ly_ctx_unset_options()
|
||||
*
|
||||
* - ::ly_ctx_set_module_imp_clb()
|
||||
* - ::ly_ctx_get_module_imp_clb()
|
||||
*
|
||||
* - ::ly_ctx_load_module()
|
||||
* - ::ly_ctx_get_module_iter()
|
||||
* - ::ly_ctx_get_module()
|
||||
* - ::ly_ctx_get_module_ns()
|
||||
* - ::ly_ctx_get_module_implemented()
|
||||
* - ::ly_ctx_get_module_implemented_ns()
|
||||
* - ::ly_ctx_get_module_latest()
|
||||
* - ::ly_ctx_get_module_latest_ns()
|
||||
* - ::ly_ctx_get_submodule()
|
||||
* - ::ly_ctx_get_submodule_latest()
|
||||
* - ::ly_ctx_get_submodule2()
|
||||
* - ::ly_ctx_get_submodule2_latest()
|
||||
*
|
||||
* - ::ly_ctx_get_yanglib_data()
|
||||
*
|
||||
* - ::ly_ctx_get_change_count()
|
||||
* - ::ly_ctx_internal_modules_count()
|
||||
*
|
||||
* - ::lys_search_localfile()
|
||||
* - ::lys_set_implemented()
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup context Context
|
||||
* @{
|
||||
*
|
||||
* Structures and functions to manipulate with the libyang context containers.
|
||||
*
|
||||
* The \em context concept allows callers to work in environments with different sets of YANG schemas.
|
||||
* More detailed information can be found at @ref howtoContext page.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @struct ly_ctx
|
||||
* @brief libyang context handler.
|
||||
*/
|
||||
struct ly_ctx;
|
||||
|
||||
/**
|
||||
* @ingroup context
|
||||
* @defgroup contextoptions Context options
|
||||
*
|
||||
* Options to change context behavior.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define LY_CTX_ALL_IMPLEMENTED 0x01 /**< All the imported modules of the schema being parsed are implemented. */
|
||||
#define LY_CTX_REF_IMPLEMENTED 0x02 /**< Implement all imported modules "referenced" from an implemented module.
|
||||
Normally, leafrefs, augment and deviation targets are implemented as
|
||||
specified by YANG 1.1. In addition to this, implement any modules of
|
||||
nodes referenced by when and must conditions and by any default values.
|
||||
Generally, only if all these modules are implemented, the explicitly
|
||||
implemented modules can be properly used and instantiated in data. */
|
||||
#define LY_CTX_NO_YANGLIBRARY 0x04 /**< Do not internally implement ietf-yang-library module. The option
|
||||
causes that function ::ly_ctx_get_yanglib_data() does not work (returns ::LY_EINVAL) until
|
||||
the ietf-yang-library module is loaded manually. While any revision
|
||||
of this schema can be loaded with this option, note that the only
|
||||
revisions implemented by ::ly_ctx_get_yanglib_data() are 2016-06-21 and 2019-01-04.
|
||||
This option cannot be changed on existing context. */
|
||||
#define LY_CTX_DISABLE_SEARCHDIRS 0x08 /**< Do not search for schemas in context's searchdirs neither in current
|
||||
working directory. It is entirely skipped and the only way to get
|
||||
schema data for imports or for ::ly_ctx_load_module() is to use the
|
||||
callbacks provided by caller via ::ly_ctx_set_module_imp_clb() */
|
||||
#define LY_CTX_DISABLE_SEARCHDIR_CWD 0x10 /**< Do not automatically search for schemas in current working
|
||||
directory, which is by default searched automatically (despite not
|
||||
recursively). */
|
||||
#define LY_CTX_PREFER_SEARCHDIRS 0x20 /**< When searching for schema, prefer searchdirs instead of user callback. */
|
||||
#define LY_CTX_SET_PRIV_PARSED 0x40 /**< For all compiled nodes, their private objects (::lysc_node.priv) are used
|
||||
by libyang as a reference to the corresponding parsed node (::lysp_node).
|
||||
The exception are \"case\" statements, which are omitted (shorthand),
|
||||
in that case the private objects are set to NULL.
|
||||
So if this option is set, the user must not change private objects.
|
||||
Setting this option by ::ly_ctx_set_options() may result in context recompilation.
|
||||
Resetting this option by ::ly_ctx_unset_options() cause that private
|
||||
objects will be set to NULL. */
|
||||
#define LY_CTX_EXPLICIT_COMPILE 0x80 /**< If this flag is set, the compiled modules and their schema nodes are
|
||||
not automatically updated (compiled) on any context changes. In other words, they do
|
||||
not immediately take effect. To do that, call ::ly_ctx_compile(). Changes
|
||||
requiring compilation include adding new modules, changing their features,
|
||||
and implementing parsed-only modules. This option allows efficient compiled
|
||||
context creation without redundant recompilations. */
|
||||
#define LY_CTX_ENABLE_IMP_FEATURES 0x0100 /**< By default, all features of newly implemented imported modules of
|
||||
a module that is being loaded are disabled. With this flag they all become
|
||||
enabled. */
|
||||
#define LY_CTX_LEAFREF_EXTENDED 0x0200 /**< By default, path attribute of leafref accepts only path as defined in RFC 7950.
|
||||
By using this option, the path attribute will also allow using XPath functions as deref() */
|
||||
#define LY_CTX_LEAFREF_LINKING 0x0400 /**< Link valid leafref nodes with its target during validation if leafref node is not using
|
||||
'require-instance false;'. It also enables usage of
|
||||
[lyd_leafref_get_links](@ref lyd_leafref_get_links) and
|
||||
[lyd_leafref_link_node_tree](@ref lyd_leafref_link_node_tree) APIs. */
|
||||
#define LY_CTX_BUILTIN_PLUGINS_ONLY 0x0800 /**< By default, context uses all available plugins for types and extensions,
|
||||
both included and external. This options prevents all included plugins to be
|
||||
loaded except for built-in YANG types so all derived types will use these and
|
||||
for all purposes behave as the base type. The option can be used for cases when
|
||||
invalid data needs to be stored in YANG node values. */
|
||||
|
||||
/** @} contextoptions */
|
||||
|
||||
/**
|
||||
* @brief Create libyang context.
|
||||
*
|
||||
* Context is used to hold all information about schemas. Usually, the application is supposed
|
||||
* to work with a single context in which libyang is holding all schemas (and other internal
|
||||
* information) according to which the data trees will be processed and validated. So, the schema
|
||||
* trees are tightly connected with the specific context and they are held by the context internally
|
||||
* - caller does not need to keep pointers to the schemas returned by ::lys_parse(), context knows
|
||||
* about them. The data trees created with \b lyd_parse_*() are still connected with the specific context,
|
||||
* but they are not internally held by the context. The data tree just points and lean on some data
|
||||
* held by the context (schema tree, string dictionary, etc.). Therefore, in case of data trees, caller
|
||||
* is supposed to keep pointers returned by the \b lyd_parse_*() functions and manage the data tree on its own. This
|
||||
* also affects the number of instances of both tree types. While you can have only one instance of
|
||||
* specific schema connected with a single context, number of data tree instances is not connected.
|
||||
*
|
||||
* @param[in] search_dir Directory (or directories) where libyang will search for the imported or included modules
|
||||
* and submodules. If no such directory is available, NULL is accepted. Several directories can be specified,
|
||||
* delimited by colon ":" (on Windows, use semicolon ";" instead).
|
||||
* @param[in] options Context options, see @ref contextoptions.
|
||||
* @param[out] new_ctx Pointer to the created libyang context if LY_SUCCESS returned.
|
||||
* @return LY_ERR return value.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_ctx_new(const char *search_dir, uint16_t options, struct ly_ctx **new_ctx);
|
||||
|
||||
/**
|
||||
* @brief Create libyang context according to the provided yang-library data in a file.
|
||||
*
|
||||
* This function loads the yang-library data from the given path. If you need to pass the data as
|
||||
* string, use ::::ly_ctx_new_ylmem(). Both functions extend functionality of ::ly_ctx_new() by loading
|
||||
* modules specified in the ietf-yang-library form into the context being created.
|
||||
* The preferred tree model revision is 2019-01-04. However, only the first module-set is processed and loaded
|
||||
* into the context. If there are no matching nodes from this tree, the legacy tree (originally from model revision 2016-04-09)
|
||||
* is processed. Note, that the modules are loaded the same way as in case of ::ly_ctx_load_module(), so the schema paths in the
|
||||
* yang-library data are ignored and the modules are loaded from the context's search locations. On the other hand, YANG features
|
||||
* of the modules are set as specified in the yang-library data.
|
||||
* To get yang library data from a libyang context, use ::ly_ctx_get_yanglib_data().
|
||||
*
|
||||
* @param[in] search_dir Directory where libyang will search for the imported or included modules and submodules.
|
||||
* If no such directory is available, NULL is accepted.
|
||||
* @param[in] path Path to the file containing yang-library-data in the specified format
|
||||
* @param[in] format Format of the data in the provided file.
|
||||
* @param[in] options Context options, see @ref contextoptions.
|
||||
* @param[in,out] ctx If *ctx is not NULL, the existing libyang context is modified. Otherwise, a pointer to a
|
||||
* newly created context is returned here if LY_SUCCESS.
|
||||
* @return LY_ERR return value
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_ctx_new_ylpath(const char *search_dir, const char *path, LYD_FORMAT format, int options,
|
||||
struct ly_ctx **ctx);
|
||||
|
||||
/**
|
||||
* @brief Create libyang context according to the provided yang-library data in a string.
|
||||
*
|
||||
* Details in ::ly_ctx_new_ylpath().
|
||||
*
|
||||
* @param[in] search_dir Directory where libyang will search for the imported or included modules and submodules.
|
||||
* If no such directory is available, NULL is accepted.
|
||||
* @param[in] data String containing yang-library data in the specified format.
|
||||
* @param[in] format Format of the data in the provided file.
|
||||
* @param[in] options Context options, see @ref contextoptions.
|
||||
* @param[in,out] ctx If *ctx is not NULL, the existing libyang context is modified. Otherwise, a pointer to a
|
||||
* newly created context is returned here if LY_SUCCESS.
|
||||
* @return LY_ERR return value
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_ctx_new_ylmem(const char *search_dir, const char *data, LYD_FORMAT format, int options,
|
||||
struct ly_ctx **ctx);
|
||||
|
||||
/**
|
||||
* @brief Create libyang context according to the provided yang-library data in a data tree.
|
||||
*
|
||||
* Details in ::ly_ctx_new_ylpath().
|
||||
*
|
||||
* @param[in] search_dir Directory where libyang will search for the imported or included modules and submodules.
|
||||
* If no such directory is available, NULL is accepted.
|
||||
* @param[in] tree Data tree containing yang-library data.
|
||||
* @param[in] options Context options, see @ref contextoptions.
|
||||
* @param[in,out] ctx If *ctx is not NULL, the existing libyang context is modified. Otherwise, a pointer to a
|
||||
* newly created context is returned here if LY_SUCCESS.
|
||||
* @return LY_ERR return value
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_ctx_new_yldata(const char *search_dir, const struct lyd_node *tree, int options,
|
||||
struct ly_ctx **ctx);
|
||||
|
||||
/**
|
||||
* @brief Compile (recompile) the context applying all the performed changes after the last context compilation.
|
||||
* Should be used only if ::LY_CTX_EXPLICIT_COMPILE option is set, has no effect otherwise.
|
||||
*
|
||||
* @param[in] ctx Context to compile.
|
||||
* @return LY_ERR return value.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_ctx_compile(struct ly_ctx *ctx);
|
||||
|
||||
/**
|
||||
* @brief Add the search path into libyang context
|
||||
*
|
||||
* To reset search paths set in the context, use ::ly_ctx_unset_searchdir() and then
|
||||
* set search paths again.
|
||||
*
|
||||
* @param[in] ctx Context to be modified.
|
||||
* @param[in] search_dir New search path to add to the current paths previously set in ctx.
|
||||
* @return LY_ERR return value.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_ctx_set_searchdir(struct ly_ctx *ctx, const char *search_dir);
|
||||
|
||||
/**
|
||||
* @brief Clean the search path(s) from the libyang context
|
||||
*
|
||||
* To remove the recently added search path(s), use ::ly_ctx_unset_searchdir_last().
|
||||
*
|
||||
* @param[in] ctx Context to be modified.
|
||||
* @param[in] value Searchdir to be removed, use NULL to remove them all.
|
||||
* @return LY_ERR return value
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_ctx_unset_searchdir(struct ly_ctx *ctx, const char *value);
|
||||
|
||||
/**
|
||||
* @brief Remove the least recently added search path(s) from the libyang context.
|
||||
*
|
||||
* To remove a specific search path by its value, use ::ly_ctx_unset_searchdir().
|
||||
*
|
||||
* @param[in] ctx Context to be modified.
|
||||
* @param[in] count Number of the searchdirs to be removed (starting by the least recently added).
|
||||
* If the value is higher then the actual number of search paths, all paths are removed and no error is returned.
|
||||
* Value 0 does not change the search path set.
|
||||
* @return LY_ERR return value
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_ctx_unset_searchdir_last(struct ly_ctx *ctx, uint32_t count);
|
||||
|
||||
/**
|
||||
* @brief Get the NULL-terminated list of the search paths in libyang context. Do not modify the result!
|
||||
*
|
||||
* @param[in] ctx Context to query.
|
||||
* @return NULL-terminated list (array) of the search paths, NULL if no searchpath was set.
|
||||
* Do not modify the provided data in any way!
|
||||
*/
|
||||
LIBYANG_API_DECL const char * const *ly_ctx_get_searchdirs(const struct ly_ctx *ctx);
|
||||
|
||||
/**
|
||||
* @brief Get the currently set context's options.
|
||||
*
|
||||
* @param[in] ctx Context to query.
|
||||
* @return Combination of all the currently set context's options, see @ref contextoptions.
|
||||
*/
|
||||
LIBYANG_API_DECL uint16_t ly_ctx_get_options(const struct ly_ctx *ctx);
|
||||
|
||||
/**
|
||||
* @brief Set some of the context's options, see @ref contextoptions.
|
||||
* @param[in] ctx Context to be modified.
|
||||
* @param[in] option Combination of the context's options to be set, see @ref contextoptions.
|
||||
* If there is to be a change to ::LY_CTX_SET_PRIV_PARSED, the context will be recompiled
|
||||
* and all ::lysc_node.priv in the modules will be overwritten, see ::LY_CTX_SET_PRIV_PARSED.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_ctx_set_options(struct ly_ctx *ctx, uint16_t option);
|
||||
|
||||
/**
|
||||
* @brief Unset some of the context's options, see @ref contextoptions.
|
||||
* @param[in] ctx Context to be modified.
|
||||
* @param[in] option Combination of the context's options to be unset, see @ref contextoptions.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_ctx_unset_options(struct ly_ctx *ctx, uint16_t option);
|
||||
|
||||
/**
|
||||
* @brief Get the change count of the context (module set) during its life-time.
|
||||
*
|
||||
* @param[in] ctx Context to be examined.
|
||||
* @return Context change count.
|
||||
*/
|
||||
LIBYANG_API_DECL uint16_t ly_ctx_get_change_count(const struct ly_ctx *ctx);
|
||||
|
||||
/**
|
||||
* @brief Get the hash of all the modules in the context. Since order of the modules is significant,
|
||||
* even when 2 contexts have the same modules but loaded in a different order, the hash will differ.
|
||||
*
|
||||
* Hash consists of all module names (1), their revisions (2), all enabled features (3), and their
|
||||
* imported/implemented state (4).
|
||||
*
|
||||
* @param[in] ctx Context to be examined.
|
||||
* @return Context modules hash.
|
||||
*/
|
||||
LIBYANG_API_DECL uint32_t ly_ctx_get_modules_hash(const struct ly_ctx *ctx);
|
||||
|
||||
/**
|
||||
* @brief Callback for freeing returned module data in #ly_module_imp_clb.
|
||||
*
|
||||
* @param[in] module_data Data to free.
|
||||
* @param[in] user_data User-supplied callback data, same as for #ly_module_imp_clb.
|
||||
*/
|
||||
typedef void (*ly_module_imp_data_free_clb)(void *module_data, void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Callback for retrieving missing included or imported models in a custom way.
|
||||
*
|
||||
* When @p submod_name is provided, the submodule is requested instead of the module (in this case only
|
||||
* the module name without its revision is provided).
|
||||
*
|
||||
* If an @arg free_module_data callback is provided, it will be used later to free the allegedly const data
|
||||
* which were returned by this callback.
|
||||
*
|
||||
* @param[in] mod_name Missing module name.
|
||||
* @param[in] mod_rev Optional missing module revision. If NULL and submod_name is not provided, the latest revision is
|
||||
* requested, the parsed module is then marked by the latest_revision flag.
|
||||
* @param[in] submod_name Optional missing submodule name.
|
||||
* @param[in] submod_rev Optional missing submodule revision. If NULL and submod_name is provided, the latest revision is
|
||||
* requested, the parsed submodule is then marked by the latest_revision flag.
|
||||
* @param[in] user_data User-supplied callback data.
|
||||
* @param[out] format Format of the returned module data.
|
||||
* @param[out] module_data Requested module data.
|
||||
* @param[out] free_module_data Callback for freeing the returned module data. If not set, the data will be left untouched.
|
||||
* @return LY_ERR value. If the returned value differs from LY_SUCCESS, libyang continue in trying to get the module data
|
||||
* according to the settings of its mechanism to search for the imported/included schemas.
|
||||
*/
|
||||
typedef LY_ERR (*ly_module_imp_clb)(const char *mod_name, const char *mod_rev, const char *submod_name, const char *submod_rev,
|
||||
void *user_data, LYS_INFORMAT *format, const char **module_data, ly_module_imp_data_free_clb *free_module_data);
|
||||
|
||||
/**
|
||||
* @brief Get the custom callback for missing import/include module retrieval.
|
||||
*
|
||||
* @param[in] ctx Context to read from.
|
||||
* @param[in] user_data Optional pointer for getting the user-supplied callback data.
|
||||
* @return Callback or NULL if not set.
|
||||
*/
|
||||
LIBYANG_API_DECL ly_module_imp_clb ly_ctx_get_module_imp_clb(const struct ly_ctx *ctx, void **user_data);
|
||||
|
||||
/**
|
||||
* @brief Set missing include or import module callback. It is meant to be used when the models
|
||||
* are not locally available (such as when downloading modules from a NETCONF server), it should
|
||||
* not be required in other cases.
|
||||
*
|
||||
* @param[in] ctx Context that will use this callback.
|
||||
* @param[in] clb Callback responsible for returning the missing model.
|
||||
* @param[in] user_data Arbitrary data that will always be passed to the callback @p clb.
|
||||
*/
|
||||
LIBYANG_API_DECL void ly_ctx_set_module_imp_clb(struct ly_ctx *ctx, ly_module_imp_clb clb, void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Callback for getting arbitrary run-time data required by an extension instance.
|
||||
*
|
||||
* @param[in] ext Compiled extension instance.
|
||||
* @param[in] user_data User-supplied callback data.
|
||||
* @param[out] ext_data Provided extension instance data.
|
||||
* @param[out] ext_data_free Whether the extension instance should free @p ext_data or not.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
typedef LY_ERR (*ly_ext_data_clb)(const struct lysc_ext_instance *ext, void *user_data, void **ext_data,
|
||||
ly_bool *ext_data_free);
|
||||
|
||||
/**
|
||||
* @brief Set callback providing run-time extension instance data. The expected data depend on the extension.
|
||||
* Data expected by internal extensions:
|
||||
*
|
||||
* - *ietf-yang-schema-mount:mount-point* (struct lyd_node \*\*ext_data)\n
|
||||
* Operational data tree with at least `ietf-yang-library` data describing the mounted schema and
|
||||
* `ietf-yang-schema-mount` **validated** data describing the specific mount point
|
||||
* ([ref](https://datatracker.ietf.org/doc/html/rfc8528#section-3.3)).
|
||||
*
|
||||
* @param[in] ctx Context that will use this callback.
|
||||
* @param[in] clb Callback responsible for returning the extension instance data.
|
||||
* @param[in] user_data Arbitrary data that will always be passed to the callback @p clb.
|
||||
*/
|
||||
LIBYANG_API_DECL ly_ext_data_clb ly_ctx_set_ext_data_clb(struct ly_ctx *ctx, ly_ext_data_clb clb, void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Get YANG module of the given name and revision.
|
||||
*
|
||||
* @param[in] ctx Context to work in.
|
||||
* @param[in] name Name of the YANG module to get.
|
||||
* @param[in] revision Requested revision date of the YANG module to get. If not specified,
|
||||
* the schema with no revision is returned, if it is present in the context.
|
||||
* @return Pointer to the YANG module, NULL if no schema in the context follows the name and revision requirements.
|
||||
*/
|
||||
LIBYANG_API_DECL struct lys_module *ly_ctx_get_module(const struct ly_ctx *ctx, const char *name, const char *revision);
|
||||
|
||||
/**
|
||||
* @brief Get the latest revision of the YANG module specified by its name.
|
||||
*
|
||||
* YANG modules with no revision are supposed to be the oldest one.
|
||||
*
|
||||
* @param[in] ctx Context where to search.
|
||||
* @param[in] name Name of the YANG module to get.
|
||||
* @return The latest revision of the specified YANG module in the given context, NULL if no YANG module of the
|
||||
* given name is present in the context.
|
||||
*/
|
||||
LIBYANG_API_DECL struct lys_module *ly_ctx_get_module_latest(const struct ly_ctx *ctx, const char *name);
|
||||
|
||||
/**
|
||||
* @brief Get the (only) implemented YANG module specified by its name.
|
||||
*
|
||||
* @param[in] ctx Context where to search.
|
||||
* @param[in] name Name of the YANG module to get.
|
||||
* @return The only implemented YANG module revision of the given name in the given context. NULL if there is no
|
||||
* implemented module of the given name.
|
||||
*/
|
||||
LIBYANG_API_DECL struct lys_module *ly_ctx_get_module_implemented(const struct ly_ctx *ctx, const char *name);
|
||||
|
||||
/**
|
||||
* @brief Iterate over all modules in the given context.
|
||||
*
|
||||
* @param[in] ctx Context with the modules.
|
||||
* @param[in,out] index Index of the next module to get. Value of 0 starts from the beginning.
|
||||
* The value is updated with each call, so to iterate over all modules the same variable is supposed
|
||||
* to be used in all calls starting with value 0.
|
||||
* @return Next context module, NULL if the last was already returned.
|
||||
*/
|
||||
LIBYANG_API_DECL struct lys_module *ly_ctx_get_module_iter(const struct ly_ctx *ctx, uint32_t *index);
|
||||
|
||||
/**
|
||||
* @brief Get YANG module of the given namespace and revision.
|
||||
*
|
||||
* @param[in] ctx Context to work in.
|
||||
* @param[in] ns Namespace of the YANG module to get.
|
||||
* @param[in] revision Requested revision date of the YANG module to get. If not specified,
|
||||
* the schema with no revision is returned, if it is present in the context.
|
||||
* @return Pointer to the YANG module, NULL if no schema in the context follows the namespace and revision requirements.
|
||||
*/
|
||||
LIBYANG_API_DECL struct lys_module *ly_ctx_get_module_ns(const struct ly_ctx *ctx, const char *ns, const char *revision);
|
||||
|
||||
/**
|
||||
* @brief Get the latest revision of the YANG module specified by its namespace.
|
||||
*
|
||||
* YANG modules with no revision are supposed to be the oldest one.
|
||||
*
|
||||
* @param[in] ctx Context where to search.
|
||||
* @param[in] ns Namespace of the YANG module to get.
|
||||
* @return The latest revision of the specified YANG module in the given context, NULL if no YANG module of the
|
||||
* given namespace is present in the context.
|
||||
*/
|
||||
LIBYANG_API_DECL struct lys_module *ly_ctx_get_module_latest_ns(const struct ly_ctx *ctx, const char *ns);
|
||||
|
||||
/**
|
||||
* @brief Get the (only) implemented YANG module specified by its namespace.
|
||||
*
|
||||
* @param[in] ctx Context where to search.
|
||||
* @param[in] ns Namespace of the YANG module to get.
|
||||
* @return The only implemented YANG module revision of the given namespace in the given context. NULL if there is no
|
||||
* implemented module of the given namespace.
|
||||
*/
|
||||
LIBYANG_API_DECL struct lys_module *ly_ctx_get_module_implemented_ns(const struct ly_ctx *ctx, const char *ns);
|
||||
|
||||
/**
|
||||
* @brief Get a specific submodule from context. If its belongs-to module is known, use ::ly_ctx_get_submodule2().
|
||||
*
|
||||
* @param[in] ctx libyang context to search in.
|
||||
* @param[in] submodule Submodule name to find.
|
||||
* @param[in] revision Revision of the submodule to find, NULL for a submodule without a revision.
|
||||
* @return Found submodule, NULL if there is none.
|
||||
*/
|
||||
LIBYANG_API_DECL const struct lysp_submodule *ly_ctx_get_submodule(const struct ly_ctx *ctx, const char *submodule,
|
||||
const char *revision);
|
||||
|
||||
/**
|
||||
* @brief Get the latests revision of a submodule from context. If its belongs-to module is known,
|
||||
* use ::ly_ctx_get_submodule2_latest().
|
||||
*
|
||||
* @param[in] ctx libyang context to search in.
|
||||
* @param[in] submodule Submodule name to find.
|
||||
* @return Found submodule, NULL if there is none.
|
||||
*/
|
||||
LIBYANG_API_DECL const struct lysp_submodule *ly_ctx_get_submodule_latest(const struct ly_ctx *ctx, const char *submodule);
|
||||
|
||||
/**
|
||||
* @brief Get a specific submodule from a module. If the belongs-to module is not known, use ::ly_ctx_get_submodule().
|
||||
*
|
||||
* @param[in] module Belongs-to module to search in.
|
||||
* @param[in] submodule Submodule name to find.
|
||||
* @param[in] revision Revision of the submodule to find, NULL for a submodule without a revision.
|
||||
* @return Found submodule, NULL if there is none.
|
||||
*/
|
||||
LIBYANG_API_DECL const struct lysp_submodule *ly_ctx_get_submodule2(const struct lys_module *module, const char *submodule,
|
||||
const char *revision);
|
||||
|
||||
/**
|
||||
* @brief Get the latest revision of a submodule from a module. If the belongs-to module is not known,
|
||||
* use ::ly_ctx_get_submodule_latest().
|
||||
*
|
||||
* @param[in] module Belongs-to module to search in.
|
||||
* @param[in] submodule Submodule name to find.
|
||||
* @return Found submodule, NULL if there is none.
|
||||
*/
|
||||
LIBYANG_API_DECL const struct lysp_submodule *ly_ctx_get_submodule2_latest(const struct lys_module *module,
|
||||
const char *submodule);
|
||||
|
||||
/**
|
||||
* @brief Learn the number of internal modules of a context. Internal modules
|
||||
* is considered one that was loaded during the context creation.
|
||||
*
|
||||
* @param[in] ctx libyang context to examine.
|
||||
* @return Number of internal modules.
|
||||
*/
|
||||
LIBYANG_API_DECL uint32_t ly_ctx_internal_modules_count(const struct ly_ctx *ctx);
|
||||
|
||||
/**
|
||||
* @brief Try to find the model in the searchpaths of \p ctx and load it into it. If custom missing
|
||||
* module callback is set, it is used instead.
|
||||
*
|
||||
* The context itself is searched for the requested module first. If \p revision is not specified
|
||||
* (the module of the latest revision is requested) and there is implemented revision of the requested
|
||||
* module in the context, this implemented revision is returned despite there might be a newer revision.
|
||||
* This behavior is cause by the fact that it is not possible to have multiple implemented revisions of
|
||||
* the same module in the context.
|
||||
*
|
||||
* @param[in] ctx Context to add to.
|
||||
* @param[in] name Name of the module to load.
|
||||
* @param[in] revision Optional revision date of the module. If not specified, the latest revision is loaded.
|
||||
* @param[in] features Optional array of features ended with NULL to be enabled if the module is being implemented.
|
||||
* The feature string '*' enables all and array of length 1 with only the terminating NULL explicitly disables all
|
||||
* the features. In case the parameter is NULL, the features are untouched - left disabled in newly loaded module or
|
||||
* with the current features settings in case the module is already present in the context.
|
||||
* @return Pointer to the data model structure, NULL if not found or some error occurred.
|
||||
*/
|
||||
LIBYANG_API_DECL struct lys_module *ly_ctx_load_module(struct ly_ctx *ctx, const char *name, const char *revision,
|
||||
const char **features);
|
||||
|
||||
/**
|
||||
* @brief Get data of the internal ietf-yang-library module with information about all the loaded modules.
|
||||
* ietf-yang-library module must be loaded.
|
||||
*
|
||||
* Note that "/ietf-yang-library:yang-library/datastore" list instances are not created and should be
|
||||
* appended by the caller. There is a single "/ietf-yang-library:yang-library/schema" instance created
|
||||
* with the key value "complete".
|
||||
*
|
||||
* If the data identifier can be limited to the existence and changes of this context, the following
|
||||
* last 2 parameters can be used:
|
||||
*
|
||||
* "%u" as @p content_id_format and ::ly_ctx_get_change_count() as its parameter;
|
||||
* "%u" as @p content_id_format and ::ly_ctx_get_modules_hash() as its parameter.
|
||||
*
|
||||
* @param[in] ctx Context with the modules.
|
||||
* @param[out] root Generated yang-library data.
|
||||
* @param[in] content_id_format Format string (printf-like) for the yang-library data identifier, which is
|
||||
* the "content_id" node in the 2019-01-04 revision of ietf-yang-library.
|
||||
* @param[in] ... Parameters for @p content_id_format.
|
||||
* @return LY_ERR value
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_ctx_get_yanglib_data(const struct ly_ctx *ctx, struct lyd_node **root,
|
||||
const char *content_id_format, ...);
|
||||
|
||||
/**
|
||||
* @brief Free all internal structures of the specified context.
|
||||
*
|
||||
* The function should be used before terminating the application to destroy
|
||||
* and free all structures internally used by libyang. If the caller uses
|
||||
* multiple contexts, the function should be called for each used context.
|
||||
*
|
||||
* All instance data are supposed to be freed before destroying the context using ::lyd_free_all(), for example.
|
||||
* Data models (schemas) are destroyed automatically as part of ::ly_ctx_destroy() call.
|
||||
*
|
||||
* Note that the data stored by user into the ::lysc_node.priv pointer are kept
|
||||
* untouched and the caller is responsible for freeing this private data.
|
||||
*
|
||||
* @param[in] ctx libyang context to destroy
|
||||
*/
|
||||
LIBYANG_API_DECL void ly_ctx_destroy(struct ly_ctx *ctx);
|
||||
|
||||
/** @} context */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LY_CONTEXT_H_ */
|
271
src/dict.c
Normal file
271
src/dict.c
Normal file
|
@ -0,0 +1,271 @@
|
|||
/**
|
||||
* @file dict.c
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief libyang dictionary for storing strings
|
||||
*
|
||||
* Copyright (c) 2015 - 2023 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "dict.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "compat.h"
|
||||
#include "log.h"
|
||||
#include "ly_common.h"
|
||||
|
||||
/* starting size of the dictionary */
|
||||
#define LYDICT_MIN_SIZE 1024
|
||||
|
||||
/**
|
||||
* @brief Comparison callback for dictionary's hash table
|
||||
*
|
||||
* Implementation of ::lyht_value_equal_cb.
|
||||
*/
|
||||
static ly_bool
|
||||
lydict_val_eq(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *cb_data)
|
||||
{
|
||||
const char *str1, *str2;
|
||||
size_t *len1;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, val1_p, val2_p, cb_data, 0);
|
||||
|
||||
str1 = ((struct ly_dict_rec *)val1_p)->value;
|
||||
str2 = ((struct ly_dict_rec *)val2_p)->value;
|
||||
len1 = cb_data;
|
||||
|
||||
LY_CHECK_ERR_RET(!str1, LOGARG(NULL, val1_p), 0);
|
||||
LY_CHECK_ERR_RET(!str2, LOGARG(NULL, val2_p), 0);
|
||||
|
||||
if (!strncmp(str1, str2, *len1) && !str2[*len1]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
lydict_init(struct ly_dict *dict)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, dict, );
|
||||
|
||||
dict->hash_tab = lyht_new(LYDICT_MIN_SIZE, sizeof(struct ly_dict_rec), lydict_val_eq, NULL, 1);
|
||||
LY_CHECK_ERR_RET(!dict->hash_tab, LOGINT(NULL), );
|
||||
pthread_mutex_init(&dict->lock, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
lydict_clean(struct ly_dict *dict)
|
||||
{
|
||||
struct ly_dict_rec *dict_rec = NULL;
|
||||
struct ly_ht_rec *rec = NULL;
|
||||
uint32_t hlist_idx;
|
||||
uint32_t rec_idx;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, dict, );
|
||||
|
||||
LYHT_ITER_ALL_RECS(dict->hash_tab, hlist_idx, rec_idx, rec) {
|
||||
/*
|
||||
* this should not happen, all records inserted into
|
||||
* dictionary are supposed to be removed using lydict_remove()
|
||||
* before calling lydict_clean()
|
||||
*/
|
||||
dict_rec = (struct ly_dict_rec *)rec->val;
|
||||
LOGWRN(NULL, "String \"%s\" not freed from the dictionary, refcount %" PRIu32 ".", dict_rec->value, dict_rec->refcount);
|
||||
/* if record wasn't removed before free string allocated for that record */
|
||||
#ifdef NDEBUG
|
||||
free(dict_rec->value);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* free table and destroy mutex */
|
||||
lyht_free(dict->hash_tab, NULL);
|
||||
pthread_mutex_destroy(&dict->lock);
|
||||
}
|
||||
|
||||
static ly_bool
|
||||
lydict_resize_val_eq(void *val1_p, void *val2_p, ly_bool mod, void *UNUSED(cb_data))
|
||||
{
|
||||
const char *str1, *str2;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, val1_p, val2_p, 0);
|
||||
|
||||
str1 = ((struct ly_dict_rec *)val1_p)->value;
|
||||
str2 = ((struct ly_dict_rec *)val2_p)->value;
|
||||
|
||||
LY_CHECK_ERR_RET(!str1, LOGARG(NULL, val1_p), 0);
|
||||
LY_CHECK_ERR_RET(!str2, LOGARG(NULL, val2_p), 0);
|
||||
|
||||
if (mod) {
|
||||
/* used when inserting new values */
|
||||
if (strcmp(str1, str2) == 0) {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
/* used when finding the original value again in the resized table */
|
||||
if (str1 == str2) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
lydict_remove(const struct ly_ctx *ctx, const char *value)
|
||||
{
|
||||
LY_ERR ret = LY_SUCCESS;
|
||||
size_t len;
|
||||
uint32_t hash;
|
||||
struct ly_dict_rec rec, *match = NULL;
|
||||
char *val_p;
|
||||
|
||||
if (!ctx || !value) {
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LOGDBG(LY_LDGDICT, "removing \"%s\"", value);
|
||||
|
||||
len = strlen(value);
|
||||
hash = lyht_hash(value, len);
|
||||
|
||||
/* create record for lyht_find call */
|
||||
rec.value = (char *)value;
|
||||
rec.refcount = 0;
|
||||
|
||||
pthread_mutex_lock((pthread_mutex_t *)&ctx->dict.lock);
|
||||
/* set len as data for compare callback */
|
||||
lyht_set_cb_data(ctx->dict.hash_tab, (void *)&len);
|
||||
/* check if value is already inserted */
|
||||
ret = lyht_find(ctx->dict.hash_tab, &rec, hash, (void **)&match);
|
||||
|
||||
if (ret == LY_SUCCESS) {
|
||||
LY_CHECK_ERR_GOTO(!match, LOGINT(ctx), finish);
|
||||
|
||||
/* if value is already in dictionary, decrement reference counter */
|
||||
match->refcount--;
|
||||
if (match->refcount == 0) {
|
||||
/*
|
||||
* remove record
|
||||
* save pointer to stored string before lyht_remove to
|
||||
* free it after it is removed from hash table
|
||||
*/
|
||||
val_p = match->value;
|
||||
ret = lyht_remove_with_resize_cb(ctx->dict.hash_tab, &rec, hash, lydict_resize_val_eq);
|
||||
free(val_p);
|
||||
LY_CHECK_ERR_GOTO(ret, LOGINT(ctx), finish);
|
||||
}
|
||||
} else if (ret == LY_ENOTFOUND) {
|
||||
LOGERR(ctx, LY_ENOTFOUND, "Value \"%s\" was not found in the dictionary.", value);
|
||||
} else {
|
||||
LOGINT(ctx);
|
||||
}
|
||||
|
||||
finish:
|
||||
pthread_mutex_unlock((pthread_mutex_t *)&ctx->dict.lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
dict_insert(const struct ly_ctx *ctx, char *value, size_t len, ly_bool zerocopy, const char **str_p)
|
||||
{
|
||||
LY_ERR ret = LY_SUCCESS;
|
||||
struct ly_dict_rec *match = NULL, rec;
|
||||
uint32_t hash;
|
||||
|
||||
LOGDBG(LY_LDGDICT, "inserting \"%.*s\"", (int)len, value);
|
||||
|
||||
hash = lyht_hash(value, len);
|
||||
/* set len as data for compare callback */
|
||||
lyht_set_cb_data(ctx->dict.hash_tab, (void *)&len);
|
||||
/* create record for lyht_insert */
|
||||
rec.value = value;
|
||||
rec.refcount = 1;
|
||||
|
||||
ret = lyht_insert_with_resize_cb(ctx->dict.hash_tab, (void *)&rec, hash, lydict_resize_val_eq, (void **)&match);
|
||||
if (ret == LY_EEXIST) {
|
||||
match->refcount++;
|
||||
if (zerocopy) {
|
||||
free(value);
|
||||
}
|
||||
ret = LY_SUCCESS;
|
||||
} else if (ret == LY_SUCCESS) {
|
||||
if (!zerocopy) {
|
||||
/*
|
||||
* allocate string for new record
|
||||
* record is already inserted in hash table
|
||||
*/
|
||||
match->value = malloc(sizeof *match->value * (len + 1));
|
||||
LY_CHECK_ERR_RET(!match->value, LOGMEM(ctx), LY_EMEM);
|
||||
if (len) {
|
||||
memcpy(match->value, value, len);
|
||||
}
|
||||
match->value[len] = '\0';
|
||||
}
|
||||
} else {
|
||||
/* lyht_insert returned error */
|
||||
if (zerocopy) {
|
||||
free(value);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (str_p) {
|
||||
*str_p = match->value;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
lydict_insert(const struct ly_ctx *ctx, const char *value, size_t len, const char **str_p)
|
||||
{
|
||||
LY_ERR result;
|
||||
|
||||
LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL);
|
||||
|
||||
if (!value) {
|
||||
*str_p = NULL;
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
if (!len) {
|
||||
len = strlen(value);
|
||||
}
|
||||
|
||||
pthread_mutex_lock((pthread_mutex_t *)&ctx->dict.lock);
|
||||
result = dict_insert(ctx, (char *)value, len, 0, str_p);
|
||||
pthread_mutex_unlock((pthread_mutex_t *)&ctx->dict.lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
lydict_insert_zc(const struct ly_ctx *ctx, char *value, const char **str_p)
|
||||
{
|
||||
LY_ERR result;
|
||||
|
||||
LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL);
|
||||
|
||||
if (!value) {
|
||||
*str_p = NULL;
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
pthread_mutex_lock((pthread_mutex_t *)&ctx->dict.lock);
|
||||
result = dict_insert(ctx, value, strlen(value), 1, str_p);
|
||||
pthread_mutex_unlock((pthread_mutex_t *)&ctx->dict.lock);
|
||||
|
||||
return result;
|
||||
}
|
122
src/dict.h
Normal file
122
src/dict.h
Normal file
|
@ -0,0 +1,122 @@
|
|||
/**
|
||||
* @file dict.h
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @brief libyang dictionary
|
||||
*
|
||||
* Copyright (c) 2015-2018 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef LY_DICT_H_
|
||||
#define LY_DICT_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* dummy context structure */
|
||||
struct ly_ctx;
|
||||
|
||||
/**
|
||||
* @page howtoContextDict Context Dictionary
|
||||
*
|
||||
* Context includes dictionary to store strings more effectively. The most of strings repeats quite often in schema
|
||||
* as well as data trees. Therefore, instead of allocating those strings each time they appear, libyang stores them
|
||||
* as records in the dictionary. The basic API to the context dictionary is public, so even a caller application can
|
||||
* use the dictionary.
|
||||
*
|
||||
* To insert a string into the dictionary, caller can use ::lydict_insert() (adding a constant string) or
|
||||
* ::lydict_insert_zc() (for dynamically allocated strings that won't be used by the caller after its insertion into
|
||||
* the dictionary). Both functions provide the pointer to the inserted string in the dictionary record.
|
||||
*
|
||||
* To remove (reference of the) string from the context dictionary, ::lydict_remove() is supposed to be used.
|
||||
*
|
||||
* \note Incorrect usage of the dictionary can break libyang functionality.
|
||||
*
|
||||
* \note API for this group of functions is described in the [Dictionary module](@ref dict).
|
||||
*
|
||||
* Functions List
|
||||
* --------------
|
||||
* - ::lydict_insert()
|
||||
* - ::lydict_insert_zc()
|
||||
* - ::lydict_remove()
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup dict Dictionary
|
||||
* @{
|
||||
*
|
||||
* Publicly visible functions and values of the libyang dictionary. They provide
|
||||
* access to the strings stored in the libyang context. More detailed information can be found at
|
||||
* @ref howtoContextDict page.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Insert string into dictionary. If the string is already present,
|
||||
* only a reference counter is incremented and no memory allocation is
|
||||
* performed.
|
||||
*
|
||||
* @param[in] ctx libyang context handler
|
||||
* @param[in] value String to be stored in the dictionary. If NULL, function does nothing.
|
||||
* @param[in] len Number of bytes to store. The value is not required to be
|
||||
* NULL terminated string, the len parameter says number of bytes stored in
|
||||
* dictionary. The specified number of bytes is duplicated and terminating NULL
|
||||
* byte is added automatically. If \p len is 0, it is count automatically using strlen().
|
||||
* @param[out] str_p Optional parameter to get pointer to the string corresponding to the @p value and stored in dictionary.
|
||||
* @return LY_SUCCESS in case of successful insertion into dictionary, note that the function does not return LY_EEXIST.
|
||||
* @return LY_EINVAL in case of invalid input parameters.
|
||||
* @return LY_EMEM in case of memory allocation failure.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR lydict_insert(const struct ly_ctx *ctx, const char *value, size_t len, const char **str_p);
|
||||
|
||||
/**
|
||||
* @brief Insert string into dictionary - zerocopy version. If the string is
|
||||
* already present, only a reference counter is incremented and no memory
|
||||
* allocation is performed. This insert function variant avoids duplication of
|
||||
* specified value - it is inserted into the dictionary directly.
|
||||
*
|
||||
* @param[in] ctx libyang context handler
|
||||
* @param[in] value NULL-terminated string to be stored in the dictionary. If
|
||||
* the string is not present in dictionary, the pointer is directly used by the
|
||||
* dictionary. Otherwise, the reference counter is incremented and the value is
|
||||
* freed. So, after calling the function, caller is supposed to not use the
|
||||
* value address anymore. If NULL, function does nothing.
|
||||
* @param[out] str_p Optional parameter to get pointer to the string corresponding to the @p value and stored in dictionary.
|
||||
* @return LY_SUCCESS in case of successful insertion into dictionary, note that the function does not return LY_EEXIST.
|
||||
* @return LY_EINVAL in case of invalid input parameters.
|
||||
* @return LY_EMEM in case of memory allocation failure.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR lydict_insert_zc(const struct ly_ctx *ctx, char *value, const char **str_p);
|
||||
|
||||
/**
|
||||
* @brief Remove specified string from the dictionary. It decrement reference
|
||||
* counter for the string and if it is zero, the string itself is freed.
|
||||
*
|
||||
* @param[in] ctx libyang context handler
|
||||
* @param[in] value String to be freed. Note, that not only the string itself
|
||||
* must match the stored value, but also the address is being compared and the
|
||||
* counter is decremented only if it matches. If NULL, function does nothing.
|
||||
* @return LY_SUCCESS if the value was found and removed (or refcount decreased).
|
||||
* @return LY_ENOTFOUND if the value was not found.
|
||||
* @return LY_ERR on other errors.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR lydict_remove(const struct ly_ctx *ctx, const char *value);
|
||||
|
||||
/** @} dict */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LY_DICT_H_ */
|
2347
src/diff.c
Normal file
2347
src/diff.c
Normal file
File diff suppressed because it is too large
Load diff
62
src/diff.h
Normal file
62
src/diff.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* @file diff.h
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief internal diff header
|
||||
*
|
||||
* Copyright (c) 2020 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef LY_DIFF_H_
|
||||
#define LY_DIFF_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
struct lyd_node;
|
||||
|
||||
/**
|
||||
* @brief Internal structure for storing current (virtual) user-ordered instances order.
|
||||
*/
|
||||
struct lyd_diff_userord {
|
||||
const struct lysc_node *schema; /**< User-ordered list/leaf-list schema node. */
|
||||
uint64_t pos; /**< Current position in the second tree. */
|
||||
const struct lyd_node **inst; /**< Sized array of current instance order. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Diff operations.
|
||||
*/
|
||||
enum lyd_diff_op {
|
||||
LYD_DIFF_OP_CREATE, /**< Subtree created. */
|
||||
LYD_DIFF_OP_DELETE, /**< Subtree deleted. */
|
||||
LYD_DIFF_OP_REPLACE, /**< Node value changed or (leaf-)list instance moved. */
|
||||
LYD_DIFF_OP_NONE /**< No change of an existing inner node or default flag change of a term node. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Add a new change into diff.
|
||||
*
|
||||
* @param[in] node Node (subtree) to add into diff.
|
||||
* @param[in] op Operation to set.
|
||||
* @param[in] orig_default Original default metadata to set.
|
||||
* @param[in] orig_value Original value metadata to set.
|
||||
* @param[in] key Key metadata to set.
|
||||
* @param[in] value Value metadata to set.
|
||||
* @param[in] position Position metadata to set.
|
||||
* @param[in] orig_key Original key metadata to set.
|
||||
* @param[in] orig_position Original position metadata to set.
|
||||
* @param[in,out] diff Diff to append to.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR lyd_diff_add(const struct lyd_node *node, enum lyd_diff_op op, const char *orig_default, const char *orig_value,
|
||||
const char *key, const char *value, const char *position, const char *orig_key, const char *orig_position,
|
||||
struct lyd_node **diff);
|
||||
|
||||
#endif /* LY_DIFF_H_ */
|
534
src/hash_table.c
Normal file
534
src/hash_table.c
Normal file
|
@ -0,0 +1,534 @@
|
|||
/**
|
||||
* @file hash_table.c
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief libyang generic hash table implementation
|
||||
*
|
||||
* Copyright (c) 2015 - 2023 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "hash_table.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "compat.h"
|
||||
#include "dict.h"
|
||||
#include "log.h"
|
||||
#include "ly_common.h"
|
||||
|
||||
LIBYANG_API_DEF uint32_t
|
||||
lyht_hash_multi(uint32_t hash, const char *key_part, size_t len)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
if (key_part && len) {
|
||||
for (i = 0; i < len; ++i) {
|
||||
hash += key_part[i];
|
||||
hash += (hash << 10);
|
||||
hash ^= (hash >> 6);
|
||||
}
|
||||
} else {
|
||||
hash += (hash << 3);
|
||||
hash ^= (hash >> 11);
|
||||
hash += (hash << 15);
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF uint32_t
|
||||
lyht_hash(const char *key, size_t len)
|
||||
{
|
||||
uint32_t hash;
|
||||
|
||||
hash = lyht_hash_multi(0, key, len);
|
||||
return lyht_hash_multi(hash, NULL, len);
|
||||
}
|
||||
|
||||
static LY_ERR
|
||||
lyht_init_hlists_and_records(struct ly_ht *ht)
|
||||
{
|
||||
struct ly_ht_rec *rec;
|
||||
uint32_t i;
|
||||
|
||||
ht->recs = calloc(ht->size, ht->rec_size);
|
||||
LY_CHECK_ERR_RET(!ht->recs, LOGMEM(NULL), LY_EMEM);
|
||||
for (i = 0; i < ht->size; i++) {
|
||||
rec = lyht_get_rec(ht->recs, ht->rec_size, i);
|
||||
if (i != ht->size) {
|
||||
rec->next = i + 1;
|
||||
} else {
|
||||
rec->next = LYHT_NO_RECORD;
|
||||
}
|
||||
}
|
||||
|
||||
ht->hlists = malloc(sizeof(ht->hlists[0]) * ht->size);
|
||||
LY_CHECK_ERR_RET(!ht->hlists, free(ht->recs); LOGMEM(NULL), LY_EMEM);
|
||||
for (i = 0; i < ht->size; i++) {
|
||||
ht->hlists[i].first = LYHT_NO_RECORD;
|
||||
ht->hlists[i].last = LYHT_NO_RECORD;
|
||||
}
|
||||
ht->first_free_rec = 0;
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF struct ly_ht *
|
||||
lyht_new(uint32_t size, uint16_t val_size, lyht_value_equal_cb val_equal, void *cb_data, uint16_t resize)
|
||||
{
|
||||
struct ly_ht *ht;
|
||||
|
||||
/* check that 2^x == size (power of 2) */
|
||||
assert(size && !(size & (size - 1)));
|
||||
assert(val_equal && val_size);
|
||||
assert(resize == 0 || resize == 1);
|
||||
|
||||
if (size < LYHT_MIN_SIZE) {
|
||||
size = LYHT_MIN_SIZE;
|
||||
}
|
||||
|
||||
ht = malloc(sizeof *ht);
|
||||
LY_CHECK_ERR_RET(!ht, LOGMEM(NULL), NULL);
|
||||
|
||||
ht->used = 0;
|
||||
ht->size = size;
|
||||
ht->val_equal = val_equal;
|
||||
ht->cb_data = cb_data;
|
||||
ht->resize = resize;
|
||||
|
||||
ht->rec_size = SIZEOF_LY_HT_REC + val_size;
|
||||
if (lyht_init_hlists_and_records(ht) != LY_SUCCESS) {
|
||||
free(ht);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ht;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF lyht_value_equal_cb
|
||||
lyht_set_cb(struct ly_ht *ht, lyht_value_equal_cb new_val_equal)
|
||||
{
|
||||
lyht_value_equal_cb prev;
|
||||
|
||||
prev = ht->val_equal;
|
||||
ht->val_equal = new_val_equal;
|
||||
return prev;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF void *
|
||||
lyht_set_cb_data(struct ly_ht *ht, void *new_cb_data)
|
||||
{
|
||||
void *prev;
|
||||
|
||||
prev = ht->cb_data;
|
||||
ht->cb_data = new_cb_data;
|
||||
return prev;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF struct ly_ht *
|
||||
lyht_dup(const struct ly_ht *orig)
|
||||
{
|
||||
struct ly_ht *ht;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, orig, NULL);
|
||||
|
||||
ht = lyht_new(orig->size, orig->rec_size - SIZEOF_LY_HT_REC, orig->val_equal, orig->cb_data, orig->resize ? 1 : 0);
|
||||
if (!ht) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(ht->hlists, orig->hlists, sizeof(ht->hlists[0]) * orig->size);
|
||||
memcpy(ht->recs, orig->recs, (size_t)orig->size * orig->rec_size);
|
||||
ht->used = orig->used;
|
||||
return ht;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF void
|
||||
lyht_free(struct ly_ht *ht, void (*val_free)(void *val_p))
|
||||
{
|
||||
struct ly_ht_rec *rec;
|
||||
uint32_t hlist_idx;
|
||||
uint32_t rec_idx;
|
||||
|
||||
if (!ht) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (val_free) {
|
||||
LYHT_ITER_ALL_RECS(ht, hlist_idx, rec_idx, rec) {
|
||||
val_free(&rec->val);
|
||||
}
|
||||
}
|
||||
free(ht->hlists);
|
||||
free(ht->recs);
|
||||
free(ht);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resize a hash table.
|
||||
*
|
||||
* @param[in] ht Hash table to resize.
|
||||
* @param[in] operation Operation to perform. 1 to enlarge, -1 to shrink, 0 to only rehash all records.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
static LY_ERR
|
||||
lyht_resize(struct ly_ht *ht, int operation, int check)
|
||||
{
|
||||
struct ly_ht_rec *rec;
|
||||
struct ly_ht_hlist *old_hlists;
|
||||
unsigned char *old_recs;
|
||||
uint32_t old_first_free_rec;
|
||||
uint32_t i, old_size;
|
||||
uint32_t rec_idx;
|
||||
|
||||
old_hlists = ht->hlists;
|
||||
old_recs = ht->recs;
|
||||
old_size = ht->size;
|
||||
old_first_free_rec = ht->first_free_rec;
|
||||
|
||||
if (operation > 0) {
|
||||
/* double the size */
|
||||
ht->size <<= 1;
|
||||
} else if (operation < 0) {
|
||||
/* half the size */
|
||||
ht->size >>= 1;
|
||||
}
|
||||
|
||||
if (lyht_init_hlists_and_records(ht) != LY_SUCCESS) {
|
||||
ht->hlists = old_hlists;
|
||||
ht->recs = old_recs;
|
||||
ht->size = old_size;
|
||||
ht->first_free_rec = old_first_free_rec;
|
||||
return LY_EMEM;
|
||||
}
|
||||
|
||||
/* reset used, it will increase again */
|
||||
ht->used = 0;
|
||||
|
||||
/* add all the old records into the new records array */
|
||||
for (i = 0; i < old_size; i++) {
|
||||
for (rec_idx = old_hlists[i].first, rec = lyht_get_rec(old_recs, ht->rec_size, rec_idx);
|
||||
rec_idx != LYHT_NO_RECORD;
|
||||
rec_idx = rec->next, rec = lyht_get_rec(old_recs, ht->rec_size, rec_idx)) {
|
||||
LY_ERR ret;
|
||||
|
||||
if (check) {
|
||||
ret = lyht_insert(ht, rec->val, rec->hash, NULL);
|
||||
} else {
|
||||
ret = lyht_insert_no_check(ht, rec->val, rec->hash, NULL);
|
||||
}
|
||||
|
||||
assert(!ret);
|
||||
(void)ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* final touches */
|
||||
free(old_recs);
|
||||
free(old_hlists);
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Search for a record with specific value and hash.
|
||||
*
|
||||
* @param[in] ht Hash table to search in.
|
||||
* @param[in] val_p Pointer to the value to find.
|
||||
* @param[in] hash Hash to find.
|
||||
* @param[in] mod Whether the operation modifies the hash table (insert or remove) or not (find).
|
||||
* @param[in] val_equal Callback for checking value equivalence.
|
||||
* @param[out] crec_p Optional found first record.
|
||||
* @param[out] col Optional collision number of @p rec_p, 0 for no collision.
|
||||
* @param[out] rec_p Found exact matching record, may be a collision of @p crec_p.
|
||||
* @return LY_ENOTFOUND if no record found,
|
||||
* @return LY_SUCCESS if record was found.
|
||||
*/
|
||||
static LY_ERR
|
||||
lyht_find_rec(const struct ly_ht *ht, void *val_p, uint32_t hash, ly_bool mod, lyht_value_equal_cb val_equal,
|
||||
struct ly_ht_rec **crec_p, uint32_t *col, struct ly_ht_rec **rec_p)
|
||||
{
|
||||
uint32_t hlist_idx = hash & (ht->size - 1);
|
||||
struct ly_ht_rec *rec;
|
||||
uint32_t rec_idx;
|
||||
|
||||
if (crec_p) {
|
||||
*crec_p = NULL;
|
||||
}
|
||||
if (col) {
|
||||
*col = 0;
|
||||
}
|
||||
*rec_p = NULL;
|
||||
|
||||
LYHT_ITER_HLIST_RECS(ht, hlist_idx, rec_idx, rec) {
|
||||
if ((rec->hash == hash) && val_equal(val_p, &rec->val, mod, ht->cb_data)) {
|
||||
if (crec_p) {
|
||||
*crec_p = rec;
|
||||
}
|
||||
*rec_p = rec;
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
if (col) {
|
||||
*col = *col + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* not found even in collisions */
|
||||
return LY_ENOTFOUND;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
lyht_find(const struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p)
|
||||
{
|
||||
struct ly_ht_rec *rec;
|
||||
|
||||
lyht_find_rec(ht, val_p, hash, 0, ht->val_equal, NULL, NULL, &rec);
|
||||
|
||||
if (rec && match_p) {
|
||||
*match_p = rec->val;
|
||||
}
|
||||
return rec ? LY_SUCCESS : LY_ENOTFOUND;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
lyht_find_with_val_cb(const struct ly_ht *ht, void *val_p, uint32_t hash, lyht_value_equal_cb val_equal, void **match_p)
|
||||
{
|
||||
struct ly_ht_rec *rec;
|
||||
|
||||
lyht_find_rec(ht, val_p, hash, 0, val_equal ? val_equal : ht->val_equal, NULL, NULL, &rec);
|
||||
|
||||
if (rec && match_p) {
|
||||
*match_p = rec->val;
|
||||
}
|
||||
return rec ? LY_SUCCESS : LY_ENOTFOUND;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
lyht_find_next_with_collision_cb(const struct ly_ht *ht, void *val_p, uint32_t hash,
|
||||
lyht_value_equal_cb collision_val_equal, void **match_p)
|
||||
{
|
||||
struct ly_ht_rec *rec, *crec;
|
||||
uint32_t rec_idx;
|
||||
uint32_t i;
|
||||
|
||||
/* find the record of the previously found value */
|
||||
if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, &crec, &i, &rec)) {
|
||||
/* not found, cannot happen */
|
||||
LOGINT_RET(NULL);
|
||||
}
|
||||
|
||||
for (rec_idx = rec->next, rec = lyht_get_rec(ht->recs, ht->rec_size, rec_idx);
|
||||
rec_idx != LYHT_NO_RECORD;
|
||||
rec_idx = rec->next, rec = lyht_get_rec(ht->recs, ht->rec_size, rec_idx)) {
|
||||
|
||||
if (rec->hash != hash) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (collision_val_equal) {
|
||||
if (collision_val_equal(val_p, &rec->val, 0, ht->cb_data)) {
|
||||
/* even the value matches */
|
||||
if (match_p) {
|
||||
*match_p = rec->val;
|
||||
}
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
} else if (ht->val_equal(val_p, &rec->val, 0, ht->cb_data)) {
|
||||
/* even the value matches */
|
||||
if (match_p) {
|
||||
*match_p = rec->val;
|
||||
}
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* the last equal value was already returned */
|
||||
return LY_ENOTFOUND;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
lyht_find_next(const struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p)
|
||||
{
|
||||
return lyht_find_next_with_collision_cb(ht, val_p, hash, NULL, match_p);
|
||||
}
|
||||
|
||||
static LY_ERR
|
||||
_lyht_insert_with_resize_cb(struct ly_ht *ht, void *val_p, uint32_t hash, lyht_value_equal_cb resize_val_equal,
|
||||
void **match_p, int check)
|
||||
{
|
||||
uint32_t hlist_idx = hash & (ht->size - 1);
|
||||
LY_ERR r, ret = LY_SUCCESS;
|
||||
struct ly_ht_rec *rec, *prev_rec;
|
||||
lyht_value_equal_cb old_val_equal = NULL;
|
||||
uint32_t rec_idx;
|
||||
|
||||
if (check) {
|
||||
if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, NULL, NULL, &rec) == LY_SUCCESS) {
|
||||
if (rec && match_p) {
|
||||
*match_p = rec->val;
|
||||
}
|
||||
return LY_EEXIST;
|
||||
}
|
||||
}
|
||||
|
||||
rec_idx = ht->first_free_rec;
|
||||
assert(rec_idx < ht->size);
|
||||
rec = lyht_get_rec(ht->recs, ht->rec_size, rec_idx);
|
||||
ht->first_free_rec = rec->next;
|
||||
|
||||
if (ht->hlists[hlist_idx].first == LYHT_NO_RECORD) {
|
||||
ht->hlists[hlist_idx].first = rec_idx;
|
||||
} else {
|
||||
prev_rec = lyht_get_rec(ht->recs, ht->rec_size, ht->hlists[hlist_idx].last);
|
||||
prev_rec->next = rec_idx;
|
||||
}
|
||||
rec->next = LYHT_NO_RECORD;
|
||||
ht->hlists[hlist_idx].last = rec_idx;
|
||||
|
||||
rec->hash = hash;
|
||||
memcpy(&rec->val, val_p, ht->rec_size - SIZEOF_LY_HT_REC);
|
||||
if (match_p) {
|
||||
*match_p = (void *)&rec->val;
|
||||
}
|
||||
|
||||
/* check size & enlarge if needed */
|
||||
++ht->used;
|
||||
if (ht->resize) {
|
||||
r = (ht->used * LYHT_HUNDRED_PERCENTAGE) / ht->size;
|
||||
if ((ht->resize == 1) && (r >= LYHT_FIRST_SHRINK_PERCENTAGE)) {
|
||||
/* enable shrinking */
|
||||
ht->resize = 2;
|
||||
}
|
||||
if ((ht->resize == 2) && (r >= LYHT_ENLARGE_PERCENTAGE)) {
|
||||
if (resize_val_equal) {
|
||||
old_val_equal = lyht_set_cb(ht, resize_val_equal);
|
||||
}
|
||||
|
||||
/* enlarge */
|
||||
ret = lyht_resize(ht, 1, check);
|
||||
/* if hash_table was resized, we need to find new matching value */
|
||||
if ((ret == LY_SUCCESS) && match_p) {
|
||||
ret = lyht_find(ht, val_p, hash, match_p);
|
||||
assert(!ret);
|
||||
}
|
||||
|
||||
if (resize_val_equal) {
|
||||
lyht_set_cb(ht, old_val_equal);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
lyht_insert_with_resize_cb(struct ly_ht *ht, void *val_p, uint32_t hash, lyht_value_equal_cb resize_val_equal,
|
||||
void **match_p)
|
||||
{
|
||||
return _lyht_insert_with_resize_cb(ht, val_p, hash, resize_val_equal, match_p, 1);
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
lyht_insert(struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p)
|
||||
{
|
||||
return _lyht_insert_with_resize_cb(ht, val_p, hash, NULL, match_p, 1);
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
lyht_insert_no_check(struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p)
|
||||
{
|
||||
return _lyht_insert_with_resize_cb(ht, val_p, hash, NULL, match_p, 0);
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
lyht_remove_with_resize_cb(struct ly_ht *ht, void *val_p, uint32_t hash, lyht_value_equal_cb resize_val_equal)
|
||||
{
|
||||
struct ly_ht_rec *found_rec, *prev_rec, *rec;
|
||||
uint32_t hlist_idx = hash & (ht->size - 1);
|
||||
LY_ERR r, ret = LY_SUCCESS;
|
||||
lyht_value_equal_cb old_val_equal = NULL;
|
||||
uint32_t prev_rec_idx;
|
||||
uint32_t rec_idx;
|
||||
|
||||
if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, NULL, NULL, &found_rec)) {
|
||||
LOGARG(NULL, hash);
|
||||
return LY_ENOTFOUND;
|
||||
}
|
||||
|
||||
prev_rec_idx = LYHT_NO_RECORD;
|
||||
LYHT_ITER_HLIST_RECS(ht, hlist_idx, rec_idx, rec) {
|
||||
if (rec == found_rec) {
|
||||
break;
|
||||
}
|
||||
prev_rec_idx = rec_idx;
|
||||
}
|
||||
|
||||
if (prev_rec_idx == LYHT_NO_RECORD) {
|
||||
ht->hlists[hlist_idx].first = rec->next;
|
||||
if (rec->next == LYHT_NO_RECORD) {
|
||||
ht->hlists[hlist_idx].last = LYHT_NO_RECORD;
|
||||
}
|
||||
} else {
|
||||
prev_rec = lyht_get_rec(ht->recs, ht->rec_size, prev_rec_idx);
|
||||
prev_rec->next = rec->next;
|
||||
if (rec->next == LYHT_NO_RECORD) {
|
||||
ht->hlists[hlist_idx].last = prev_rec_idx;
|
||||
}
|
||||
}
|
||||
|
||||
rec->next = ht->first_free_rec;
|
||||
ht->first_free_rec = rec_idx;
|
||||
|
||||
/* check size & shrink if needed */
|
||||
--ht->used;
|
||||
if (ht->resize == 2) {
|
||||
r = (ht->used * LYHT_HUNDRED_PERCENTAGE) / ht->size;
|
||||
if ((r < LYHT_SHRINK_PERCENTAGE) && (ht->size > LYHT_MIN_SIZE)) {
|
||||
if (resize_val_equal) {
|
||||
old_val_equal = lyht_set_cb(ht, resize_val_equal);
|
||||
}
|
||||
|
||||
/* shrink */
|
||||
ret = lyht_resize(ht, -1, 1);
|
||||
|
||||
if (resize_val_equal) {
|
||||
lyht_set_cb(ht, old_val_equal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
lyht_remove(struct ly_ht *ht, void *val_p, uint32_t hash)
|
||||
{
|
||||
return lyht_remove_with_resize_cb(ht, val_p, hash, NULL);
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF uint32_t
|
||||
lyht_get_fixed_size(uint32_t item_count)
|
||||
{
|
||||
if (item_count == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* return next power of 2 (greater or equal) */
|
||||
item_count--;
|
||||
item_count |= item_count >> 1;
|
||||
item_count |= item_count >> 2;
|
||||
item_count |= item_count >> 4;
|
||||
item_count |= item_count >> 8;
|
||||
item_count |= item_count >> 16;
|
||||
|
||||
return item_count + 1;
|
||||
}
|
259
src/hash_table.h
Normal file
259
src/hash_table.h
Normal file
|
@ -0,0 +1,259 @@
|
|||
/**
|
||||
* @file hash_table.h
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief libyang hash table
|
||||
*
|
||||
* Copyright (c) 2015 - 2023 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef LY_HASH_TABLE_H_
|
||||
#define LY_HASH_TABLE_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "log.h"
|
||||
|
||||
/**
|
||||
* @struct ly_ht
|
||||
* @brief libyang hash table.
|
||||
*/
|
||||
struct ly_ht;
|
||||
|
||||
/**
|
||||
* @brief Compute hash from (several) string(s).
|
||||
*
|
||||
* Usage:
|
||||
* - init hash to 0
|
||||
* - repeatedly call ::lyht_hash_multi(), provide hash from the last call
|
||||
* - call ::lyht_hash_multi() with key_part = NULL to finish the hash
|
||||
*
|
||||
* @param[in] hash Previous hash.
|
||||
* @param[in] key_part Next key to hash,
|
||||
* @param[in] len Length of @p key_part.
|
||||
* @return Hash with the next key.
|
||||
*/
|
||||
LIBYANG_API_DECL uint32_t lyht_hash_multi(uint32_t hash, const char *key_part, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Compute hash from a string.
|
||||
*
|
||||
* Bob Jenkin's one-at-a-time hash
|
||||
* http://www.burtleburtle.net/bob/hash/doobs.html
|
||||
*
|
||||
* Spooky hash is faster, but it works only for little endian architectures.
|
||||
*
|
||||
* @param[in] key Key to hash.
|
||||
* @param[in] len Length of @p key.
|
||||
* @return Hash of the key.
|
||||
*/
|
||||
LIBYANG_API_DECL uint32_t lyht_hash(const char *key, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Callback for checking hash table values equivalence.
|
||||
*
|
||||
* @param[in] val1_p Pointer to the first value, the one being searched (inserted/removed).
|
||||
* @param[in] val2_p Pointer to the second value, the one stored in the hash table.
|
||||
* @param[in] mod Whether the operation modifies the hash table (insert or remove) or not (find).
|
||||
* @param[in] cb_data User callback data.
|
||||
* @return false (non-equal) or true (equal).
|
||||
*/
|
||||
typedef ly_bool (*lyht_value_equal_cb)(void *val1_p, void *val2_p, ly_bool mod, void *cb_data);
|
||||
|
||||
/**
|
||||
* @brief Create new hash table.
|
||||
*
|
||||
* @param[in] size Starting size of the hash table (capacity of values), must be power of 2.
|
||||
* @param[in] val_size Size in bytes of value (the stored hashed item).
|
||||
* @param[in] val_equal Callback for checking value equivalence.
|
||||
* @param[in] cb_data User data always passed to @p val_equal.
|
||||
* @param[in] resize Whether to resize the table on too few/too many records taken.
|
||||
* @return Empty hash table, NULL on error.
|
||||
*/
|
||||
LIBYANG_API_DECL struct ly_ht *lyht_new(uint32_t size, uint16_t val_size, lyht_value_equal_cb val_equal, void *cb_data,
|
||||
uint16_t resize);
|
||||
|
||||
/**
|
||||
* @brief Set hash table value equal callback.
|
||||
*
|
||||
* @param[in] ht Hash table to modify.
|
||||
* @param[in] new_val_equal New callback for checking value equivalence.
|
||||
* @return Previous callback for checking value equivalence.
|
||||
*/
|
||||
LIBYANG_API_DECL lyht_value_equal_cb lyht_set_cb(struct ly_ht *ht, lyht_value_equal_cb new_val_equal);
|
||||
|
||||
/**
|
||||
* @brief Set hash table value equal callback user data.
|
||||
*
|
||||
* @param[in] ht Hash table to modify.
|
||||
* @param[in] new_cb_data New data for values callback.
|
||||
* @return Previous data for values callback.
|
||||
*/
|
||||
LIBYANG_API_DECL void *lyht_set_cb_data(struct ly_ht *ht, void *new_cb_data);
|
||||
|
||||
/**
|
||||
* @brief Make a duplicate of an existing hash table.
|
||||
*
|
||||
* @param[in] orig Original hash table to duplicate.
|
||||
* @return Duplicated hash table @p orig, NULL on error.
|
||||
*/
|
||||
LIBYANG_API_DECL struct ly_ht *lyht_dup(const struct ly_ht *orig);
|
||||
|
||||
/**
|
||||
* @brief Free a hash table.
|
||||
*
|
||||
* @param[in] ht Hash table to be freed.
|
||||
* @param[in] val_free Optional callback for freeing all the stored values, @p val_p is a pointer to a stored value.
|
||||
*/
|
||||
LIBYANG_API_DECL void lyht_free(struct ly_ht *ht, void (*val_free)(void *val_p));
|
||||
|
||||
/**
|
||||
* @brief Find a value in a hash table.
|
||||
*
|
||||
* @param[in] ht Hash table to search in.
|
||||
* @param[in] val_p Pointer to the value to find.
|
||||
* @param[in] hash Hash of the stored value.
|
||||
* @param[out] match_p Pointer to the matching value, optional.
|
||||
* @return LY_SUCCESS if value was found,
|
||||
* @return LY_ENOTFOUND if not found.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR lyht_find(const struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p);
|
||||
|
||||
/**
|
||||
* @brief Find a value in a hash table but use a custom val_equal callback.
|
||||
*
|
||||
* @param[in] ht Hash table to search in.
|
||||
* @param[in] val_p Pointer to the value to find.
|
||||
* @param[in] hash Hash of the stored value.
|
||||
* @param[in] val_equal Callback for checking value equivalence.
|
||||
* @param[out] match_p Pointer to the matching value, optional.
|
||||
* @return LY_SUCCESS if value was found,
|
||||
* @return LY_ENOTFOUND if not found.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR lyht_find_with_val_cb(const struct ly_ht *ht, void *val_p, uint32_t hash,
|
||||
lyht_value_equal_cb val_equal, void **match_p);
|
||||
|
||||
/**
|
||||
* @brief Find another equal value in the hash table.
|
||||
*
|
||||
* @param[in] ht Hash table to search in.
|
||||
* @param[in] val_p Pointer to the previously found value in @p ht.
|
||||
* @param[in] hash Hash of the previously found value.
|
||||
* @param[out] match_p Pointer to the matching value, optional.
|
||||
* @return LY_SUCCESS if value was found,
|
||||
* @return LY_ENOTFOUND if not found.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR lyht_find_next(const struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p);
|
||||
|
||||
/**
|
||||
* @brief Find another equal value in the hash table. Same functionality as ::lyht_find_next()
|
||||
* but allows to specify a collision val equal callback to be used for checking for matching colliding values.
|
||||
*
|
||||
* @param[in] ht Hash table to search in.
|
||||
* @param[in] val_p Pointer to the previously found value in @p ht.
|
||||
* @param[in] hash Hash of the previously found value.
|
||||
* @param[in] collision_val_equal Val equal callback to use for checking collisions.
|
||||
* @param[out] match_p Pointer to the matching value, optional.
|
||||
* @return LY_SUCCESS if value was found,
|
||||
* @return LY_ENOTFOUND if not found.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR lyht_find_next_with_collision_cb(const struct ly_ht *ht, void *val_p, uint32_t hash,
|
||||
lyht_value_equal_cb collision_val_equal, void **match_p);
|
||||
|
||||
/**
|
||||
* @brief Insert a value into a hash table.
|
||||
*
|
||||
* @param[in] ht Hash table to insert into.
|
||||
* @param[in] val_p Pointer to the value to insert. Be careful, if the values stored in the hash table
|
||||
* are pointers, @p val_p must be a pointer to a pointer.
|
||||
* @param[in] hash Hash of the stored value.
|
||||
* @param[out] match_p Pointer to the stored value, optional
|
||||
* @return LY_SUCCESS on success,
|
||||
* @return LY_EEXIST in case the value is already present.
|
||||
* @return LY_EMEM in case of memory allocation failure.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR lyht_insert(struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p);
|
||||
|
||||
/**
|
||||
* @brief Insert a value into a hash table, without checking whether the value has already been inserted.
|
||||
*
|
||||
* @param[in] ht Hash table to insert into.
|
||||
* @param[in] val_p Pointer to the value to insert. Be careful, if the values stored in the hash table
|
||||
* are pointers, @p val_p must be a pointer to a pointer.
|
||||
* @param[in] hash Hash of the stored value.
|
||||
* @param[out] match_p Pointer to the stored value, optional
|
||||
* @return LY_SUCCESS on success,
|
||||
* @return LY_EMEM in case of memory allocation failure.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR lyht_insert_no_check(struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p);
|
||||
|
||||
/**
|
||||
* @brief Insert a value into hash table. Same functionality as ::lyht_insert()
|
||||
* but allows to specify a temporary val equal callback to be used in case the hash table
|
||||
* will be resized after successful insertion.
|
||||
*
|
||||
* @param[in] ht Hash table to insert into.
|
||||
* @param[in] val_p Pointer to the value to insert. Be careful, if the values stored in the hash table
|
||||
* are pointers, @p val_p must be a pointer to a pointer.
|
||||
* @param[in] hash Hash of the stored value.
|
||||
* @param[in] resize_val_equal Val equal callback to use for resizing.
|
||||
* @param[out] match_p Pointer to the stored value, optional
|
||||
* @return LY_SUCCESS on success,
|
||||
* @return LY_EEXIST in case the value is already present.
|
||||
* @return LY_EMEM in case of memory allocation failure.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR lyht_insert_with_resize_cb(struct ly_ht *ht, void *val_p, uint32_t hash,
|
||||
lyht_value_equal_cb resize_val_equal, void **match_p);
|
||||
|
||||
/**
|
||||
* @brief Remove a value from a hash table.
|
||||
*
|
||||
* @param[in] ht Hash table to remove from.
|
||||
* @param[in] val_p Pointer to value to be removed. Be careful, if the values stored in the hash table
|
||||
* are pointers, @p val_p must be a pointer to a pointer.
|
||||
* @param[in] hash Hash of the stored value.
|
||||
* @return LY_SUCCESS on success,
|
||||
* @return LY_ENOTFOUND if value was not found.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR lyht_remove(struct ly_ht *ht, void *val_p, uint32_t hash);
|
||||
|
||||
/**
|
||||
* @brief Remove a value from a hash table. Same functionality as ::lyht_remove()
|
||||
* but allows to specify a temporary val equal callback to be used in case the hash table
|
||||
* will be resized after successful removal.
|
||||
*
|
||||
* @param[in] ht Hash table to remove from.
|
||||
* @param[in] val_p Pointer to value to be removed. Be careful, if the values stored in the hash table
|
||||
* are pointers, @p val_p must be a pointer to a pointer.
|
||||
* @param[in] hash Hash of the stored value.
|
||||
* @param[in] resize_val_equal Val equal callback to use for resizing.
|
||||
* @return LY_SUCCESS on success,
|
||||
* @return LY_ENOTFOUND if value was not found.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR lyht_remove_with_resize_cb(struct ly_ht *ht, void *val_p, uint32_t hash,
|
||||
lyht_value_equal_cb resize_val_equal);
|
||||
|
||||
/**
|
||||
* @brief Get suitable size of a hash table for a fixed number of items.
|
||||
*
|
||||
* @param[in] item_count Number of stored items.
|
||||
* @return Hash table size.
|
||||
*/
|
||||
LIBYANG_API_DECL uint32_t lyht_get_fixed_size(uint32_t item_count);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LY_HASH_TABLE_H_ */
|
146
src/hash_table_internal.h
Normal file
146
src/hash_table_internal.h
Normal file
|
@ -0,0 +1,146 @@
|
|||
/**
|
||||
* @file hash_table_internal.h
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief libyang hash table internal header
|
||||
*
|
||||
* Copyright (c) 2015 - 2023 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef LY_HASH_TABLE_INTERNAL_H_
|
||||
#define LY_HASH_TABLE_INTERNAL_H_
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "compat.h"
|
||||
#include "hash_table.h"
|
||||
|
||||
/** reference value for 100% */
|
||||
#define LYHT_HUNDRED_PERCENTAGE 100
|
||||
|
||||
/** when the table is at least this much percent full, it is enlarged (double the size) */
|
||||
#define LYHT_ENLARGE_PERCENTAGE 75
|
||||
|
||||
/** only once the table is this much percent full, enable shrinking */
|
||||
#define LYHT_FIRST_SHRINK_PERCENTAGE 50
|
||||
|
||||
/** when the table is less than this much percent full, it is shrunk (half the size) */
|
||||
#define LYHT_SHRINK_PERCENTAGE 25
|
||||
|
||||
/** never shrink beyond this size */
|
||||
#define LYHT_MIN_SIZE 8
|
||||
|
||||
/**
|
||||
* @brief Generic hash table record.
|
||||
*/
|
||||
struct ly_ht_rec {
|
||||
uint32_t hash; /* hash of the value */
|
||||
uint32_t next; /* index of next collision */
|
||||
unsigned char val[1]; /* arbitrary-size value */
|
||||
} _PACKED;
|
||||
|
||||
/* real size, without taking the val[1] in account */
|
||||
#define SIZEOF_LY_HT_REC (sizeof(struct ly_ht_rec) - 1)
|
||||
|
||||
struct ly_ht_hlist {
|
||||
uint32_t first;
|
||||
uint32_t last;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief (Very) generic hash table.
|
||||
*
|
||||
* This structure implements a hash table, providing fast accesses to stored
|
||||
* values from their hash.
|
||||
*
|
||||
* The hash table structure contains 2 pointers to tables that are allocated
|
||||
* at initialization:
|
||||
* - a table of records: each record is composed of a struct ly_ht_rec header,
|
||||
* followed by the user value. The header contains the hash value and a
|
||||
* next index that can be used to chain records.
|
||||
* - a table of list heads: each list head entry contains the index of the
|
||||
* first record in the records table whose hash (modulo hash table size)
|
||||
* is equal to the index of the list head entry. The other matching records
|
||||
* are chained together.
|
||||
*
|
||||
* The unused records are chained in first_free_rec, which contains the index
|
||||
* of the first unused record entry in the records table.
|
||||
*
|
||||
* The LYHT_NO_RECORD magic value is used when an index points to nothing.
|
||||
*/
|
||||
struct ly_ht {
|
||||
uint32_t used; /* number of values stored in the hash table (filled records) */
|
||||
uint32_t size; /* always holds 2^x == size (is power of 2), actually number of records allocated */
|
||||
lyht_value_equal_cb val_equal; /* callback for testing value equivalence */
|
||||
void *cb_data; /* user data callback arbitrary value */
|
||||
uint16_t resize; /* 0 - resizing is disabled, *
|
||||
* 1 - enlarging is enabled, *
|
||||
* 2 - both shrinking and enlarging is enabled */
|
||||
uint16_t rec_size; /* real size (in bytes) of one record for accessing recs array */
|
||||
uint32_t first_free_rec; /* index of the first free record */
|
||||
struct ly_ht_hlist *hlists; /* pointer to the hlists table */
|
||||
unsigned char *recs; /* pointer to the hash table itself (array of struct ht_rec) */
|
||||
};
|
||||
|
||||
/* index that points to nothing */
|
||||
#define LYHT_NO_RECORD UINT32_MAX
|
||||
|
||||
/* get the record associated to */
|
||||
static inline struct ly_ht_rec *
|
||||
lyht_get_rec(unsigned char *recs, uint16_t rec_size, uint32_t idx)
|
||||
{
|
||||
return (struct ly_ht_rec *)&recs[idx * rec_size];
|
||||
}
|
||||
|
||||
/* Iterate all records in a hlist */
|
||||
#define LYHT_ITER_HLIST_RECS(ht, hlist_idx, rec_idx, rec) \
|
||||
for (rec_idx = ht->hlists[hlist_idx].first, \
|
||||
rec = lyht_get_rec(ht->recs, ht->rec_size, rec_idx); \
|
||||
rec_idx != LYHT_NO_RECORD; \
|
||||
rec_idx = rec->next, \
|
||||
rec = lyht_get_rec(ht->recs, ht->rec_size, rec_idx))
|
||||
|
||||
/* Iterate all records in the hash table */
|
||||
#define LYHT_ITER_ALL_RECS(ht, hlist_idx, rec_idx, rec) \
|
||||
for (hlist_idx = 0; hlist_idx < ht->size; hlist_idx++) \
|
||||
LYHT_ITER_HLIST_RECS(ht, hlist_idx, rec_idx, rec)
|
||||
|
||||
/**
|
||||
* @brief Dictionary hash table record.
|
||||
*/
|
||||
struct ly_dict_rec {
|
||||
char *value; /**< stored string */
|
||||
uint32_t refcount; /**< reference count of the string */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Dictionary for storing repeated strings.
|
||||
*/
|
||||
struct ly_dict {
|
||||
struct ly_ht *hash_tab;
|
||||
pthread_mutex_t lock;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initiate content (non-zero values) of the dictionary
|
||||
*
|
||||
* @param[in] dict Dictionary table to initiate
|
||||
*/
|
||||
void lydict_init(struct ly_dict *dict);
|
||||
|
||||
/**
|
||||
* @brief Cleanup the dictionary content
|
||||
*
|
||||
* @param[in] dict Dictionary table to cleanup
|
||||
*/
|
||||
void lydict_clean(struct ly_dict *dict);
|
||||
|
||||
#endif /* LY_HASH_TABLE_INTERNAL_H_ */
|
329
src/in.c
Normal file
329
src/in.c
Normal file
|
@ -0,0 +1,329 @@
|
|||
/**
|
||||
* @file in.c
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @brief libyang input functions.
|
||||
*
|
||||
* Copyright (c) 2015 - 2020 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _POSIX_C_SOURCE 200809L /* strdup, strndup */
|
||||
|
||||
#include "in.h"
|
||||
#include "in_internal.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "compat.h"
|
||||
#include "dict.h"
|
||||
#include "log.h"
|
||||
#include "ly_common.h"
|
||||
#include "parser_data.h"
|
||||
#include "parser_internal.h"
|
||||
#include "set.h"
|
||||
#include "tree.h"
|
||||
#include "tree_data.h"
|
||||
#include "tree_data_internal.h"
|
||||
#include "tree_schema.h"
|
||||
#include "tree_schema_internal.h"
|
||||
|
||||
LIBYANG_API_DEF LY_IN_TYPE
|
||||
ly_in_type(const struct ly_in *in)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, in, LY_IN_ERROR);
|
||||
return in->type;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
ly_in_reset(struct ly_in *in)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, in, LY_EINVAL);
|
||||
|
||||
in->current = in->func_start = in->start;
|
||||
in->line = 1;
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
ly_in_new_fd(int fd, struct ly_in **in)
|
||||
{
|
||||
size_t length;
|
||||
char *addr;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, fd >= 0, in, LY_EINVAL);
|
||||
|
||||
LY_CHECK_RET(ly_mmap(NULL, fd, &length, (void **)&addr));
|
||||
if (!addr) {
|
||||
LOGERR(NULL, LY_EINVAL, "Empty input file.");
|
||||
return LY_EINVAL;
|
||||
}
|
||||
|
||||
*in = calloc(1, sizeof **in);
|
||||
LY_CHECK_ERR_RET(!*in, LOGMEM(NULL); ly_munmap(addr, length), LY_EMEM);
|
||||
|
||||
(*in)->type = LY_IN_FD;
|
||||
(*in)->method.fd = fd;
|
||||
(*in)->current = (*in)->start = (*in)->func_start = addr;
|
||||
(*in)->line = 1;
|
||||
(*in)->length = length;
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF int
|
||||
ly_in_fd(struct ly_in *in, int fd)
|
||||
{
|
||||
int prev_fd;
|
||||
size_t length;
|
||||
const char *addr;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, in, in->type == LY_IN_FD, -1);
|
||||
|
||||
prev_fd = in->method.fd;
|
||||
|
||||
if (fd != -1) {
|
||||
LY_CHECK_RET(ly_mmap(NULL, fd, &length, (void **)&addr), -1);
|
||||
if (!addr) {
|
||||
LOGERR(NULL, LY_EINVAL, "Empty input file.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ly_munmap((char *)in->start, in->length);
|
||||
|
||||
in->method.fd = fd;
|
||||
in->current = in->start = addr;
|
||||
in->line = 1;
|
||||
in->length = length;
|
||||
}
|
||||
|
||||
return prev_fd;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
ly_in_new_file(FILE *f, struct ly_in **in)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, f, in, LY_EINVAL);
|
||||
|
||||
LY_CHECK_RET(ly_in_new_fd(fileno(f), in));
|
||||
|
||||
/* convert the LY_IN_FD input handler into the LY_IN_FILE */
|
||||
(*in)->type = LY_IN_FILE;
|
||||
(*in)->method.f = f;
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF FILE *
|
||||
ly_in_file(struct ly_in *in, FILE *f)
|
||||
{
|
||||
FILE *prev_f;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, in, in->type == LY_IN_FILE, NULL);
|
||||
|
||||
prev_f = in->method.f;
|
||||
|
||||
if (f) {
|
||||
/* convert LY_IN_FILE handler into LY_IN_FD to be able to update it via ly_in_fd() */
|
||||
in->type = LY_IN_FD;
|
||||
in->method.fd = fileno(prev_f);
|
||||
if (ly_in_fd(in, fileno(f)) == -1) {
|
||||
in->type = LY_IN_FILE;
|
||||
in->method.f = prev_f;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* if success, convert the result back */
|
||||
in->type = LY_IN_FILE;
|
||||
in->method.f = f;
|
||||
}
|
||||
|
||||
return prev_f;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
ly_in_new_memory(const char *str, struct ly_in **in)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, str, in, LY_EINVAL);
|
||||
|
||||
*in = calloc(1, sizeof **in);
|
||||
LY_CHECK_ERR_RET(!*in, LOGMEM(NULL), LY_EMEM);
|
||||
|
||||
(*in)->type = LY_IN_MEMORY;
|
||||
(*in)->start = (*in)->current = (*in)->func_start = str;
|
||||
(*in)->line = 1;
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF const char *
|
||||
ly_in_memory(struct ly_in *in, const char *str)
|
||||
{
|
||||
const char *data;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, in, in->type == LY_IN_MEMORY, NULL);
|
||||
|
||||
data = in->current;
|
||||
|
||||
if (str) {
|
||||
in->start = in->current = str;
|
||||
in->line = 1;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
ly_in_new_filepath(const char *filepath, size_t len, struct ly_in **in)
|
||||
{
|
||||
LY_ERR ret;
|
||||
char *fp;
|
||||
int fd;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, filepath, in, LY_EINVAL);
|
||||
|
||||
if (len) {
|
||||
fp = strndup(filepath, len);
|
||||
} else {
|
||||
fp = strdup(filepath);
|
||||
}
|
||||
|
||||
fd = open(fp, O_RDONLY);
|
||||
LY_CHECK_ERR_RET(fd == -1, LOGERR(NULL, LY_ESYS, "Failed to open file \"%s\" (%s).", fp, strerror(errno)); free(fp),
|
||||
LY_ESYS);
|
||||
|
||||
LY_CHECK_ERR_RET(ret = ly_in_new_fd(fd, in), free(fp), ret);
|
||||
|
||||
/* convert the LY_IN_FD input handler into the LY_IN_FILE */
|
||||
(*in)->type = LY_IN_FILEPATH;
|
||||
(*in)->method.fpath.fd = fd;
|
||||
(*in)->method.fpath.filepath = fp;
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF const char *
|
||||
ly_in_filepath(struct ly_in *in, const char *filepath, size_t len)
|
||||
{
|
||||
int fd, prev_fd;
|
||||
char *fp = NULL;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, in, in->type == LY_IN_FILEPATH, filepath ? NULL : ((void *)-1));
|
||||
|
||||
if (!filepath) {
|
||||
return in->method.fpath.filepath;
|
||||
}
|
||||
|
||||
if (len) {
|
||||
fp = strndup(filepath, len);
|
||||
} else {
|
||||
fp = strdup(filepath);
|
||||
}
|
||||
|
||||
/* replace filepath */
|
||||
fd = open(fp, O_RDONLY);
|
||||
LY_CHECK_ERR_RET(!fd, LOGERR(NULL, LY_ESYS, "Failed to open file \"%s\" (%s).", fp, strerror(errno)); free(fp), NULL);
|
||||
|
||||
/* convert LY_IN_FILEPATH handler into LY_IN_FD to be able to update it via ly_in_fd() */
|
||||
in->type = LY_IN_FD;
|
||||
prev_fd = ly_in_fd(in, fd);
|
||||
LY_CHECK_ERR_RET(prev_fd == -1, in->type = LY_IN_FILEPATH; free(fp), NULL);
|
||||
|
||||
/* and convert the result back */
|
||||
in->type = LY_IN_FILEPATH;
|
||||
close(prev_fd);
|
||||
free(in->method.fpath.filepath);
|
||||
in->method.fpath.fd = fd;
|
||||
in->method.fpath.filepath = fp;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF size_t
|
||||
ly_in_parsed(const struct ly_in *in)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, in, 0);
|
||||
|
||||
return in->current - in->func_start;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF void
|
||||
ly_in_free(struct ly_in *in, ly_bool destroy)
|
||||
{
|
||||
if (!in) {
|
||||
return;
|
||||
} else if (in->type == LY_IN_ERROR) {
|
||||
LOGINT(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (destroy) {
|
||||
if (in->type == LY_IN_MEMORY) {
|
||||
free((char *)in->start);
|
||||
} else {
|
||||
ly_munmap((char *)in->start, in->length);
|
||||
|
||||
if (in->type == LY_IN_FILE) {
|
||||
fclose(in->method.f);
|
||||
} else {
|
||||
close(in->method.fd);
|
||||
|
||||
if (in->type == LY_IN_FILEPATH) {
|
||||
free(in->method.fpath.filepath);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (in->type != LY_IN_MEMORY) {
|
||||
ly_munmap((char *)in->start, in->length);
|
||||
|
||||
if (in->type == LY_IN_FILEPATH) {
|
||||
close(in->method.fpath.fd);
|
||||
free(in->method.fpath.filepath);
|
||||
}
|
||||
}
|
||||
|
||||
free(in);
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
ly_in_read(struct ly_in *in, void *buf, size_t count)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, in, buf, LY_EINVAL);
|
||||
|
||||
if (in->length && (in->length - (in->current - in->start) < count)) {
|
||||
/* EOF */
|
||||
return LY_EDENIED;
|
||||
}
|
||||
|
||||
if (count) {
|
||||
memcpy(buf, in->current, count);
|
||||
}
|
||||
in->current += count;
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
ly_in_skip(struct ly_in *in, size_t count)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, in, LY_EINVAL);
|
||||
|
||||
if (in->length && (in->length - (in->current - in->start) < count)) {
|
||||
/* EOF */
|
||||
return LY_EDENIED;
|
||||
}
|
||||
|
||||
in->current += count;
|
||||
return LY_SUCCESS;
|
||||
}
|
252
src/in.h
Normal file
252
src/in.h
Normal file
|
@ -0,0 +1,252 @@
|
|||
/**
|
||||
* @file in.h
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @brief libyang input structures and functions
|
||||
*
|
||||
* Copyright (c) 2020 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef LY_IN_H_
|
||||
#define LY_IN_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @page howtoInput Input Processing
|
||||
*
|
||||
* libyang provides a mechanism to generalize work with the inputs (and [outputs](@ref howtoOutput)) of
|
||||
* the different types. The ::ly_in handler can be created providing necessary information connected with the specific
|
||||
* input type and then used throughout the parser functions processing the input data. Using a generic input handler avoids
|
||||
* need to have a set of functions for each parser functionality and results in simpler API.
|
||||
*
|
||||
* The API allows to alter the source of the data behind the handler by another source. Also resetting a seekable source
|
||||
* input is possible with ::ly_in_reset() to re-read the input.
|
||||
*
|
||||
* @note
|
||||
* Currently, libyang supports only reading data from standard (disk) file, not from sockets, pipes, etc. The reason is
|
||||
* that the parsers expects all the data to be present in the file (input data are complete). In future, we would like
|
||||
* to change the internal mechanism and support sequential processing of the input data. In XML wording - we have DOM
|
||||
* parser, but in future we would like to move to something like a SAX parser.
|
||||
*
|
||||
* @note
|
||||
* This mechanism was introduced in libyang 2.0. To simplify transition from libyang 1.0 to version 2.0 and also for
|
||||
* some simple use case where using the input handler would be an overkill, there are some basic parsers functions
|
||||
* that do not require input handler. But remember, that functionality of these function can be limited in particular cases
|
||||
* in contrast to the functions using input handlers.
|
||||
*
|
||||
* Functions List
|
||||
* --------------
|
||||
* - ::ly_in_new_fd()
|
||||
* - ::ly_in_new_file()
|
||||
* - ::ly_in_new_filepath()
|
||||
* - ::ly_in_new_memory()
|
||||
*
|
||||
* - ::ly_in_fd()
|
||||
* - ::ly_in_file()
|
||||
* - ::ly_in_filepath()
|
||||
* - ::ly_in_memory()
|
||||
*
|
||||
* - ::ly_in_type()
|
||||
* - ::ly_in_parsed()
|
||||
*
|
||||
* - ::ly_in_reset()
|
||||
* - ::ly_in_free()
|
||||
*
|
||||
* libyang Parsers List
|
||||
* --------------------
|
||||
* - @subpage howtoSchemaParsers
|
||||
* - @subpage howtoDataParsers
|
||||
*/
|
||||
|
||||
/**
|
||||
* @struct ly_in
|
||||
* @brief Parser input structure specifying where the data are read.
|
||||
*/
|
||||
struct ly_in;
|
||||
|
||||
/**
|
||||
* @brief Types of the parser's inputs
|
||||
*/
|
||||
typedef enum LY_IN_TYPE {
|
||||
LY_IN_ERROR = -1, /**< error value to indicate failure of the functions returning LY_IN_TYPE */
|
||||
LY_IN_FD, /**< file descriptor printer */
|
||||
LY_IN_FILE, /**< FILE stream parser */
|
||||
LY_IN_FILEPATH, /**< filepath parser */
|
||||
LY_IN_MEMORY /**< memory parser */
|
||||
} LY_IN_TYPE;
|
||||
|
||||
/**
|
||||
* @brief Get input type of the input handler.
|
||||
*
|
||||
* @param[in] in Input handler.
|
||||
* @return Type of the parser's input.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_IN_TYPE ly_in_type(const struct ly_in *in);
|
||||
|
||||
/**
|
||||
* @brief Reset the input medium to read from its beginning, so the following parser function will read from the object's beginning.
|
||||
*
|
||||
* Note that in case the underlying output is not seekable (stream referring a pipe/FIFO/socket or the callback output type),
|
||||
* nothing actually happens despite the function succeeds. Also note that the medium is not returned to the state it was when
|
||||
* the handler was created. For example, file is seeked into the offset zero, not to the offset where it was opened when
|
||||
* ::ly_in_new_file() was called.
|
||||
*
|
||||
* @param[in] in Input handler.
|
||||
* @return LY_SUCCESS in case of success
|
||||
* @return LY_ESYS in case of failure
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_in_reset(struct ly_in *in);
|
||||
|
||||
/**
|
||||
* @brief Create input handler using file descriptor.
|
||||
*
|
||||
* @param[in] fd File descriptor to use.
|
||||
* @param[out] in Created input handler supposed to be passed to different ly*_parse() functions.
|
||||
* @return LY_SUCCESS in case of success
|
||||
* @return LY_ERR value in case of failure.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_in_new_fd(int fd, struct ly_in **in);
|
||||
|
||||
/**
|
||||
* @brief Get or reset file descriptor input handler.
|
||||
*
|
||||
* @param[in] in Input handler.
|
||||
* @param[in] fd Optional value of a new file descriptor for the handler. If -1, only the current file descriptor value is returned.
|
||||
* @return Previous value of the file descriptor. Note that caller is responsible for closing the returned file descriptor in case of setting new descriptor @p fd.
|
||||
* @return -1 in case of error when setting up the new file descriptor.
|
||||
*/
|
||||
LIBYANG_API_DECL int ly_in_fd(struct ly_in *in, int fd);
|
||||
|
||||
/**
|
||||
* @brief Create input handler using file stream.
|
||||
*
|
||||
* @param[in] f File stream to use.
|
||||
* @param[out] in Created input handler supposed to be passed to different ly*_parse() functions.
|
||||
* @return LY_SUCCESS in case of success
|
||||
* @return LY_ERR value in case of failure.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_in_new_file(FILE *f, struct ly_in **in);
|
||||
|
||||
/**
|
||||
* @brief Get or reset file stream input handler.
|
||||
*
|
||||
* @param[in] in Input handler.
|
||||
* @param[in] f Optional new file stream for the handler. If NULL, only the current file stream is returned.
|
||||
* @return NULL in case of invalid argument or an error when setting up the new input file, original input handler @p in is untouched in this case.
|
||||
* @return Previous file stream of the handler. Note that caller is responsible for closing the returned stream in case of setting new stream @p f.
|
||||
*/
|
||||
LIBYANG_API_DECL FILE *ly_in_file(struct ly_in *in, FILE *f);
|
||||
|
||||
/**
|
||||
* @brief Create input handler using memory to read data.
|
||||
*
|
||||
* @param[in] str Pointer where to start reading data. The input data are expected to be NULL-terminated.
|
||||
* Note that in case the destroy argument of ::ly_in_free() is used, the input string is passed to free(),
|
||||
* so if it is really a static string, do not use the destroy argument!
|
||||
* @param[out] in Created input handler supposed to be passed to different ly*_parse() functions.
|
||||
* @return LY_SUCCESS in case of success
|
||||
* @return LY_ERR value in case of failure.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_in_new_memory(const char *str, struct ly_in **in);
|
||||
|
||||
/**
|
||||
* @brief Get or change memory where the data are read from.
|
||||
*
|
||||
* @param[in] in Input handler.
|
||||
* @param[in] str String containing the data to read. The input data are expected to be NULL-terminated.
|
||||
* Note that in case the destroy argument of ::ly_in_free() is used, the input string is passed to free(),
|
||||
* so if it is really a static string, do not use the destroy argument!
|
||||
* @return Previous starting address to read data from. Note that the caller is responsible to free
|
||||
* the data in case of changing string pointer @p str.
|
||||
*/
|
||||
LIBYANG_API_DECL const char *ly_in_memory(struct ly_in *in, const char *str);
|
||||
|
||||
/**
|
||||
* @brief Create input handler file of the given filename.
|
||||
*
|
||||
* @param[in] filepath Path of the file where to read data.
|
||||
* @param[in] len Optional number of bytes to use from @p filepath. If 0, the @p filepath is considered to be NULL-terminated and
|
||||
* the whole string is taken into account.
|
||||
* @param[out] in Created input handler supposed to be passed to different ly*_parse() functions.
|
||||
* @return LY_SUCCESS in case of success
|
||||
* @return LY_ERR value in case of failure.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_in_new_filepath(const char *filepath, size_t len, struct ly_in **in);
|
||||
|
||||
/**
|
||||
* @brief Get or change the filepath of the file where the parser reads the data.
|
||||
*
|
||||
* Note that in case of changing the filepath, the current file is closed and a new one is
|
||||
* created/opened instead of renaming the previous file. Also note that the previous filepath
|
||||
* string is returned only in case of not changing it's value.
|
||||
*
|
||||
* @param[in] in Input handler.
|
||||
* @param[in] filepath Optional new filepath for the handler. If and only if NULL, the current filepath string is returned.
|
||||
* @param[in] len Optional number of bytes to use from @p filepath. If 0, the @p filepath is considered to be NULL-terminated and
|
||||
* the whole string is taken into account.
|
||||
* @return Previous filepath string in case the @p filepath argument is NULL.
|
||||
* @return NULL if changing filepath succeedes and ((void *)-1) otherwise.
|
||||
*/
|
||||
LIBYANG_API_DECL const char *ly_in_filepath(struct ly_in *in, const char *filepath, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Get the number of parsed bytes by the last function.
|
||||
*
|
||||
* @param[in] in In structure used.
|
||||
* @return Number of parsed bytes.
|
||||
*/
|
||||
LIBYANG_API_DECL size_t ly_in_parsed(const struct ly_in *in);
|
||||
|
||||
/**
|
||||
* @brief Free the input handler.
|
||||
*
|
||||
* @param[in] in Input handler to free.
|
||||
* @param[in] destroy Flag to free the input data buffer (for LY_IN_MEMORY) or to
|
||||
* close stream/file descriptor (for LY_IN_FD and LY_IN_FILE)
|
||||
*/
|
||||
LIBYANG_API_DECL void ly_in_free(struct ly_in *in, ly_bool destroy);
|
||||
|
||||
/**
|
||||
* @brief Read bytes from an input.
|
||||
*
|
||||
* Does not count new lines, which is expected from the caller who has better idea about
|
||||
* the content of the read data and can better optimize counting.
|
||||
*
|
||||
* @param[in] in Input structure.
|
||||
* @param[in] buf Destination buffer.
|
||||
* @param[in] count Number of bytes to read.
|
||||
* @return LY_SUCCESS on success,
|
||||
* @return LY_EDENIED on EOF.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_in_read(struct ly_in *in, void *buf, size_t count);
|
||||
|
||||
/**
|
||||
* @brief Just skip bytes in an input.
|
||||
*
|
||||
* Does not count new lines, which is expected from the caller who has better idea about
|
||||
* the content of the skipped data and can better optimize counting.
|
||||
*
|
||||
* @param[in] in Input structure.
|
||||
* @param[in] count Number of bytes to skip.
|
||||
* @return LY_SUCCESS on success,
|
||||
* @return LY_EDENIED on EOF.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_in_skip(struct ly_in *in, size_t count);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LY_IN_H_ */
|
50
src/in_internal.h
Normal file
50
src/in_internal.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* @file in_internal.h
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief Internal structures and functions for libyang parsers
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef LY_IN_INTERNAL_H_
|
||||
#define LY_IN_INTERNAL_H_
|
||||
|
||||
#include "in.h"
|
||||
|
||||
/**
|
||||
* @brief Parser input structure specifying where the data are read.
|
||||
*/
|
||||
struct ly_in {
|
||||
LY_IN_TYPE type; /**< type of the output to select the output method */
|
||||
const char *current; /**< Current position in the input data */
|
||||
const char *func_start; /**< Input data position when the last parser function was executed */
|
||||
const char *start; /**< Input data start */
|
||||
size_t length; /**< mmap() length (if used) */
|
||||
|
||||
union {
|
||||
int fd; /**< file descriptor for LY_IN_FD type */
|
||||
FILE *f; /**< file structure for LY_IN_FILE and LY_IN_FILEPATH types */
|
||||
|
||||
struct {
|
||||
int fd; /**< file descriptor for LY_IN_FILEPATH */
|
||||
char *filepath; /**< stored original filepath */
|
||||
} fpath; /**< filepath structure for LY_IN_FILEPATH */
|
||||
} method; /**< type-specific information about the output */
|
||||
uint64_t line; /**< current line of the input */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Increment line counter.
|
||||
* @param[in] IN The input handler.
|
||||
*/
|
||||
#define LY_IN_NEW_LINE(IN) \
|
||||
(IN)->line++
|
||||
|
||||
#endif /* LY_IN_INTERNAL_H_ */
|
1096
src/json.c
Normal file
1096
src/json.c
Normal file
File diff suppressed because it is too large
Load diff
150
src/json.h
Normal file
150
src/json.h
Normal file
|
@ -0,0 +1,150 @@
|
|||
/**
|
||||
* @file json.h
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief Generic JSON format parser routines.
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef LY_JSON_H_
|
||||
#define LY_JSON_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "set.h"
|
||||
|
||||
struct ly_ctx;
|
||||
struct ly_in;
|
||||
|
||||
#define LYJSON_STRING_BUF_START 24
|
||||
#define LYJSON_STRING_BUF_STEP 128
|
||||
|
||||
/* Macro to test if character is whitespace */
|
||||
#define is_jsonws(c) (c == 0x20 || c == 0x9 || c == 0xa || c == 0xd)
|
||||
|
||||
/* Macro to test if character is valid string character */
|
||||
#define is_jsonstrchar(c) (c == 0x20 || c == 0x21 || (c >= 0x23 && c <= 0x5b) || (c >= 0x5d && c <= 0x10ffff))
|
||||
|
||||
/* Macro to push JSON parser status */
|
||||
#define LYJSON_STATUS_PUSH_RET(CTX, STATUS) \
|
||||
LY_CHECK_RET(ly_set_add(&CTX->status, (void *)(uintptr_t)(STATUS), 1, NULL))
|
||||
|
||||
/* Macro to pop JSON parser status */
|
||||
#define LYJSON_STATUS_POP(CTX) \
|
||||
assert(CTX->status.count); CTX->status.count--;
|
||||
|
||||
/**
|
||||
* @brief Status of the parser providing information what is expected next (which function is supposed to be called).
|
||||
*/
|
||||
enum LYJSON_PARSER_STATUS {
|
||||
LYJSON_ERROR = 0, /* JSON parser error - value is used as an error return code */
|
||||
LYJSON_OBJECT, /* JSON object */
|
||||
LYJSON_OBJECT_NEXT, /* JSON object next item */
|
||||
LYJSON_OBJECT_CLOSED, /* JSON object closed */
|
||||
LYJSON_ARRAY, /* JSON array */
|
||||
LYJSON_ARRAY_NEXT, /* JSON array next item */
|
||||
LYJSON_ARRAY_CLOSED, /* JSON array closed */
|
||||
LYJSON_OBJECT_NAME, /* JSON object name */
|
||||
LYJSON_NUMBER, /* JSON number value */
|
||||
LYJSON_STRING, /* JSON string value */
|
||||
LYJSON_TRUE, /* JSON true value */
|
||||
LYJSON_FALSE, /* JSON false value */
|
||||
LYJSON_NULL, /* JSON null value */
|
||||
LYJSON_END /* end of input data */
|
||||
};
|
||||
|
||||
struct lyjson_ctx {
|
||||
const struct ly_ctx *ctx;
|
||||
struct ly_in *in; /* input structure */
|
||||
|
||||
struct ly_set status; /* stack of ::LYJSON_PARSER_STATUS values corresponding to the JSON items being processed */
|
||||
|
||||
const char *value; /* ::LYJSON_STRING, ::LYJSON_NUMBER, ::LYJSON_OBJECT_NAME */
|
||||
size_t value_len; /* ::LYJSON_STRING, ::LYJSON_NUMBER, ::LYJSON_OBJECT_NAME */
|
||||
ly_bool dynamic; /* ::LYJSON_STRING, ::LYJSON_NUMBER, ::LYJSON_OBJECT_NAME */
|
||||
|
||||
struct {
|
||||
enum LYJSON_PARSER_STATUS status;
|
||||
uint32_t status_count;
|
||||
const char *value;
|
||||
size_t value_len;
|
||||
ly_bool dynamic;
|
||||
const char *input;
|
||||
} backup;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Get string representation of the JSON context status (token).
|
||||
*
|
||||
* @param[in] status Context status (aka JSON token)
|
||||
* @return String representation of the @p status.
|
||||
*/
|
||||
const char *lyjson_token2str(enum LYJSON_PARSER_STATUS status);
|
||||
|
||||
/**
|
||||
* @brief Get current status of the parser.
|
||||
*
|
||||
* @param[in] jsonctx JSON parser context to check.
|
||||
* @return ::LYJSON_PARSER_STATUS according to the last parsed token.
|
||||
*/
|
||||
enum LYJSON_PARSER_STATUS lyjson_ctx_status(struct lyjson_ctx *jsonctx);
|
||||
|
||||
/**
|
||||
* @brief Get current nesting (object/array) depth.
|
||||
*
|
||||
* @param[in] jsonctx JSON parser context to check.
|
||||
* @return Current nesting depth.
|
||||
*/
|
||||
uint32_t lyjson_ctx_depth(struct lyjson_ctx *jsonctx);
|
||||
|
||||
/**
|
||||
* @brief Create a new JSON parser context and start parsing.
|
||||
*
|
||||
* @param[in] ctx libyang context.
|
||||
* @param[in] in JSON string data to parse.
|
||||
* @param[in] subtree Whether this is a special case of parsing a subtree (starting with object name).
|
||||
* @param[out] jsonctx New JSON parser context with status referring the parsed value.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
LY_ERR lyjson_ctx_new(const struct ly_ctx *ctx, struct ly_in *in, struct lyjson_ctx **jsonctx);
|
||||
|
||||
/**
|
||||
* @brief Move to the next JSON artifact and update parser status.
|
||||
*
|
||||
* @param[in] jsonctx XML context to move.
|
||||
* @param[out] status Optional parameter to provide new parser status
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
LY_ERR lyjson_ctx_next(struct lyjson_ctx *jsonctx, enum LYJSON_PARSER_STATUS *status);
|
||||
|
||||
/**
|
||||
* @brief Backup the JSON parser context's state To restore the backup, use ::lyjson_ctx_restore().
|
||||
*
|
||||
* @param[in] jsonctx JSON parser context to backup.
|
||||
*/
|
||||
void lyjson_ctx_backup(struct lyjson_ctx *jsonctx);
|
||||
|
||||
/**
|
||||
* @brief Restore the JSON parser context's state from the backup created by ::lyjson_ctx_backup().
|
||||
*
|
||||
* @param[in] jsonctx JSON parser context to restore.
|
||||
*/
|
||||
void lyjson_ctx_restore(struct lyjson_ctx *jsonctx);
|
||||
|
||||
/**
|
||||
* @brief Remove the allocated working memory of the context.
|
||||
*
|
||||
* @param[in] jsonctx JSON parser context to clear.
|
||||
*/
|
||||
void lyjson_ctx_free(struct lyjson_ctx *jsonctx);
|
||||
|
||||
#endif /* LY_JSON_H_ */
|
178
src/libyang.h
Normal file
178
src/libyang.h
Normal file
|
@ -0,0 +1,178 @@
|
|||
/**
|
||||
* @file libyang.h
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief The main libyang public header.
|
||||
*
|
||||
* Copyright (c) 2015 - 2024 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef LY_LIBYANG_H_
|
||||
#define LY_LIBYANG_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "context.h"
|
||||
#include "dict.h"
|
||||
#include "in.h"
|
||||
#include "log.h"
|
||||
#include "metadata.h"
|
||||
#include "out.h"
|
||||
#include "parser_data.h"
|
||||
#include "parser_schema.h"
|
||||
#include "printer_data.h"
|
||||
#include "printer_schema.h"
|
||||
#include "set.h"
|
||||
#include "tree.h"
|
||||
#include "tree_data.h"
|
||||
#include "tree_schema.h"
|
||||
|
||||
/**
|
||||
* @brief libyang v3 compatibility macros with v2.
|
||||
*/
|
||||
#define ly_strerrcode ly_strerr
|
||||
#define ly_last_errmsg ly_last_logmsg
|
||||
#define ly_errcode(ctx) (ly_err_last(ctx) ? ly_err_last(ctx)->err : 0)
|
||||
#define ly_errmsg(ctx) (ly_err_last(ctx) ? ly_err_last(ctx)->msg : NULL)
|
||||
#define ly_errpath(ctx) (ly_err_last(ctx) ? (ly_err_last(ctx)->data_path ? ly_err_last(ctx)->data_path : ly_err_last(ctx)->schema_path) : NULL)
|
||||
#define ly_vecode(ctx) (ly_err_last(ctx) ? ly_err_last(ctx)->vecode : 0)
|
||||
|
||||
/*
|
||||
* The following headers are supposed to be included explicitly:
|
||||
* - hash_table.h
|
||||
* - metadata.h
|
||||
* - plugins_types.h
|
||||
* - plugins_exts.h
|
||||
*/
|
||||
|
||||
/**
|
||||
* @mainpage About
|
||||
*
|
||||
* libyang is a library implementing processing of the YANG schemas and data modeled by the YANG language. The
|
||||
* library is implemented in C for GNU/Linux and provides C API.
|
||||
*
|
||||
* @section about-features Main Features
|
||||
*
|
||||
* - [Parsing (and validating) schemas](@ref howtoSchema) in YANG format.
|
||||
* - [Parsing (and validating) schemas](@ref howtoSchema) in YIN format.
|
||||
* - [Parsing, validating and printing instance data](@ref howtoData) in XML format.
|
||||
* - [Parsing, validating and printing instance data](@ref howtoData) in JSON format
|
||||
* ([RFC 7951](https://tools.ietf.org/html/rfc7951)).
|
||||
* - [Manipulation with the instance data](@ref howtoDataManipulation).
|
||||
* - Support for [default values in the instance data](@ref howtoDataWD) ([RFC 6243](https://tools.ietf.org/html/rfc6243)).
|
||||
* - Support for [YANG extensions and user types](@ref howtoPlugins).
|
||||
* - Support for [YANG Metadata](@ref howtoDataMetadata) ([RFC 7952](https://tools.ietf.org/html/rfc6243)).
|
||||
* - Support for [YANG Schema Mount](@ref howtoDataMountpoint) ([RFC 8528](https://tools.ietf.org/html/rfc8528)).
|
||||
*
|
||||
* The current implementation covers YANG 1.0 ([RFC 6020](https://tools.ietf.org/html/rfc6020)) as well as
|
||||
* YANG 1.1 ([RFC 7950](https://tools.ietf.org/html/rfc7950)).
|
||||
*
|
||||
* @section about-license License
|
||||
*
|
||||
* Copyright (c) 2015-2024 CESNET, z.s.p.o.
|
||||
*
|
||||
* (The BSD 3-Clause License)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Company nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page howto libyang API Overview
|
||||
*
|
||||
* @section howtoGeneral General notes
|
||||
*
|
||||
* libyang is primarily intended for handling data modeled by YANG modeling language, so the library is supposed to be optimized
|
||||
* for this purpose. However, as a side effect, the library has to be able precisely process YANG modules. Thus, it is usable by
|
||||
* YANG module authors to validate their modules and schemas in the development process.
|
||||
*
|
||||
* - @subpage howtoStructures
|
||||
* - @subpage howtoErrors
|
||||
* - @subpage howtoLogger
|
||||
* - @subpage howtoThreads
|
||||
* - @subpage howtoContext
|
||||
* - @subpage howtoInput
|
||||
* - @subpage howtoOutput
|
||||
* - @subpage howtoSchema
|
||||
* - @subpage howtoData
|
||||
* - @subpage howtoXPath
|
||||
* - @subpage howtoPlugins
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page howtoStructures Data Structures
|
||||
*
|
||||
* @section sizedarrays Sized Arrays
|
||||
*
|
||||
* The structure starts with 32bit number storing size of the array - the number of the items inside. The size is part of the
|
||||
* array to have it allocated together with the array itself only when it is needed. However, the pointers to the array always
|
||||
* points after the 32b number, so items can be accessed directly as for standard C arrays. Because of a known size (available
|
||||
* via ::LY_ARRAY_COUNT macro), it is not terminated by any special byte (sequence), so there is also no limitation for specific
|
||||
* content of the stored records (e.g. that first byte must not be NULL).
|
||||
*
|
||||
* The sized arrays must be carefully freed (which should be done anyway only internally), since pointers to the sized arrays used
|
||||
* in libyang structures, does not point to the beginning of the allocated space.
|
||||
*
|
||||
* - ::LY_ARRAY_COUNT
|
||||
* - ::LY_ARRAY_FOR
|
||||
*
|
||||
* @section struct_lists Lists
|
||||
*
|
||||
* The lists are structures connected via a `next` and `prev` pointers. Iterating over the siblings can be simply done by
|
||||
* ::LY_LIST_FOR macro. Examples of such structures are ::lyd_node or ::lysc_node.
|
||||
*
|
||||
* The `prev` pointer is always filled. In case there is just a single item in the list, the `prev` pointer points to the
|
||||
* item itself. Otherwise, the `prev` pointer of the first item points to the last item of the list. In contrast, the
|
||||
* `next` pointer of the last item in the list is always NULL.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page howtoThreads Threading Limitations
|
||||
*
|
||||
* @section context Context
|
||||
*
|
||||
* It is safe to read from ::ly_ctx structure concurrently and use its dictionary, which is protected by a lock.
|
||||
* Thread-safe functions include any ones working with data trees (only context dictionary is accessed) and all
|
||||
* the `ly_ctx_get_*()` functions. Generally, they are the functions with `const` context parameter.
|
||||
*
|
||||
* @section data Data Trees
|
||||
*
|
||||
* Data trees are not internally synchronized so the general safe practice of a single writer **or** several concurrent
|
||||
* readers should be followed. Specifically, only the functions with non-const ::lyd_node parameters modify the node(s)
|
||||
* and no concurrent execution of such functions should be allowed on a single data tree or subtrees of one.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @page internals Developers' Notes
|
||||
* @tableofcontents
|
||||
*
|
||||
* Following texts describes various internal subsystems and mechanism in libyang which are hidden from external users, but important
|
||||
* for libyang developers. The texts should explain various decisions made and internal processes utilized in libyang.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LY_LIBYANG_H_ */
|
985
src/log.c
Normal file
985
src/log.c
Normal file
|
@ -0,0 +1,985 @@
|
|||
/**
|
||||
* @file log.c
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief Logger routines implementations
|
||||
*
|
||||
* Copyright (c) 2015 - 2023 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE /* asprintf, strdup */
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "compat.h"
|
||||
#include "in_internal.h"
|
||||
#include "ly_common.h"
|
||||
#include "plugins_exts.h"
|
||||
#include "set.h"
|
||||
#include "tree_data.h"
|
||||
#include "tree_data_internal.h"
|
||||
#include "tree_schema.h"
|
||||
#include "tree_schema_internal.h"
|
||||
|
||||
ATOMIC_T ly_ll = (uint_fast32_t)LY_LLWRN;
|
||||
ATOMIC_T ly_log_opts = (uint_fast32_t)(LY_LOLOG | LY_LOSTORE_LAST);
|
||||
THREAD_LOCAL uint32_t *temp_ly_log_opts;
|
||||
static ly_log_clb log_clb;
|
||||
THREAD_LOCAL char last_msg[LY_LAST_MSG_SIZE];
|
||||
#ifndef NDEBUG
|
||||
ATOMIC_T ly_ldbg_groups = 0;
|
||||
#endif
|
||||
|
||||
THREAD_LOCAL struct ly_log_location_s log_location = {0};
|
||||
|
||||
LIBYANG_API_DEF const char *
|
||||
ly_strerr(LY_ERR err)
|
||||
{
|
||||
/* ignore plugin flag */
|
||||
err &= ~LY_EPLUGIN;
|
||||
|
||||
switch (err) {
|
||||
case LY_SUCCESS:
|
||||
return "Success";
|
||||
case LY_EMEM:
|
||||
return "Out of memory";
|
||||
case LY_ESYS:
|
||||
return "System call failed";
|
||||
case LY_EINVAL:
|
||||
return "Invalid value";
|
||||
case LY_EEXIST:
|
||||
return "Already exists";
|
||||
case LY_ENOTFOUND:
|
||||
return "Not found";
|
||||
case LY_EINT:
|
||||
return "Internal error";
|
||||
case LY_EVALID:
|
||||
return "Validation failed";
|
||||
case LY_EDENIED:
|
||||
return "Operation denied";
|
||||
case LY_EINCOMPLETE:
|
||||
return "Operation incomplete";
|
||||
case LY_ERECOMPILE:
|
||||
return "Recompilation required";
|
||||
case LY_ENOT:
|
||||
return "Negative result";
|
||||
case LY_EOTHER:
|
||||
return "Another failure reason";
|
||||
case LY_EPLUGIN:
|
||||
break;
|
||||
}
|
||||
|
||||
/* unreachable */
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF const char *
|
||||
ly_strvecode(LY_VECODE vecode)
|
||||
{
|
||||
switch (vecode) {
|
||||
case LYVE_SUCCESS:
|
||||
return "Success";
|
||||
case LYVE_SYNTAX:
|
||||
return "General syntax error";
|
||||
case LYVE_SYNTAX_YANG:
|
||||
return "YANG syntax error";
|
||||
case LYVE_SYNTAX_YIN:
|
||||
return "YIN syntax error";
|
||||
case LYVE_REFERENCE:
|
||||
return "Reference error";
|
||||
case LYVE_XPATH:
|
||||
return "XPath error";
|
||||
case LYVE_SEMANTICS:
|
||||
return "Semantic error";
|
||||
case LYVE_SYNTAX_XML:
|
||||
return "XML syntax error";
|
||||
case LYVE_SYNTAX_JSON:
|
||||
return "JSON syntax error";
|
||||
case LYVE_DATA:
|
||||
return "YANG data error";
|
||||
case LYVE_OTHER:
|
||||
return "Another error";
|
||||
}
|
||||
|
||||
/* unreachable */
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF const char *
|
||||
ly_last_logmsg(void)
|
||||
{
|
||||
return last_msg;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
ly_err_new(struct ly_err_item **err, LY_ERR ecode, LY_VECODE vecode, char *data_path, char *apptag,
|
||||
const char *err_format, ...)
|
||||
{
|
||||
char *msg = NULL;
|
||||
struct ly_err_item *e;
|
||||
|
||||
if (!err || (ecode == LY_SUCCESS)) {
|
||||
/* nothing to do */
|
||||
return ecode;
|
||||
}
|
||||
|
||||
e = calloc(1, sizeof *e);
|
||||
LY_CHECK_ERR_RET(!e, LOGMEM(NULL), LY_EMEM);
|
||||
|
||||
e->prev = (*err) ? (*err)->prev : e;
|
||||
if (*err) {
|
||||
(*err)->prev->next = e;
|
||||
}
|
||||
|
||||
/* fill in the information */
|
||||
e->level = LY_LLERR;
|
||||
e->err = ecode;
|
||||
e->vecode = vecode;
|
||||
e->data_path = data_path;
|
||||
e->apptag = apptag;
|
||||
|
||||
if (err_format) {
|
||||
va_list print_args;
|
||||
|
||||
va_start(print_args, err_format);
|
||||
|
||||
if (vasprintf(&msg, err_format, print_args) == -1) {
|
||||
/* we don't have anything more to do, just set msg to NULL to avoid undefined content,
|
||||
* still keep the information about the original error instead of LY_EMEM or other printf's error */
|
||||
msg = NULL;
|
||||
}
|
||||
|
||||
va_end(print_args);
|
||||
}
|
||||
e->msg = msg;
|
||||
|
||||
if (!(*err)) {
|
||||
*err = e;
|
||||
}
|
||||
|
||||
return e->err;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get error record from error hash table of a context for the current thread.
|
||||
*
|
||||
* @param[in] ctx Context to use.
|
||||
* @return Thread error record, if any.
|
||||
*/
|
||||
static struct ly_ctx_err_rec *
|
||||
ly_err_get_rec(const struct ly_ctx *ctx)
|
||||
{
|
||||
struct ly_ctx_err_rec rec, *match;
|
||||
|
||||
/* prepare record */
|
||||
rec.tid = pthread_self();
|
||||
|
||||
/* get the pointer to the matching record */
|
||||
if (lyht_find(ctx->err_ht, &rec, lyht_hash((void *)&rec.tid, sizeof rec.tid), (void **)&match)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert new error record to error hash table of a context for the current thread.
|
||||
*
|
||||
* @param[in] ctx Context to use.
|
||||
* @return Thread error record.
|
||||
*/
|
||||
static struct ly_ctx_err_rec *
|
||||
ly_err_new_rec(const struct ly_ctx *ctx)
|
||||
{
|
||||
struct ly_ctx_err_rec new, *rec;
|
||||
LY_ERR r;
|
||||
|
||||
/* insert a new record */
|
||||
new.err = NULL;
|
||||
new.tid = pthread_self();
|
||||
|
||||
/* reuse lock */
|
||||
/* LOCK */
|
||||
pthread_mutex_lock((pthread_mutex_t *)&ctx->lyb_hash_lock);
|
||||
|
||||
r = lyht_insert(ctx->err_ht, &new, lyht_hash((void *)&new.tid, sizeof new.tid), (void **)&rec);
|
||||
|
||||
/* UNLOCK */
|
||||
pthread_mutex_unlock((pthread_mutex_t *)&ctx->lyb_hash_lock);
|
||||
|
||||
return r ? NULL : rec;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF const struct ly_err_item *
|
||||
ly_err_first(const struct ly_ctx *ctx)
|
||||
{
|
||||
struct ly_ctx_err_rec *rec;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, ctx, NULL);
|
||||
|
||||
/* get the pointer to the matching record */
|
||||
rec = ly_err_get_rec(ctx);
|
||||
|
||||
return rec ? rec->err : NULL;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF const struct ly_err_item *
|
||||
ly_err_last(const struct ly_ctx *ctx)
|
||||
{
|
||||
struct ly_ctx_err_rec *rec;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, ctx, NULL);
|
||||
|
||||
/* get the pointer to the matching record */
|
||||
if (!(rec = ly_err_get_rec(ctx))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rec->err ? rec->err->prev : NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ly_err_move(struct ly_ctx *src_ctx, struct ly_ctx *trg_ctx)
|
||||
{
|
||||
struct ly_ctx_err_rec *rec;
|
||||
struct ly_err_item *err = NULL;
|
||||
|
||||
/* get and remove the errors from src */
|
||||
rec = ly_err_get_rec(src_ctx);
|
||||
if (rec) {
|
||||
err = rec->err;
|
||||
rec->err = NULL;
|
||||
}
|
||||
|
||||
/* set them for trg */
|
||||
if (!(rec = ly_err_get_rec(trg_ctx))) {
|
||||
if (!(rec = ly_err_new_rec(trg_ctx))) {
|
||||
LOGINT(NULL);
|
||||
ly_err_free(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ly_err_free(rec->err);
|
||||
rec->err = err;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF void
|
||||
ly_err_free(void *ptr)
|
||||
{
|
||||
struct ly_err_item *e, *next;
|
||||
|
||||
/* clean the error list */
|
||||
LY_LIST_FOR_SAFE(ptr, next, e) {
|
||||
free(e->msg);
|
||||
free(e->data_path);
|
||||
free(e->schema_path);
|
||||
free(e->apptag);
|
||||
free(e);
|
||||
}
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF void
|
||||
ly_err_clean(struct ly_ctx *ctx, struct ly_err_item *eitem)
|
||||
{
|
||||
struct ly_ctx_err_rec *rec;
|
||||
struct ly_err_item *e;
|
||||
|
||||
if (!(rec = ly_err_get_rec(ctx))) {
|
||||
return;
|
||||
}
|
||||
if (rec->err == eitem) {
|
||||
eitem = NULL;
|
||||
}
|
||||
|
||||
if (!eitem) {
|
||||
/* free all err */
|
||||
ly_err_free(rec->err);
|
||||
rec->err = NULL;
|
||||
} else {
|
||||
/* disconnect the error */
|
||||
for (e = rec->err; e && (e->next != eitem); e = e->next) {}
|
||||
assert(e);
|
||||
e->next = NULL;
|
||||
rec->err->prev = e;
|
||||
/* free this err and newer */
|
||||
ly_err_free(eitem);
|
||||
}
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_LOG_LEVEL
|
||||
ly_log_level(LY_LOG_LEVEL level)
|
||||
{
|
||||
LY_LOG_LEVEL prev = ATOMIC_LOAD_RELAXED(ly_ll);
|
||||
|
||||
ATOMIC_STORE_RELAXED(ly_ll, level);
|
||||
return prev;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF uint32_t
|
||||
ly_log_options(uint32_t opts)
|
||||
{
|
||||
uint32_t prev = ATOMIC_LOAD_RELAXED(ly_log_opts);
|
||||
|
||||
ATOMIC_STORE_RELAXED(ly_log_opts, opts);
|
||||
return prev;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF uint32_t *
|
||||
ly_temp_log_options(uint32_t *opts)
|
||||
{
|
||||
uint32_t *prev_lo = temp_ly_log_opts;
|
||||
|
||||
temp_ly_log_opts = opts;
|
||||
|
||||
return prev_lo;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF uint32_t
|
||||
ly_log_dbg_groups(uint32_t dbg_groups)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
uint32_t prev = ATOMIC_LOAD_RELAXED(ly_ldbg_groups);
|
||||
|
||||
ATOMIC_STORE_RELAXED(ly_ldbg_groups, dbg_groups);
|
||||
return prev;
|
||||
#else
|
||||
(void)dbg_groups;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF void
|
||||
ly_set_log_clb(ly_log_clb clb)
|
||||
{
|
||||
log_clb = clb;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF ly_log_clb
|
||||
ly_get_log_clb(void)
|
||||
{
|
||||
return log_clb;
|
||||
}
|
||||
|
||||
void
|
||||
ly_log_location(const struct lysc_node *scnode, const struct lyd_node *dnode, const char *spath, const struct ly_in *in)
|
||||
{
|
||||
if (scnode) {
|
||||
ly_set_add(&log_location.scnodes, (void *)scnode, 1, NULL);
|
||||
}
|
||||
if (dnode || (!scnode && !spath && !in)) {
|
||||
ly_set_add(&log_location.dnodes, (void *)dnode, 1, NULL);
|
||||
}
|
||||
if (spath) {
|
||||
char *s = strdup(spath);
|
||||
|
||||
LY_CHECK_ERR_RET(!s, LOGMEM(NULL), );
|
||||
ly_set_add(&log_location.spaths, s, 1, NULL);
|
||||
}
|
||||
if (in) {
|
||||
ly_set_add(&log_location.inputs, (void *)in, 1, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ly_log_location_revert(uint32_t scnode_steps, uint32_t dnode_steps, uint32_t spath_steps, uint32_t in_steps)
|
||||
{
|
||||
for (uint32_t i = scnode_steps; i && log_location.scnodes.count; i--) {
|
||||
log_location.scnodes.count--;
|
||||
}
|
||||
|
||||
for (uint32_t i = dnode_steps; i && log_location.dnodes.count; i--) {
|
||||
log_location.dnodes.count--;
|
||||
}
|
||||
|
||||
for (uint32_t i = spath_steps; i && log_location.spaths.count; i--) {
|
||||
ly_set_rm_index(&log_location.spaths, log_location.spaths.count - 1, free);
|
||||
}
|
||||
|
||||
for (uint32_t i = in_steps; i && log_location.inputs.count; i--) {
|
||||
log_location.inputs.count--;
|
||||
}
|
||||
|
||||
/* deallocate the empty sets */
|
||||
if (scnode_steps && !log_location.scnodes.count) {
|
||||
ly_set_erase(&log_location.scnodes, NULL);
|
||||
}
|
||||
if (dnode_steps && !log_location.dnodes.count) {
|
||||
ly_set_erase(&log_location.dnodes, NULL);
|
||||
}
|
||||
if (spath_steps && !log_location.spaths.count) {
|
||||
ly_set_erase(&log_location.spaths, free);
|
||||
}
|
||||
if (in_steps && !log_location.inputs.count) {
|
||||
ly_set_erase(&log_location.inputs, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
const struct lyd_node *
|
||||
ly_log_location_dnode(uint32_t idx)
|
||||
{
|
||||
if (idx < log_location.dnodes.count) {
|
||||
return log_location.dnodes.dnodes[idx];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ly_log_location_dnode_count(void)
|
||||
{
|
||||
return log_location.dnodes.count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Store generated error in a context.
|
||||
*
|
||||
* @param[in] ctx Context to use.
|
||||
* @param[in] level Message log level.
|
||||
* @param[in] err Error number.
|
||||
* @param[in] vecode Error validation error code.
|
||||
* @param[in] msg Error message, always spent.
|
||||
* @param[in] data_path Error data path, always spent.
|
||||
* @param[in] schema_path Error schema path, always spent.
|
||||
* @param[in] line Error input line, if any.
|
||||
* @param[in] apptag Error app tag, always spent.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
static LY_ERR
|
||||
log_store(const struct ly_ctx *ctx, LY_LOG_LEVEL level, LY_ERR err, LY_VECODE vecode, char *msg, char *data_path,
|
||||
char *schema_path, uint64_t line, char *apptag)
|
||||
{
|
||||
struct ly_ctx_err_rec *rec;
|
||||
struct ly_err_item *e, *last;
|
||||
|
||||
assert(ctx && (level < LY_LLVRB));
|
||||
|
||||
if (!(rec = ly_err_get_rec(ctx))) {
|
||||
if (!(rec = ly_err_new_rec(ctx))) {
|
||||
goto mem_fail;
|
||||
}
|
||||
}
|
||||
|
||||
e = rec->err;
|
||||
if (!e) {
|
||||
/* if we are only to fill in path, there must have been an error stored */
|
||||
assert(msg);
|
||||
e = calloc(1, sizeof *e);
|
||||
LY_CHECK_GOTO(!e, mem_fail);
|
||||
e->prev = e;
|
||||
e->next = NULL;
|
||||
|
||||
rec->err = e;
|
||||
} else if (!msg) {
|
||||
/* only filling the path */
|
||||
assert(data_path || schema_path);
|
||||
|
||||
/* find last error */
|
||||
e = e->prev;
|
||||
do {
|
||||
if (e->level == LY_LLERR) {
|
||||
/* fill the path */
|
||||
if (data_path) {
|
||||
free(e->data_path);
|
||||
e->data_path = data_path;
|
||||
} else {
|
||||
free(e->schema_path);
|
||||
e->schema_path = schema_path;
|
||||
}
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
e = e->prev;
|
||||
} while (e->prev->next);
|
||||
/* last error was not found */
|
||||
assert(0);
|
||||
} else if ((temp_ly_log_opts && ((*temp_ly_log_opts & LY_LOSTORE_LAST) == LY_LOSTORE_LAST)) ||
|
||||
(!temp_ly_log_opts && ((ATOMIC_LOAD_RELAXED(ly_log_opts) & LY_LOSTORE_LAST) == LY_LOSTORE_LAST))) {
|
||||
/* overwrite last message */
|
||||
free(e->msg);
|
||||
free(e->data_path);
|
||||
free(e->schema_path);
|
||||
free(e->apptag);
|
||||
} else {
|
||||
/* store new message */
|
||||
last = e->prev;
|
||||
e->prev = calloc(1, sizeof *e);
|
||||
LY_CHECK_GOTO(!e->prev, mem_fail);
|
||||
e = e->prev;
|
||||
e->prev = last;
|
||||
e->next = NULL;
|
||||
last->next = e;
|
||||
}
|
||||
|
||||
/* fill in the information */
|
||||
e->level = level;
|
||||
e->err = err;
|
||||
e->vecode = vecode;
|
||||
e->msg = msg;
|
||||
e->data_path = data_path;
|
||||
e->schema_path = schema_path;
|
||||
e->line = line;
|
||||
e->apptag = apptag;
|
||||
return LY_SUCCESS;
|
||||
|
||||
mem_fail:
|
||||
LOGMEM(NULL);
|
||||
free(msg);
|
||||
free(data_path);
|
||||
free(schema_path);
|
||||
free(apptag);
|
||||
return LY_EMEM;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Log data path/schema path/line to stderr after the message has been printed.
|
||||
*
|
||||
* @param[in] data_path Error data path.
|
||||
* @param[in] schema_path Error schema path.
|
||||
* @param[in] line Error input line.
|
||||
*/
|
||||
static void
|
||||
log_stderr_path_line(const char *data_path, const char *schema_path, uint64_t line)
|
||||
{
|
||||
ly_bool par = 0;
|
||||
|
||||
if (data_path) {
|
||||
fprintf(stderr, "%sdata path: %s", " (", data_path);
|
||||
par = 1;
|
||||
}
|
||||
|
||||
if (schema_path) {
|
||||
fprintf(stderr, "%sschemadata path: %s", par ? ", " : " (", schema_path);
|
||||
par = 1;
|
||||
}
|
||||
|
||||
if (line) {
|
||||
fprintf(stderr, "%sline: %" PRIu64, par ? ", " : " (", line);
|
||||
par = 1;
|
||||
}
|
||||
|
||||
fprintf(stderr, par ? ")\n" : "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Log a message.
|
||||
*
|
||||
* @param[in] ctx Context to use.
|
||||
* @param[in] level Message log level.
|
||||
* @param[in] err Error number.
|
||||
* @param[in] vecode Error validation error code.
|
||||
* @param[in] data_path Error data path, always spent.
|
||||
* @param[in] schema_path Error schema path, always spent.
|
||||
* @param[in] line Error input line, if any.
|
||||
* @param[in] apptag Error app tag.
|
||||
* @param[in] format Error message format.
|
||||
* @param[in] args Error message format arguments.
|
||||
*/
|
||||
static void
|
||||
log_vprintf(const struct ly_ctx *ctx, LY_LOG_LEVEL level, LY_ERR err, LY_VECODE vecode, char *data_path,
|
||||
char *schema_path, uint64_t line, const char *apptag, const char *format, va_list args)
|
||||
{
|
||||
char *dyn_msg = NULL;
|
||||
const char *msg;
|
||||
ly_bool free_strs = 1, lolog, lostore;
|
||||
|
||||
/* learn effective logger options */
|
||||
if (temp_ly_log_opts) {
|
||||
lolog = *temp_ly_log_opts & LY_LOLOG;
|
||||
lostore = *temp_ly_log_opts & LY_LOSTORE;
|
||||
} else {
|
||||
lolog = ATOMIC_LOAD_RELAXED(ly_log_opts) & LY_LOLOG;
|
||||
lostore = ATOMIC_LOAD_RELAXED(ly_log_opts) & LY_LOSTORE;
|
||||
}
|
||||
|
||||
if (level > ATOMIC_LOAD_RELAXED(ly_ll)) {
|
||||
/* do not print or store the message */
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (err == LY_EMEM) {
|
||||
/* no not use more dynamic memory */
|
||||
vsnprintf(last_msg, LY_LAST_MSG_SIZE, format, args);
|
||||
msg = last_msg;
|
||||
} else {
|
||||
/* print into a single message */
|
||||
if (vasprintf(&dyn_msg, format, args) == -1) {
|
||||
LOGMEM(ctx);
|
||||
goto cleanup;
|
||||
}
|
||||
msg = dyn_msg;
|
||||
|
||||
/* store as the last message */
|
||||
strncpy(last_msg, msg, LY_LAST_MSG_SIZE - 1);
|
||||
}
|
||||
|
||||
/* store the error/warning in the context (if we need to store errors internally, it does not matter what are
|
||||
* the user log options), if the message is not dynamic, it would most likely fail to store (no memory) */
|
||||
if ((level < LY_LLVRB) && ctx && lostore && dyn_msg) {
|
||||
free_strs = 0;
|
||||
if (log_store(ctx, level, err, vecode, dyn_msg, data_path, schema_path, line, apptag ? strdup(apptag) : NULL)) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* if we are only storing errors internally, never print the message (yet) */
|
||||
if (lolog) {
|
||||
if (log_clb) {
|
||||
log_clb(level, msg, data_path, schema_path, line);
|
||||
} else {
|
||||
fprintf(stderr, "libyang[%d]: ", level);
|
||||
fprintf(stderr, "%s", msg);
|
||||
log_stderr_path_line(data_path, schema_path, line);
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (free_strs) {
|
||||
free(data_path);
|
||||
free(schema_path);
|
||||
free(dyn_msg);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
void
|
||||
ly_log_dbg(uint32_t group, const char *format, ...)
|
||||
{
|
||||
char *dbg_format;
|
||||
const char *str_group;
|
||||
va_list ap;
|
||||
|
||||
if (!(ATOMIC_LOAD_RELAXED(ly_ldbg_groups) & group)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (group) {
|
||||
case LY_LDGDICT:
|
||||
str_group = "DICT";
|
||||
break;
|
||||
case LY_LDGXPATH:
|
||||
str_group = "XPATH";
|
||||
break;
|
||||
case LY_LDGDEPSETS:
|
||||
str_group = "DEPSETS";
|
||||
break;
|
||||
default:
|
||||
LOGINT(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (asprintf(&dbg_format, "%s: %s", str_group, format) == -1) {
|
||||
LOGMEM(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
va_start(ap, format);
|
||||
log_vprintf(NULL, LY_LLDBG, 0, 0, NULL, NULL, 0, NULL, dbg_format, ap);
|
||||
va_end(ap);
|
||||
|
||||
free(dbg_format);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
ly_log(const struct ly_ctx *ctx, LY_LOG_LEVEL level, LY_ERR err, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
log_vprintf(ctx, level, err, 0, NULL, NULL, 0, NULL, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Append a schema node name to a generated data path, only if it fits.
|
||||
*
|
||||
* @param[in,out] str Generated path to update.
|
||||
* @param[in] snode Schema node to append.
|
||||
* @param[in] parent Last printed data node.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
static LY_ERR
|
||||
ly_vlog_build_path_append(char **str, const struct lysc_node *snode, const struct lyd_node *parent)
|
||||
{
|
||||
const struct lys_module *mod, *prev_mod;
|
||||
uint32_t len, new_len;
|
||||
void *mem;
|
||||
|
||||
if (snode->nodetype & (LYS_CHOICE | LYS_CASE)) {
|
||||
/* schema-only node */
|
||||
return LY_SUCCESS;
|
||||
} else if (lysc_data_parent(snode) != lyd_node_schema(parent)) {
|
||||
/* not a direct descendant node */
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
/* get module to print, if any */
|
||||
mod = snode->module;
|
||||
prev_mod = lyd_node_module(parent);
|
||||
if (prev_mod == mod) {
|
||||
mod = NULL;
|
||||
}
|
||||
|
||||
/* realloc string */
|
||||
len = *str ? strlen(*str) : 0;
|
||||
new_len = len + 1 + (mod ? strlen(mod->name) + 1 : 0) + strlen(snode->name);
|
||||
mem = realloc(*str, new_len + 1);
|
||||
LY_CHECK_ERR_RET(!mem, LOGMEM(LYD_CTX(parent)), LY_EMEM);
|
||||
*str = mem;
|
||||
|
||||
/* print the last schema node */
|
||||
sprintf(*str + len, "/%s%s%s", mod ? mod->name : "", mod ? ":" : "", snode->name);
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
ly_vlog_build_data_path(const struct ly_ctx *ctx, char **path)
|
||||
{
|
||||
LY_ERR rc = LY_SUCCESS;
|
||||
const struct lyd_node *dnode = NULL;
|
||||
|
||||
*path = NULL;
|
||||
|
||||
if (log_location.dnodes.count) {
|
||||
dnode = log_location.dnodes.objs[log_location.dnodes.count - 1];
|
||||
if (!dnode) {
|
||||
/* special root node */
|
||||
assert(log_location.dnodes.count == 1);
|
||||
*path = strdup("/");
|
||||
LY_CHECK_ERR_GOTO(!*path, LOGMEM(ctx); rc = LY_EMEM, cleanup);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (dnode->parent || !lysc_data_parent(dnode->schema)) {
|
||||
/* data node with all of its parents */
|
||||
*path = lyd_path(log_location.dnodes.objs[log_location.dnodes.count - 1], LYD_PATH_STD, NULL, 0);
|
||||
LY_CHECK_ERR_GOTO(!*path, LOGMEM(ctx); rc = LY_EMEM, cleanup);
|
||||
} else {
|
||||
/* data parsers put all the parent nodes in the set, but they are not connected */
|
||||
*path = lyd_path_set(&log_location.dnodes, LYD_PATH_STD);
|
||||
LY_CHECK_ERR_GOTO(!*path, LOGMEM(ctx); rc = LY_EMEM, cleanup);
|
||||
}
|
||||
}
|
||||
|
||||
/* sometimes the last node is not created yet and we only have the schema node */
|
||||
if (log_location.scnodes.count) {
|
||||
rc = ly_vlog_build_path_append(path, log_location.scnodes.objs[log_location.scnodes.count - 1], dnode);
|
||||
LY_CHECK_GOTO(rc, cleanup);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (rc) {
|
||||
free(*path);
|
||||
*path = NULL;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Build log path/input line from the stored log location information.
|
||||
*
|
||||
* @param[in] ctx Context to use.
|
||||
* @param[out] data_path Generated data path.
|
||||
* @param[out] schema_path Generated data path.
|
||||
* @param[out] line Input line.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
static LY_ERR
|
||||
ly_vlog_build_path_line(const struct ly_ctx *ctx, char **data_path, char **schema_path, uint64_t *line)
|
||||
{
|
||||
*data_path = NULL;
|
||||
*schema_path = NULL;
|
||||
*line = 0;
|
||||
|
||||
if (log_location.spaths.count && ((const char *)(log_location.spaths.objs[log_location.spaths.count - 1]))[0]) {
|
||||
/* simply get what is in the provided path string */
|
||||
*schema_path = strdup(log_location.spaths.objs[log_location.spaths.count - 1]);
|
||||
LY_CHECK_ERR_RET(!*schema_path, LOGMEM(ctx), LY_EMEM);
|
||||
} else {
|
||||
/* data/schema node */
|
||||
if (log_location.dnodes.count) {
|
||||
LY_CHECK_RET(ly_vlog_build_data_path(ctx, data_path));
|
||||
} else if (log_location.scnodes.count) {
|
||||
*schema_path = lysc_path(log_location.scnodes.objs[log_location.scnodes.count - 1], LYSC_PATH_LOG, NULL, 0);
|
||||
LY_CHECK_ERR_RET(!*schema_path, LOGMEM(ctx), LY_EMEM);
|
||||
}
|
||||
}
|
||||
|
||||
/* line */
|
||||
if (log_location.inputs.count) {
|
||||
*line = ((struct ly_in *)log_location.inputs.objs[log_location.inputs.count - 1])->line;
|
||||
}
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
ly_vlog(const struct ly_ctx *ctx, const char *apptag, LY_VECODE code, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *data_path = NULL, *schema_path = NULL;
|
||||
uint64_t line = 0;
|
||||
|
||||
if (ctx) {
|
||||
ly_vlog_build_path_line(ctx, &data_path, &schema_path, &line);
|
||||
}
|
||||
|
||||
va_start(ap, format);
|
||||
log_vprintf(ctx, LY_LLERR, LY_EVALID, code, data_path, schema_path, line, apptag, format, ap);
|
||||
/* path is spent and should not be freed! */
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Print a log message from an extension plugin callback.
|
||||
*
|
||||
* @param[in] ctx libyang context to store the error record. If not provided, the error is just printed.
|
||||
* @param[in] plugin_name Name of the plugin generating the message.
|
||||
* @param[in] level Log message level (error, warning, etc.)
|
||||
* @param[in] err Error type code.
|
||||
* @param[in] data_path Error data path, always spent.
|
||||
* @param[in] schema_path Error schema path, always spent.
|
||||
* @param[in] line Error input line, if any.
|
||||
* @param[in] format Format string to print.
|
||||
* @param[in] ap Var arg list for @p format.
|
||||
*/
|
||||
static void
|
||||
ly_ext_log(const struct ly_ctx *ctx, const char *plugin_name, LY_LOG_LEVEL level, LY_ERR err, char *data_path,
|
||||
char *schema_path, uint64_t line, const char *format, va_list ap)
|
||||
{
|
||||
char *plugin_msg;
|
||||
|
||||
if (ATOMIC_LOAD_RELAXED(ly_ll) < level) {
|
||||
return;
|
||||
}
|
||||
if (asprintf(&plugin_msg, "Ext plugin \"%s\": %s", plugin_name, format) == -1) {
|
||||
LOGMEM(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
log_vprintf(ctx, level, (level == LY_LLERR ? LY_EPLUGIN : 0) | err, LYVE_OTHER, data_path, schema_path, line, NULL,
|
||||
plugin_msg, ap);
|
||||
free(plugin_msg);
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF void
|
||||
lyplg_ext_parse_log(const struct lysp_ctx *pctx, const struct lysp_ext_instance *ext, LY_LOG_LEVEL level, LY_ERR err,
|
||||
const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *data_path, *schema_path;
|
||||
uint64_t line;
|
||||
|
||||
ly_vlog_build_path_line(PARSER_CTX(pctx), &data_path, &schema_path, &line);
|
||||
|
||||
va_start(ap, format);
|
||||
ly_ext_log(PARSER_CTX(pctx), ext->record->plugin.id, level, err, data_path, schema_path, line, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF void
|
||||
lyplg_ext_compile_log(const struct lysc_ctx *cctx, const struct lysc_ext_instance *ext, LY_LOG_LEVEL level, LY_ERR err,
|
||||
const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *schema_path = NULL;
|
||||
|
||||
if (cctx && !(schema_path = strdup(cctx->path))) {
|
||||
LOGMEM(cctx->ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
va_start(ap, format);
|
||||
ly_ext_log(ext->module->ctx, ext->def->plugin->id, level, err, NULL, schema_path, 0, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF void
|
||||
lyplg_ext_compile_log_path(const char *path, const struct lysc_ext_instance *ext, LY_LOG_LEVEL level, LY_ERR err,
|
||||
const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *schema_path = NULL;
|
||||
|
||||
if (path && !(schema_path = strdup(path))) {
|
||||
LOGMEM(ext->module->ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
va_start(ap, format);
|
||||
ly_ext_log(ext->module->ctx, ext->def->plugin->id, level, err, NULL, schema_path, 0, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Serves only for creating ap.
|
||||
*/
|
||||
static void
|
||||
_lyplg_ext_compile_log_err(const struct ly_err_item *eitem, const struct lysc_ext_instance *ext, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *data_path = NULL, *schema_path = NULL;
|
||||
|
||||
if (eitem->data_path) {
|
||||
data_path = strdup(eitem->data_path);
|
||||
}
|
||||
if (eitem->schema_path) {
|
||||
schema_path = strdup(eitem->schema_path);
|
||||
}
|
||||
|
||||
va_start(ap, ext);
|
||||
ly_ext_log(ext->module->ctx, ext->def->plugin->id, eitem->level, eitem->err, data_path, schema_path, eitem->line, "%s", ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF void
|
||||
lyplg_ext_compile_log_err(const struct ly_err_item *eitem, const struct lysc_ext_instance *ext)
|
||||
{
|
||||
_lyplg_ext_compile_log_err(eitem, ext, eitem->msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exact same functionality as ::ly_err_print() but has variable arguments so log_vprintf() can be called.
|
||||
*/
|
||||
static void
|
||||
_ly_err_print(const struct ly_ctx *ctx, const struct ly_err_item *eitem, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *data_path = NULL, *schema_path = NULL;
|
||||
|
||||
LY_CHECK_ARG_RET(ctx, eitem, );
|
||||
|
||||
if (eitem->data_path) {
|
||||
data_path = strdup(eitem->data_path);
|
||||
}
|
||||
if (eitem->schema_path) {
|
||||
schema_path = strdup(eitem->schema_path);
|
||||
}
|
||||
|
||||
va_start(ap, format);
|
||||
log_vprintf(ctx, eitem->level, eitem->err, eitem->vecode, data_path, schema_path, eitem->line, eitem->apptag, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF void
|
||||
ly_err_print(const struct ly_ctx *ctx, const struct ly_err_item *eitem)
|
||||
{
|
||||
/* String ::ly_err_item.msg cannot be used directly because it may contain the % character */
|
||||
_ly_err_print(ctx, eitem, "%s", eitem->msg);
|
||||
}
|
361
src/log.h
Normal file
361
src/log.h
Normal file
|
@ -0,0 +1,361 @@
|
|||
/**
|
||||
* @file log.h
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief Logger manipulation routines and error definitions.
|
||||
*
|
||||
* Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef LY_LOG_H_
|
||||
#define LY_LOG_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ly_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* dummy context structure */
|
||||
struct ly_ctx;
|
||||
|
||||
/**
|
||||
* @brief Type to indicate boolean value.
|
||||
*
|
||||
* Do not test for actual value. Instead, handle it as true/false value in condition.
|
||||
*/
|
||||
typedef uint8_t ly_bool;
|
||||
|
||||
/**
|
||||
* @page howtoLogger Information Logging
|
||||
*
|
||||
* The libyang logger is supposed to process all the messages (and some other accompanied information) generated by the performed
|
||||
* functions. According to the logger settings, the information can be printed, stored or further processed by a callback
|
||||
* functions.
|
||||
*
|
||||
* The logger is tightly connected with [errors handling](@ref howtoErrors), because when an error appears, the logger (according
|
||||
* to [logger options](@ref logopts)) generates error records available via libyang context.
|
||||
*
|
||||
* There are 4 verbosity levels defined as ::LY_LOG_LEVEL. The level can be changed by the ::ly_log_level() function.
|
||||
* By default, the verbosity level is set to #LY_LLERR value, so only the errors are processed.
|
||||
*
|
||||
* By default, all libyang messages are printed to `stderr`. However, the callers are able to set their own logging callback
|
||||
* function (::ly_log_clb). In that case, instead of printing messages, libyang passes error level, message and path (if any) to
|
||||
* the caller's callback function set via ::ly_set_log_clb(). In case of error level, the error information is still
|
||||
* automatically stored and available via the [error handling functions](@ref howtoErrors).
|
||||
*
|
||||
* With [logging options](@ref logopts) set via ::ly_log_options(), the caller can modify what is done with all the messages.
|
||||
* Default flags are ::LY_LOLOG and ::LY_LOSTORE_LAST so that messages are logged and the last one is stored. If you set the flag
|
||||
* ::LY_LOSTORE, all the messages will be stored. Be careful because unless you regularly clean them, the error list in context
|
||||
* will grow indefinitely.
|
||||
*
|
||||
* As a separate group, there are @ref dbggroup to select group of debugging messages to print. The options can be set via
|
||||
* ::ly_log_dbg_groups() function, but note that the options take effect only in case the libyang is compiled in
|
||||
* [Debug build mode](@ref build).
|
||||
*
|
||||
* \note API for this group of functions is described in the [logger module](@ref log).
|
||||
*
|
||||
* Functions List
|
||||
* --------------
|
||||
* - ::ly_log_level()
|
||||
* - ::ly_log_dbg_groups()
|
||||
* - ::ly_log_options()
|
||||
* - ::ly_set_log_clb()
|
||||
* - ::ly_get_log_clb()
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup log Logger
|
||||
* @{
|
||||
*
|
||||
* Publicly visible functions and values of the libyang logger. For more
|
||||
* information, see @ref howtoLogger.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef LY_LOG_LEVEL
|
||||
* @brief Verbosity levels of the libyang logger.
|
||||
*/
|
||||
typedef enum {
|
||||
LY_LLERR = 0, /**< Print only error messages. */
|
||||
LY_LLWRN = 1, /**< Print error and warning messages, default value. */
|
||||
LY_LLVRB = 2, /**< Besides errors and warnings, print some other verbose messages. */
|
||||
LY_LLDBG = 3 /**< Print all messages including some development debug messages (be careful,
|
||||
without subsequently calling ::ly_log_dbg_groups() no debug messages will be printed!). */
|
||||
} LY_LOG_LEVEL;
|
||||
|
||||
/**
|
||||
* @brief Set logger verbosity level.
|
||||
*
|
||||
* To get the current value, the function must be called twice resetting the level by the received value.
|
||||
*
|
||||
* @param[in] level Verbosity level.
|
||||
* @return Previous verbosity level.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_LOG_LEVEL ly_log_level(LY_LOG_LEVEL level);
|
||||
|
||||
/**
|
||||
* @ingroup log
|
||||
* @defgroup logopts Logging options
|
||||
*
|
||||
* Logging option bits of libyang.
|
||||
*
|
||||
* Can be set via ::ly_log_options().
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
#define LY_LOLOG 0x01 /**< Log messages normally, using callback if set. If not set, messages will
|
||||
not be printed by libyang. */
|
||||
#define LY_LOSTORE 0x02 /**< Store any generated errors or warnings, never verbose or debug messages.
|
||||
Note that if #LY_LOLOG is not set then verbose and debug messages are always lost. */
|
||||
#define LY_LOSTORE_LAST 0x06 /**< Store any generated errors or warnings but only the last message, always overwrite
|
||||
the previous one. */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Set logger options. Default is #LY_LOLOG | #LY_LOSTORE_LAST.
|
||||
*
|
||||
* To get the current value, the function must be called twice resetting the level by the received value.
|
||||
*
|
||||
* @param[in] opts Bitfield of @ref logopts.
|
||||
* @return Previous logger options.
|
||||
*/
|
||||
LIBYANG_API_DECL uint32_t ly_log_options(uint32_t opts);
|
||||
|
||||
/**
|
||||
* @brief Set temporary thread-safe logger options overwriting those set by ::ly_log_options().
|
||||
*
|
||||
* @param[in] opts Pointer to the temporary @ref logopts. If NULL, restores the effect of global logger options.
|
||||
* @return Previous temporary options.
|
||||
*/
|
||||
LIBYANG_API_DECL uint32_t *ly_temp_log_options(uint32_t *opts);
|
||||
|
||||
/**
|
||||
* @ingroup log
|
||||
* @defgroup dbggroup Debug messages groups
|
||||
*
|
||||
* Categories of the debug messages.
|
||||
*
|
||||
* Allows to show only the selected group(s) of the debug messages.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define LY_LDGDICT 0x01 /**< Dictionary additions and deletions. */
|
||||
#define LY_LDGXPATH 0x02 /**< XPath parsing end evaluation. */
|
||||
#define LY_LDGDEPSETS 0x04 /**< Dependency module sets for schema compilation. */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enable specific debugging messages (independent of log level).
|
||||
*
|
||||
* To get the current value, the function must be called twice resetting the level by the received value.
|
||||
* Note: does not have any effect on non-debug (Release) builds
|
||||
*
|
||||
* @param[in] dbg_groups Bitfield of enabled debug message groups (see @ref dbggroup).
|
||||
* @return Previous options bitfield.
|
||||
*/
|
||||
LIBYANG_API_DECL uint32_t ly_log_dbg_groups(uint32_t dbg_groups);
|
||||
|
||||
/**
|
||||
* @brief Logger callback.
|
||||
*
|
||||
* @param[in] level Log level of the message.
|
||||
* @param[in] msg Message.
|
||||
* @param[in] data_path Optional data path of the related node.
|
||||
* @param[in] schema_path Optional schema path of the related node.
|
||||
* @param[in] line Optional related input line.
|
||||
*/
|
||||
typedef void (*ly_log_clb)(LY_LOG_LEVEL level, const char *msg, const char *data_path, const char *schema_path,
|
||||
uint64_t line);
|
||||
|
||||
/**
|
||||
* @brief Set logger callback.
|
||||
*
|
||||
* @param[in] clb Logging callback.
|
||||
*/
|
||||
LIBYANG_API_DECL void ly_set_log_clb(ly_log_clb clb);
|
||||
|
||||
/**
|
||||
* @brief Get logger callback.
|
||||
*
|
||||
* @return Logger callback (can be NULL).
|
||||
*/
|
||||
LIBYANG_API_DECL ly_log_clb ly_get_log_clb(void);
|
||||
|
||||
/** @} log */
|
||||
|
||||
/**
|
||||
* @page howtoErrors Errors Handling
|
||||
*
|
||||
* The most of the API functions directly returns error code in the form of ::LY_ERR value. In addition, if the ::LY_EVALID error
|
||||
* arises, additional [validation error code](@ref ::LY_VECODE) is provided to categorize validation failures into several groups.
|
||||
*
|
||||
* All the errors arisen in connection with manipulation with the [context](@ref howtoContext), [YANG modules](@ref howtoSchema)
|
||||
* or [YANG data](@ref howtoData), are recorded into the context and can be examined for the more detailed information. These
|
||||
* records are stored as ::ly_err_item structures and they are not only context-specific, but also thread-specific.
|
||||
*
|
||||
* Storing error information is tightly connected with
|
||||
* [logging](@ref howtoLogger). So the @ref logopts control if and which errors are stored in the context. By default, only the
|
||||
* last error is recorded, so a new error replaces the previous one. This can be changed with ::LY_LOSTORE option set via
|
||||
* ::ly_log_options(). Then, the errors are stored as a list preserving the previous error records. The stored records can be
|
||||
* accessed using ::ly_err_last() or ::ly_err_first() functions. The ::ly_err_clean() is used to remove error records from the
|
||||
* context.
|
||||
*
|
||||
* To print a specific error information via libyang logger, there is ::ly_err_print().
|
||||
*
|
||||
* \note API for this group of functions is described in the [error information module](@ref errors).
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup errors Error information
|
||||
*
|
||||
* Structures and functions to allow error information processing.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef LY_ERR
|
||||
* @brief libyang's error codes returned by the libyang functions.
|
||||
*/
|
||||
typedef enum {
|
||||
LY_SUCCESS = 0, /**< no error, not set by functions, included just to complete #LY_ERR enumeration */
|
||||
LY_EMEM, /**< Memory allocation failure */
|
||||
LY_ESYS, /**< System call failure */
|
||||
LY_EINVAL, /**< Invalid value */
|
||||
LY_EEXIST, /**< Item already exists */
|
||||
LY_ENOTFOUND, /**< Item does not exists */
|
||||
LY_EINT, /**< Internal error */
|
||||
LY_EVALID, /**< Validation failure */
|
||||
LY_EDENIED, /**< Operation is not allowed */
|
||||
LY_EINCOMPLETE, /**< The operation did not fail, but for some reason it was not possible to finish it completely.
|
||||
According to the specific use case, the caller is usually supposed to perform the operation again. */
|
||||
LY_ERECOMPILE, /**< The operation did not fail, but requires context recompilation before it can be completed.
|
||||
According to the specific use case, the caller should react appropriately. */
|
||||
LY_ENOT, /**< Negative result */
|
||||
LY_EOTHER, /**< Unknown error */
|
||||
|
||||
LY_EPLUGIN = 128/**< Error reported by a plugin - the highest bit in the first byte is set.
|
||||
This value is used ORed with one of the other LY_ERR value and can be simply masked. */
|
||||
} LY_ERR;
|
||||
|
||||
/**
|
||||
* @ingroup log
|
||||
* @typedef LY_VECODE
|
||||
* @brief libyang's codes of validation error. Whenever ly_errno is set to LY_EVALID, the ly_vecode is also set
|
||||
* to the appropriate LY_VECODE value.
|
||||
*/
|
||||
typedef enum {
|
||||
LYVE_SUCCESS = 0, /**< no error */
|
||||
LYVE_SYNTAX, /**< generic syntax error */
|
||||
LYVE_SYNTAX_YANG, /**< YANG-related syntax error */
|
||||
LYVE_SYNTAX_YIN, /**< YIN-related syntax error */
|
||||
LYVE_REFERENCE, /**< invalid referencing or using an item */
|
||||
LYVE_XPATH, /**< invalid XPath expression */
|
||||
LYVE_SEMANTICS, /**< generic semantic error */
|
||||
LYVE_SYNTAX_XML, /**< XML-related syntax error */
|
||||
LYVE_SYNTAX_JSON, /**< JSON-related syntax error */
|
||||
LYVE_DATA, /**< YANG data does not reflect some of the module restrictions */
|
||||
|
||||
LYVE_OTHER /**< Unknown error */
|
||||
} LY_VECODE;
|
||||
|
||||
/**
|
||||
* @brief Libyang full error structure.
|
||||
*/
|
||||
struct ly_err_item {
|
||||
LY_LOG_LEVEL level; /**< error (message) log level */
|
||||
LY_ERR err; /**< error code number */
|
||||
LY_VECODE vecode; /**< validation error code, if any */
|
||||
char *msg; /**< error message */
|
||||
char *data_path; /**< error data path related to the error, if any */
|
||||
char *schema_path; /**< error schema path related to the error, if any */
|
||||
uint64_t line; /**< input line the error occured on, if available */
|
||||
char *apptag; /**< error-app-tag, if any */
|
||||
struct ly_err_item *next; /**< next error item */
|
||||
struct ly_err_item *prev; /**< previous error item, points to the last item for the ifrst item */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Get human-readable error message for an error code.
|
||||
*
|
||||
* @param[in] err Error code.
|
||||
* @return String error message.
|
||||
*/
|
||||
LIBYANG_API_DECL const char *ly_strerr(LY_ERR err);
|
||||
|
||||
/**
|
||||
* @brief Get human-readable error message for a validation error code.
|
||||
*
|
||||
* @param[in] vecode Validation error code.
|
||||
* @return String error message.
|
||||
*/
|
||||
LIBYANG_API_DECL const char *ly_strvecode(LY_VECODE vecode);
|
||||
|
||||
/**
|
||||
* @brief Get the last (thread-specific) full logged error message.
|
||||
*
|
||||
* This function is useful for getting errors from functions that do not have any context accessible and includes
|
||||
* any additional information such as the path or line where the error occurred.
|
||||
*
|
||||
* @return Last generated error message.
|
||||
*/
|
||||
LIBYANG_API_DECL const char *ly_last_logmsg(void);
|
||||
|
||||
/**
|
||||
* @brief Get the first (thread, context-specific) generated error structure.
|
||||
*
|
||||
* @param[in] ctx Relative context.
|
||||
* @return First error structure, NULL if none available.
|
||||
*/
|
||||
LIBYANG_API_DECL const struct ly_err_item *ly_err_first(const struct ly_ctx *ctx);
|
||||
|
||||
/**
|
||||
* @brief Get the latest (thread, context-specific) generated error structure.
|
||||
*
|
||||
* @param[in] ctx Relative context.
|
||||
* @return Last error structure, NULL if none available.
|
||||
*/
|
||||
LIBYANG_API_DECL const struct ly_err_item *ly_err_last(const struct ly_ctx *ctx);
|
||||
|
||||
/**
|
||||
* @brief Print the error structure as if just generated.
|
||||
*
|
||||
* @param[in] ctx Optional context to store the message in.
|
||||
* @param[in] eitem Error item structure to print.
|
||||
*/
|
||||
LIBYANG_API_DECL void ly_err_print(const struct ly_ctx *ctx, const struct ly_err_item *eitem);
|
||||
|
||||
/**
|
||||
* @brief Free error structures from a context.
|
||||
*
|
||||
* If @p eitem is not set, free all the error structures.
|
||||
*
|
||||
* @param[in] ctx Relative context.
|
||||
* @param[in] eitem Oldest error structure to remove, optional.
|
||||
*/
|
||||
LIBYANG_API_DECL void ly_err_clean(struct ly_ctx *ctx, struct ly_err_item *eitem);
|
||||
|
||||
/** @} errors */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LY_LOG_H_ */
|
941
src/ly_common.c
Normal file
941
src/ly_common.c
Normal file
|
@ -0,0 +1,941 @@
|
|||
/**
|
||||
* @file ly_common.c
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief common internal definitions for libyang
|
||||
*
|
||||
* Copyright (c) 2018 - 2024 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "ly_common.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef _WIN32
|
||||
# ifdef HAVE_MMAP
|
||||
# include <sys/mman.h>
|
||||
# endif
|
||||
#else
|
||||
# include <io.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "compat.h"
|
||||
#include "tree_schema_internal.h"
|
||||
#include "version.h"
|
||||
#include "xml.h"
|
||||
|
||||
LIBYANG_API_DEF struct ly_version ly_version_so = {
|
||||
.major = LY_VERSION_MAJOR,
|
||||
.minor = LY_VERSION_MINOR,
|
||||
.micro = LY_VERSION_MICRO,
|
||||
.str = LY_VERSION
|
||||
};
|
||||
|
||||
LIBYANG_API_DEF struct ly_version ly_version_proj = {
|
||||
.major = LY_PROJ_VERSION_MAJOR,
|
||||
.minor = LY_PROJ_VERSION_MINOR,
|
||||
.micro = LY_PROJ_VERSION_MICRO,
|
||||
.str = LY_PROJ_VERSION
|
||||
};
|
||||
|
||||
void *
|
||||
ly_realloc(void *ptr, size_t size)
|
||||
{
|
||||
void *new_mem;
|
||||
|
||||
new_mem = realloc(ptr, size);
|
||||
if (!new_mem) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
return new_mem;
|
||||
}
|
||||
|
||||
char *
|
||||
ly_strnchr(const char *s, int c, size_t len)
|
||||
{
|
||||
for ( ; len && (*s != (char)c); ++s, --len) {}
|
||||
return len ? (char *)s : NULL;
|
||||
}
|
||||
|
||||
int
|
||||
ly_strncmp(const char *refstr, const char *str, size_t str_len)
|
||||
{
|
||||
int rc = strncmp(refstr, str, str_len);
|
||||
|
||||
if (!rc && (refstr[str_len] == '\0')) {
|
||||
return 0;
|
||||
} else {
|
||||
return rc ? rc : 1;
|
||||
}
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
ly_strntou8(const char *nptr, size_t len, uint8_t *ret)
|
||||
{
|
||||
uint8_t num = 0, dig;
|
||||
uint16_t dec_pow;
|
||||
|
||||
if (len > 3) {
|
||||
/* overflow for sure */
|
||||
return LY_EDENIED;
|
||||
}
|
||||
|
||||
dec_pow = 1;
|
||||
for ( ; len && isdigit(nptr[len - 1]); --len) {
|
||||
dig = nptr[len - 1] - 48;
|
||||
|
||||
if (LY_OVERFLOW_MUL(UINT8_MAX, dig, dec_pow)) {
|
||||
return LY_EDENIED;
|
||||
}
|
||||
dig *= dec_pow;
|
||||
|
||||
if (LY_OVERFLOW_ADD(UINT8_MAX, num, dig)) {
|
||||
return LY_EDENIED;
|
||||
}
|
||||
num += dig;
|
||||
|
||||
dec_pow *= 10;
|
||||
}
|
||||
|
||||
if (len) {
|
||||
return LY_EVALID;
|
||||
}
|
||||
*ret = num;
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
ly_value_prefix_next(const char *str_begin, const char *str_end, uint32_t *len, ly_bool *is_prefix, const char **str_next)
|
||||
{
|
||||
const char *stop, *prefix;
|
||||
size_t bytes_read;
|
||||
uint32_t c;
|
||||
ly_bool prefix_found;
|
||||
LY_ERR ret = LY_SUCCESS;
|
||||
|
||||
assert(len && is_prefix && str_next);
|
||||
|
||||
#define IS_AT_END(PTR, STR_END) (STR_END ? PTR == STR_END : !(*PTR))
|
||||
|
||||
*str_next = NULL;
|
||||
*is_prefix = 0;
|
||||
*len = 0;
|
||||
|
||||
if (!str_begin || !(*str_begin) || (str_begin == str_end)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
stop = str_begin;
|
||||
prefix = NULL;
|
||||
prefix_found = 0;
|
||||
|
||||
do {
|
||||
/* look for the beginning of the YANG value */
|
||||
do {
|
||||
LY_CHECK_RET(ly_getutf8(&stop, &c, &bytes_read));
|
||||
} while (!is_xmlqnamestartchar(c) && !IS_AT_END(stop, str_end));
|
||||
|
||||
if (IS_AT_END(stop, str_end)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* maybe the prefix was found */
|
||||
prefix = stop - bytes_read;
|
||||
|
||||
/* look for the the end of the prefix */
|
||||
do {
|
||||
LY_CHECK_RET(ly_getutf8(&stop, &c, &bytes_read));
|
||||
} while (is_xmlqnamechar(c) && !IS_AT_END(stop, str_end));
|
||||
|
||||
prefix_found = c == ':' ? 1 : 0;
|
||||
|
||||
/* if it wasn't the prefix, keep looking */
|
||||
} while (!IS_AT_END(stop, str_end) && !prefix_found);
|
||||
|
||||
if ((str_begin == prefix) && prefix_found) {
|
||||
/* prefix found at the beginning of the input string */
|
||||
*is_prefix = 1;
|
||||
*str_next = IS_AT_END(stop, str_end) ? NULL : stop;
|
||||
*len = (stop - bytes_read) - str_begin;
|
||||
} else if ((str_begin != prefix) && (prefix_found)) {
|
||||
/* there is a some string before prefix */
|
||||
*str_next = prefix;
|
||||
*len = prefix - str_begin;
|
||||
} else {
|
||||
/* no prefix found */
|
||||
*len = stop - str_begin;
|
||||
}
|
||||
|
||||
#undef IS_AT_END
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
ly_getutf8(const char **input, uint32_t *utf8_char, size_t *bytes_read)
|
||||
{
|
||||
uint32_t c, aux;
|
||||
size_t len;
|
||||
|
||||
c = (*input)[0];
|
||||
|
||||
if (!(c & 0x80)) {
|
||||
/* one byte character */
|
||||
len = 1;
|
||||
|
||||
if ((c < 0x20) && (c != 0x9) && (c != 0xa) && (c != 0xd)) {
|
||||
goto error;
|
||||
}
|
||||
} else if ((c & 0xe0) == 0xc0) {
|
||||
/* two bytes character */
|
||||
len = 2;
|
||||
|
||||
aux = (*input)[1];
|
||||
if ((aux & 0xc0) != 0x80) {
|
||||
goto error;
|
||||
}
|
||||
c = ((c & 0x1f) << 6) | (aux & 0x3f);
|
||||
|
||||
if (c < 0x80) {
|
||||
goto error;
|
||||
}
|
||||
} else if ((c & 0xf0) == 0xe0) {
|
||||
/* three bytes character */
|
||||
len = 3;
|
||||
|
||||
c &= 0x0f;
|
||||
for (uint64_t i = 1; i <= 2; i++) {
|
||||
aux = (*input)[i];
|
||||
if ((aux & 0xc0) != 0x80) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
c = (c << 6) | (aux & 0x3f);
|
||||
}
|
||||
|
||||
if ((c < 0x800) || ((c > 0xd7ff) && (c < 0xe000)) || (c > 0xfffd)) {
|
||||
goto error;
|
||||
}
|
||||
} else if ((c & 0xf8) == 0xf0) {
|
||||
/* four bytes character */
|
||||
len = 4;
|
||||
|
||||
c &= 0x07;
|
||||
for (uint64_t i = 1; i <= 3; i++) {
|
||||
aux = (*input)[i];
|
||||
if ((aux & 0xc0) != 0x80) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
c = (c << 6) | (aux & 0x3f);
|
||||
}
|
||||
|
||||
if ((c < 0x1000) || (c > 0x10ffff)) {
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
|
||||
(*utf8_char) = c;
|
||||
(*input) += len;
|
||||
if (bytes_read) {
|
||||
(*bytes_read) = len;
|
||||
}
|
||||
return LY_SUCCESS;
|
||||
|
||||
error:
|
||||
if (bytes_read) {
|
||||
(*bytes_read) = 0;
|
||||
}
|
||||
return LY_EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether an UTF-8 string is equal to a hex string after a bitwise and.
|
||||
*
|
||||
* (input & 0x[arg1][arg3][arg5]...) == 0x[arg2][arg4][arg6]...
|
||||
*
|
||||
* @param[in] input UTF-8 string.
|
||||
* @param[in] bytes Number of bytes to compare.
|
||||
* @param[in] ... 2x @p bytes number of bytes to perform bitwise and and equality operations.
|
||||
* @return Result of the operation.
|
||||
*/
|
||||
static int
|
||||
ly_utf8_and_equal(const char *input, int bytes, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int i, and, byte;
|
||||
|
||||
va_start(ap, bytes);
|
||||
for (i = 0; i < bytes; ++i) {
|
||||
and = va_arg(ap, int);
|
||||
byte = va_arg(ap, int);
|
||||
|
||||
/* compare each byte */
|
||||
if (((uint8_t)input[i] & and) != (uint8_t)byte) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether an UTF-8 string is smaller than a hex string.
|
||||
*
|
||||
* input < 0x[arg1][arg2]...
|
||||
*
|
||||
* @param[in] input UTF-8 string.
|
||||
* @param[in] bytes Number of bytes to compare.
|
||||
* @param[in] ... @p bytes number of bytes to compare with.
|
||||
* @return Result of the operation.
|
||||
*/
|
||||
static int
|
||||
ly_utf8_less(const char *input, int bytes, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int i, byte;
|
||||
|
||||
va_start(ap, bytes);
|
||||
for (i = 0; i < bytes; ++i) {
|
||||
byte = va_arg(ap, int);
|
||||
|
||||
/* compare until bytes differ */
|
||||
if ((uint8_t)input[i] > (uint8_t)byte) {
|
||||
return 0;
|
||||
} else if ((uint8_t)input[i] < (uint8_t)byte) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
/* equals */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether an UTF-8 string is greater than a hex string.
|
||||
*
|
||||
* input > 0x[arg1][arg2]...
|
||||
*
|
||||
* @param[in] input UTF-8 string.
|
||||
* @param[in] bytes Number of bytes to compare.
|
||||
* @param[in] ... @p bytes number of bytes to compare with.
|
||||
* @return Result of the operation.
|
||||
*/
|
||||
static int
|
||||
ly_utf8_greater(const char *input, int bytes, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int i, byte;
|
||||
|
||||
va_start(ap, bytes);
|
||||
for (i = 0; i < bytes; ++i) {
|
||||
byte = va_arg(ap, int);
|
||||
|
||||
/* compare until bytes differ */
|
||||
if ((uint8_t)input[i] > (uint8_t)byte) {
|
||||
return 1;
|
||||
} else if ((uint8_t)input[i] < (uint8_t)byte) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
/* equals */
|
||||
return 0;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
ly_checkutf8(const char *input, size_t in_len, size_t *utf8_len)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (!(input[0] & 0x80)) {
|
||||
/* one byte character */
|
||||
len = 1;
|
||||
|
||||
if (ly_utf8_less(input, 1, 0x20) && (input[0] != 0x9) && (input[0] != 0xa) && (input[0] != 0xd)) {
|
||||
/* invalid control characters */
|
||||
return LY_EINVAL;
|
||||
}
|
||||
} else if (((input[0] & 0xe0) == 0xc0) && (in_len > 1)) {
|
||||
/* two bytes character */
|
||||
len = 2;
|
||||
|
||||
/* (input < 0xC280) || (input > 0xDFBF) || ((input & 0xE0C0) != 0xC080) */
|
||||
if (ly_utf8_less(input, 2, 0xC2, 0x80) || ly_utf8_greater(input, 2, 0xDF, 0xBF) ||
|
||||
!ly_utf8_and_equal(input, 2, 0xE0, 0xC0, 0xC0, 0x80)) {
|
||||
return LY_EINVAL;
|
||||
}
|
||||
} else if (((input[0] & 0xf0) == 0xe0) && (in_len > 2)) {
|
||||
/* three bytes character */
|
||||
len = 3;
|
||||
|
||||
/* (input >= 0xEDA080) && (input <= 0xEDBFBF) */
|
||||
if (!ly_utf8_less(input, 3, 0xED, 0xA0, 0x80) && !ly_utf8_greater(input, 3, 0xED, 0xBF, 0xBF)) {
|
||||
/* reject UTF-16 surrogates */
|
||||
return LY_EINVAL;
|
||||
}
|
||||
|
||||
/* (input < 0xE0A080) || (input > 0xEFBFBF) || ((input & 0xF0C0C0) != 0xE08080) */
|
||||
if (ly_utf8_less(input, 3, 0xE0, 0xA0, 0x80) || ly_utf8_greater(input, 3, 0xEF, 0xBF, 0xBF) ||
|
||||
!ly_utf8_and_equal(input, 3, 0xF0, 0xE0, 0xC0, 0x80, 0xC0, 0x80)) {
|
||||
return LY_EINVAL;
|
||||
}
|
||||
} else if (((input[0] & 0xf8) == 0xf0) && (in_len > 3)) {
|
||||
/* four bytes character */
|
||||
len = 4;
|
||||
|
||||
/* (input < 0xF0908080) || (input > 0xF48FBFBF) || ((input & 0xF8C0C0C0) != 0xF0808080) */
|
||||
if (ly_utf8_less(input, 4, 0xF0, 0x90, 0x80, 0x80) || ly_utf8_greater(input, 4, 0xF4, 0x8F, 0xBF, 0xBF) ||
|
||||
!ly_utf8_and_equal(input, 4, 0xF8, 0xF0, 0xC0, 0x80, 0xC0, 0x80, 0xC0, 0x80)) {
|
||||
return LY_EINVAL;
|
||||
}
|
||||
} else {
|
||||
return LY_EINVAL;
|
||||
}
|
||||
|
||||
*utf8_len = len;
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
ly_pututf8(char *dst, uint32_t value, size_t *bytes_written)
|
||||
{
|
||||
if (value < 0x80) {
|
||||
/* one byte character */
|
||||
if ((value < 0x20) &&
|
||||
(value != 0x09) &&
|
||||
(value != 0x0a) &&
|
||||
(value != 0x0d)) {
|
||||
/* valid UTF8 but not YANG string character */
|
||||
return LY_EINVAL;
|
||||
}
|
||||
|
||||
dst[0] = value;
|
||||
(*bytes_written) = 1;
|
||||
} else if (value < 0x800) {
|
||||
/* two bytes character */
|
||||
dst[0] = 0xc0 | (value >> 6);
|
||||
dst[1] = 0x80 | (value & 0x3f);
|
||||
(*bytes_written) = 2;
|
||||
} else if (value < 0xfffe) {
|
||||
/* three bytes character */
|
||||
if (((value & 0xf800) == 0xd800) ||
|
||||
((value >= 0xfdd0) && (value <= 0xfdef))) {
|
||||
/* exclude surrogate blocks %xD800-DFFF */
|
||||
/* exclude noncharacters %xFDD0-FDEF */
|
||||
return LY_EINVAL;
|
||||
}
|
||||
|
||||
dst[0] = 0xe0 | (value >> 12);
|
||||
dst[1] = 0x80 | ((value >> 6) & 0x3f);
|
||||
dst[2] = 0x80 | (value & 0x3f);
|
||||
|
||||
(*bytes_written) = 3;
|
||||
} else if (value < 0x10fffe) {
|
||||
if ((value & 0xffe) == 0xffe) {
|
||||
/* exclude noncharacters %xFFFE-FFFF, %x1FFFE-1FFFF, %x2FFFE-2FFFF, %x3FFFE-3FFFF, %x4FFFE-4FFFF,
|
||||
* %x5FFFE-5FFFF, %x6FFFE-6FFFF, %x7FFFE-7FFFF, %x8FFFE-8FFFF, %x9FFFE-9FFFF, %xAFFFE-AFFFF,
|
||||
* %xBFFFE-BFFFF, %xCFFFE-CFFFF, %xDFFFE-DFFFF, %xEFFFE-EFFFF, %xFFFFE-FFFFF, %x10FFFE-10FFFF */
|
||||
return LY_EINVAL;
|
||||
}
|
||||
/* four bytes character */
|
||||
dst[0] = 0xf0 | (value >> 18);
|
||||
dst[1] = 0x80 | ((value >> 12) & 0x3f);
|
||||
dst[2] = 0x80 | ((value >> 6) & 0x3f);
|
||||
dst[3] = 0x80 | (value & 0x3f);
|
||||
|
||||
(*bytes_written) = 4;
|
||||
} else {
|
||||
return LY_EINVAL;
|
||||
}
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Static table of the UTF8 characters lengths according to their first byte.
|
||||
*/
|
||||
static const unsigned char utf8_char_length_table[] = {
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1
|
||||
};
|
||||
|
||||
size_t
|
||||
ly_utf8len(const char *str, size_t bytes)
|
||||
{
|
||||
size_t len = 0;
|
||||
const char *ptr = str;
|
||||
|
||||
while (((size_t)(ptr - str) < bytes) && *ptr) {
|
||||
++len;
|
||||
ptr += utf8_char_length_table[((unsigned char)(*ptr))];
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
LY_VCODE_INSTREXP_len(const char *str)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
if (!str) {
|
||||
return len;
|
||||
} else if (!str[0]) {
|
||||
return 1;
|
||||
}
|
||||
for (len = 1; len < LY_VCODE_INSTREXP_MAXLEN && str[len]; ++len) {}
|
||||
return len;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
LY_ERR
|
||||
ly_mmap(struct ly_ctx *ctx, int fd, size_t *length, void **addr)
|
||||
{
|
||||
struct stat sb;
|
||||
long pagesize;
|
||||
size_t m;
|
||||
|
||||
assert(length);
|
||||
assert(addr);
|
||||
assert(fd >= 0);
|
||||
|
||||
if (fstat(fd, &sb) == -1) {
|
||||
LOGERR(ctx, LY_ESYS, "Failed to stat the file descriptor (%s) for the mmap().", strerror(errno));
|
||||
return LY_ESYS;
|
||||
}
|
||||
if (!S_ISREG(sb.st_mode)) {
|
||||
LOGERR(ctx, LY_EINVAL, "File to mmap() is not a regular file.");
|
||||
return LY_ESYS;
|
||||
}
|
||||
if (!sb.st_size) {
|
||||
*addr = NULL;
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
pagesize = sysconf(_SC_PAGESIZE);
|
||||
|
||||
m = sb.st_size % pagesize;
|
||||
if (m && (pagesize - m >= 1)) {
|
||||
/* there will be enough space (at least 1 byte) after the file content mapping to provide zeroed NULL-termination byte */
|
||||
*length = sb.st_size + 1;
|
||||
*addr = mmap(NULL, *length, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
} else {
|
||||
/* there will not be enough bytes after the file content mapping for the additional bytes and some of them
|
||||
* would overflow into another page that would not be zerroed and any access into it would generate SIGBUS.
|
||||
* Therefore we have to do the following hack with double mapping. First, the required number of bytes
|
||||
* (including the additinal bytes) is required as anonymous and thus they will be really provided (actually more
|
||||
* because of using whole pages) and also initialized by zeros. Then, the file is mapped to the same address
|
||||
* where the anonymous mapping starts. */
|
||||
*length = sb.st_size + pagesize;
|
||||
*addr = mmap(NULL, *length, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
*addr = mmap(*addr, sb.st_size, PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, 0);
|
||||
}
|
||||
if (*addr == MAP_FAILED) {
|
||||
LOGERR(ctx, LY_ESYS, "mmap() failed (%s).", strerror(errno));
|
||||
return LY_ESYS;
|
||||
}
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
ly_munmap(void *addr, size_t length)
|
||||
{
|
||||
if (munmap(addr, length)) {
|
||||
return LY_ESYS;
|
||||
}
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
LY_ERR
|
||||
ly_mmap(struct ly_ctx *ctx, int fd, size_t *length, void **addr)
|
||||
{
|
||||
struct stat sb;
|
||||
size_t m;
|
||||
|
||||
assert(length);
|
||||
assert(addr);
|
||||
assert(fd >= 0);
|
||||
|
||||
#if _WIN32
|
||||
if (_setmode(fd, _O_BINARY) == -1) {
|
||||
LOGERR(ctx, LY_ESYS, "Failed to switch the file descriptor to binary mode.", strerror(errno));
|
||||
return LY_ESYS;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fstat(fd, &sb) == -1) {
|
||||
LOGERR(ctx, LY_ESYS, "Failed to stat the file descriptor (%s) for the mmap().", strerror(errno));
|
||||
return LY_ESYS;
|
||||
}
|
||||
if (!S_ISREG(sb.st_mode)) {
|
||||
LOGERR(ctx, LY_EINVAL, "File to mmap() is not a regular file.");
|
||||
return LY_ESYS;
|
||||
}
|
||||
if (!sb.st_size) {
|
||||
*addr = NULL;
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
/* On Windows, the mman-win32 mmap() emulation uses CreateFileMapping and MapViewOfFile, and these functions
|
||||
* do not allow mapping more than "length of file" bytes for PROT_READ. Remapping existing mappings is not allowed, either.
|
||||
* At that point the path of least resistance is just reading the file in as-is. */
|
||||
m = sb.st_size + 1;
|
||||
char *buf = calloc(m, 1);
|
||||
|
||||
if (!buf) {
|
||||
LOGERR(ctx, LY_ESYS, "ly_mmap: malloc() failed (%s).", strerror(errno));
|
||||
}
|
||||
*addr = buf;
|
||||
*length = m;
|
||||
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
ssize_t to_read = m - 1;
|
||||
|
||||
while (to_read > 0) {
|
||||
ssize_t n = read(fd, buf, to_read);
|
||||
|
||||
if (n == 0) {
|
||||
return LY_SUCCESS;
|
||||
} else if (n < 0) {
|
||||
if (errno == EINTR) {
|
||||
continue; // can I get this on Windows?
|
||||
}
|
||||
LOGERR(ctx, LY_ESYS, "ly_mmap: read() failed (%s).", strerror(errno));
|
||||
}
|
||||
to_read -= n;
|
||||
buf += n;
|
||||
}
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
ly_munmap(void *addr, size_t length)
|
||||
{
|
||||
(void)length;
|
||||
free(addr);
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
LY_ERR
|
||||
ly_strcat(char **dest, const char *format, ...)
|
||||
{
|
||||
va_list fp;
|
||||
char *addition = NULL;
|
||||
size_t len;
|
||||
|
||||
va_start(fp, format);
|
||||
len = vasprintf(&addition, format, fp);
|
||||
len += (*dest ? strlen(*dest) : 0) + 1;
|
||||
|
||||
if (*dest) {
|
||||
*dest = ly_realloc(*dest, len);
|
||||
if (!*dest) {
|
||||
va_end(fp);
|
||||
return LY_EMEM;
|
||||
}
|
||||
*dest = strcat(*dest, addition);
|
||||
free(addition);
|
||||
} else {
|
||||
*dest = addition;
|
||||
}
|
||||
|
||||
va_end(fp);
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
ly_parse_int(const char *val_str, size_t val_len, int64_t min, int64_t max, int base, int64_t *ret)
|
||||
{
|
||||
LY_ERR rc = LY_SUCCESS;
|
||||
char *ptr, *str;
|
||||
int64_t i;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, val_str, val_str[0], val_len, LY_EINVAL);
|
||||
|
||||
/* duplicate the value */
|
||||
str = strndup(val_str, val_len);
|
||||
LY_CHECK_RET(!str, LY_EMEM);
|
||||
|
||||
/* parse the value to avoid accessing following bytes */
|
||||
errno = 0;
|
||||
i = strtoll(str, &ptr, base);
|
||||
if (errno || (ptr == str)) {
|
||||
/* invalid string */
|
||||
rc = LY_EVALID;
|
||||
} else if ((i < min) || (i > max)) {
|
||||
/* invalid number */
|
||||
rc = LY_EDENIED;
|
||||
} else if (*ptr) {
|
||||
while (isspace(*ptr)) {
|
||||
++ptr;
|
||||
}
|
||||
if (*ptr) {
|
||||
/* invalid characters after some number */
|
||||
rc = LY_EVALID;
|
||||
}
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
free(str);
|
||||
if (!rc) {
|
||||
*ret = i;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
ly_parse_uint(const char *val_str, size_t val_len, uint64_t max, int base, uint64_t *ret)
|
||||
{
|
||||
LY_ERR rc = LY_SUCCESS;
|
||||
char *ptr, *str;
|
||||
uint64_t u;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, val_str, val_str[0], val_len, LY_EINVAL);
|
||||
|
||||
/* duplicate the value to avoid accessing following bytes */
|
||||
str = strndup(val_str, val_len);
|
||||
LY_CHECK_RET(!str, LY_EMEM);
|
||||
|
||||
/* parse the value */
|
||||
errno = 0;
|
||||
u = strtoull(str, &ptr, base);
|
||||
if (errno || (ptr == str)) {
|
||||
/* invalid string */
|
||||
rc = LY_EVALID;
|
||||
} else if ((u > max) || (u && (str[0] == '-'))) {
|
||||
/* invalid number */
|
||||
rc = LY_EDENIED;
|
||||
} else if (*ptr) {
|
||||
while (isspace(*ptr)) {
|
||||
++ptr;
|
||||
}
|
||||
if (*ptr) {
|
||||
/* invalid characters after some number */
|
||||
rc = LY_EVALID;
|
||||
}
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
free(str);
|
||||
if (!rc) {
|
||||
*ret = u;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse an identifier.
|
||||
*
|
||||
* ;; An identifier MUST NOT start with (('X'|'x') ('M'|'m') ('L'|'l'))
|
||||
* identifier = (ALPHA / "_")
|
||||
* *(ALPHA / DIGIT / "_" / "-" / ".")
|
||||
*
|
||||
* @param[in,out] id Identifier to parse. When returned, it points to the first character which is not part of the identifier.
|
||||
* @return LY_ERR value: LY_SUCCESS or LY_EINVAL in case of invalid starting character.
|
||||
*/
|
||||
static LY_ERR
|
||||
lys_parse_id(const char **id)
|
||||
{
|
||||
assert(id && *id);
|
||||
|
||||
if (!is_yangidentstartchar(**id)) {
|
||||
return LY_EINVAL;
|
||||
}
|
||||
++(*id);
|
||||
|
||||
while (is_yangidentchar(**id)) {
|
||||
++(*id);
|
||||
}
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
ly_parse_nodeid(const char **id, const char **prefix, size_t *prefix_len, const char **name, size_t *name_len)
|
||||
{
|
||||
assert(id && *id);
|
||||
assert(prefix && prefix_len);
|
||||
assert(name && name_len);
|
||||
|
||||
*prefix = *id;
|
||||
*prefix_len = 0;
|
||||
*name = NULL;
|
||||
*name_len = 0;
|
||||
|
||||
LY_CHECK_RET(lys_parse_id(id));
|
||||
if (**id == ':') {
|
||||
/* there is prefix */
|
||||
*prefix_len = *id - *prefix;
|
||||
++(*id);
|
||||
*name = *id;
|
||||
|
||||
LY_CHECK_RET(lys_parse_id(id));
|
||||
*name_len = *id - *name;
|
||||
} else {
|
||||
/* there is no prefix, so what we have as prefix now is actually the name */
|
||||
*name = *prefix;
|
||||
*name_len = *id - *name;
|
||||
*prefix = NULL;
|
||||
}
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
ly_parse_instance_predicate(const char **pred, size_t limit, LYD_FORMAT format,
|
||||
const char **prefix, size_t *prefix_len, const char **id, size_t *id_len, const char **value, size_t *value_len,
|
||||
const char **errmsg)
|
||||
{
|
||||
LY_ERR ret = LY_EVALID;
|
||||
const char *in = *pred;
|
||||
size_t offset = 1;
|
||||
uint8_t expr = 0; /* 0 - position predicate; 1 - leaf-list-predicate; 2 - key-predicate */
|
||||
char quot;
|
||||
|
||||
assert(in[0] == '[');
|
||||
|
||||
*prefix = *id = *value = NULL;
|
||||
*prefix_len = *id_len = *value_len = 0;
|
||||
|
||||
/* leading *WSP */
|
||||
for ( ; isspace(in[offset]); offset++) {}
|
||||
|
||||
if (isdigit(in[offset])) {
|
||||
/* pos: "[" *WSP positive-integer-value *WSP "]" */
|
||||
if (in[offset] == '0') {
|
||||
/* zero */
|
||||
*errmsg = "The position predicate cannot be zero.";
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* positive-integer-value */
|
||||
*value = &in[offset++];
|
||||
for ( ; isdigit(in[offset]); offset++) {}
|
||||
*value_len = &in[offset] - *value;
|
||||
|
||||
} else if (in[offset] == '.') {
|
||||
/* leaf-list-predicate: "[" *WSP "." *WSP "=" *WSP quoted-string *WSP "]" */
|
||||
*id = &in[offset];
|
||||
*id_len = 1;
|
||||
offset++;
|
||||
expr = 1;
|
||||
} else if (in[offset] == '-') {
|
||||
/* typically negative value */
|
||||
*errmsg = "Invalid instance predicate format (negative position or invalid node-identifier).";
|
||||
goto error;
|
||||
} else {
|
||||
/* key-predicate: "[" *WSP node-identifier *WSP "=" *WSP quoted-string *WSP "]" */
|
||||
in = &in[offset];
|
||||
if (ly_parse_nodeid(&in, prefix, prefix_len, id, id_len)) {
|
||||
*errmsg = "Invalid node-identifier.";
|
||||
goto error;
|
||||
}
|
||||
if ((format == LYD_XML) && !(*prefix)) {
|
||||
/* all node names MUST be qualified with explicit namespace prefix */
|
||||
*errmsg = "Missing prefix of a node name.";
|
||||
goto error;
|
||||
}
|
||||
offset = in - *pred;
|
||||
in = *pred;
|
||||
expr = 2;
|
||||
}
|
||||
|
||||
if (expr) {
|
||||
/* *WSP "=" *WSP quoted-string *WSP "]" */
|
||||
for ( ; isspace(in[offset]); offset++) {}
|
||||
|
||||
if (in[offset] != '=') {
|
||||
if (expr == 1) {
|
||||
*errmsg = "Unexpected character instead of \'=\' in leaf-list-predicate.";
|
||||
} else { /* 2 */
|
||||
*errmsg = "Unexpected character instead of \'=\' in key-predicate.";
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
offset++;
|
||||
for ( ; isspace(in[offset]); offset++) {}
|
||||
|
||||
/* quoted-string */
|
||||
quot = in[offset++];
|
||||
if ((quot != '\'') && (quot != '\"')) {
|
||||
*errmsg = "String value is not quoted.";
|
||||
goto error;
|
||||
}
|
||||
*value = &in[offset];
|
||||
for ( ; offset < limit && (in[offset] != quot || (offset && in[offset - 1] == '\\')); offset++) {}
|
||||
if (in[offset] == quot) {
|
||||
*value_len = &in[offset] - *value;
|
||||
offset++;
|
||||
} else {
|
||||
*errmsg = "Value is not terminated quoted-string.";
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* *WSP "]" */
|
||||
for ( ; isspace(in[offset]); offset++) {}
|
||||
if (in[offset] != ']') {
|
||||
if (expr == 0) {
|
||||
*errmsg = "Predicate (pos) is not terminated by \']\' character.";
|
||||
} else if (expr == 1) {
|
||||
*errmsg = "Predicate (leaf-list-predicate) is not terminated by \']\' character.";
|
||||
} else { /* 2 */
|
||||
*errmsg = "Predicate (key-predicate) is not terminated by \']\' character.";
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
offset++;
|
||||
|
||||
if (offset <= limit) {
|
||||
*pred = &in[offset];
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
/* we read after the limit */
|
||||
*errmsg = "Predicate is incomplete.";
|
||||
*prefix = *id = *value = NULL;
|
||||
*prefix_len = *id_len = *value_len = 0;
|
||||
offset = limit;
|
||||
ret = LY_EINVAL;
|
||||
|
||||
error:
|
||||
*pred = &in[offset];
|
||||
return ret;
|
||||
}
|
677
src/ly_common.h
Normal file
677
src/ly_common.h
Normal file
|
@ -0,0 +1,677 @@
|
|||
/**
|
||||
* @file ly_common.h
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief common internal definitions for libyang
|
||||
*
|
||||
* Copyright (c) 2015 - 2024 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef LY_COMMON_H_
|
||||
#define LY_COMMON_H_
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "compat.h"
|
||||
#include "context.h"
|
||||
#include "hash_table_internal.h"
|
||||
#include "log.h"
|
||||
#include "ly_config.h"
|
||||
#include "schema_compile.h"
|
||||
#include "set.h"
|
||||
#include "tree_data.h"
|
||||
|
||||
struct ly_ctx;
|
||||
struct ly_in;
|
||||
struct lysc_node;
|
||||
|
||||
#if __STDC_VERSION__ >= 201112 && !defined __STDC_NO_THREADS__
|
||||
# define THREAD_LOCAL _Thread_local
|
||||
#elif defined __GNUC__ || \
|
||||
defined __SUNPRO_C || \
|
||||
defined __xlC__
|
||||
# define THREAD_LOCAL __thread
|
||||
#elif defined _MSC_VER
|
||||
# define THREAD_LOCAL __declspec(thread)
|
||||
#else
|
||||
# error "Cannot define THREAD_LOCAL"
|
||||
#endif
|
||||
|
||||
/** platform-specific environment variable path separator */
|
||||
#ifndef _WIN32
|
||||
# define PATH_SEPARATOR ":"
|
||||
#else
|
||||
# define PATH_SEPARATOR ";"
|
||||
#endif
|
||||
|
||||
#define GETMACRO1(_1, NAME, ...) NAME
|
||||
#define GETMACRO2(_1, _2, NAME, ...) NAME
|
||||
#define GETMACRO3(_1, _2, _3, NAME, ...) NAME
|
||||
#define GETMACRO4(_1, _2, _3, _4, NAME, ...) NAME
|
||||
#define GETMACRO5(_1, _2, _3, _4, _5, NAME, ...) NAME
|
||||
#define GETMACRO6(_1, _2, _3, _4, _5, _6, NAME, ...) NAME
|
||||
#define GETMACRO7(_1, _2, _3, _4, _5, _6, _7, NAME, ...) NAME
|
||||
|
||||
#define VOIDPTR_C(var) ((void *)(uintptr_t)(var))
|
||||
#define VOIDPTR2_C(var) ((void **)(uintptr_t)(var))
|
||||
|
||||
/******************************************************************************
|
||||
* Logger
|
||||
*****************************************************************************/
|
||||
|
||||
/** size of the last message buffer */
|
||||
#define LY_LAST_MSG_SIZE 512
|
||||
|
||||
extern ATOMIC_T ly_ll;
|
||||
extern ATOMIC_T ly_log_opts;
|
||||
|
||||
struct ly_log_location_s {
|
||||
struct ly_set inputs; /**< Set of const struct ly_in *in pointers providing the input handler with the line information (LIFO) */
|
||||
struct ly_set scnodes; /**< Set of const struct lysc_node *scnode pointers providing the compiled schema node to generate path (LIFO) */
|
||||
struct ly_set dnodes; /**< Set of const struct lyd_node *dnode pointers providing the data node to generate path (LIFO) */
|
||||
struct ly_set spaths; /**< Set of schema path strings (LIFO) */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Print a log message and store it into the context (if provided).
|
||||
*
|
||||
* @param[in] ctx libyang context to store the error record. If not provided, the error is just printed.
|
||||
* @param[in] level Log message level (error, warning, etc.)
|
||||
* @param[in] err Error code.
|
||||
* @param[in] format Format string to print.
|
||||
*/
|
||||
void ly_log(const struct ly_ctx *ctx, LY_LOG_LEVEL level, LY_ERR err, const char *format, ...) _FORMAT_PRINTF(4, 5);
|
||||
|
||||
/**
|
||||
* @brief Generate data path based on the data and schema nodes stored in the log location.
|
||||
*
|
||||
* @param[in] ctx Context for logging.
|
||||
* @param[out] path Generated data path.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
LY_ERR ly_vlog_build_data_path(const struct ly_ctx *ctx, char **path);
|
||||
|
||||
/**
|
||||
* @brief Print Validation error and store it into the context (if provided).
|
||||
*
|
||||
* @param[in] ctx libyang context to store the error record. If not provided, the error is just printed.
|
||||
* @param[in] apptag Optional specific error-app-tag.
|
||||
* @param[in] code Validation error code.
|
||||
* @param[in] format Format string to print.
|
||||
*/
|
||||
void ly_vlog(const struct ly_ctx *ctx, const char *apptag, LY_VECODE code, const char *format, ...) _FORMAT_PRINTF(4, 5);
|
||||
|
||||
/**
|
||||
* @brief Move error items from source to target context replacing any previous ones.
|
||||
*
|
||||
* @param[in] src_ctx Source context to read errors from.
|
||||
* @param[in] trg_ctx Target context to set the errors for.
|
||||
*/
|
||||
void ly_err_move(struct ly_ctx *src_ctx, struct ly_ctx *trg_ctx);
|
||||
|
||||
/**
|
||||
* @brief Logger location data setter.
|
||||
*
|
||||
* If all the parameter are NULL, a root @p dnode is added (NULL).
|
||||
*
|
||||
* @param[in] scnode Compiled schema node.
|
||||
* @param[in] dnode Data node.
|
||||
* @param[in] spath Direct schema path string to print.
|
||||
* @param[in] in Input handler (providing line number).
|
||||
*/
|
||||
void ly_log_location(const struct lysc_node *scnode, const struct lyd_node *dnode,
|
||||
const char *spath, const struct ly_in *in);
|
||||
|
||||
/**
|
||||
* @brief Revert the specific logger location data by number of changes made by ::ly_log_location().
|
||||
*
|
||||
* @param[in] scnode_steps Number of items in ::ly_log_location_s.scnodes to forget.
|
||||
* @param[in] dnode_steps Number of items in ::ly_log_location_s.dnodes to forget.
|
||||
* @param[in] spath_steps Number of path strings in ::ly_log_location_s.spaths to forget.
|
||||
* @param[in] in_steps Number of input handlers ::ly_log_location_s.inputs to forget.
|
||||
*/
|
||||
void ly_log_location_revert(uint32_t scnode_steps, uint32_t dnode_steps, uint32_t spath_steps, uint32_t in_steps);
|
||||
|
||||
/**
|
||||
* @brief Get the stored data node for logging at the index.
|
||||
*
|
||||
* @param[in] idx Index of the data node.
|
||||
* @return Logged data node, NULL if out of range.
|
||||
*/
|
||||
const struct lyd_node *ly_log_location_dnode(uint32_t idx);
|
||||
|
||||
/**
|
||||
* @brief Get the count of stored data nodes for logging.
|
||||
*
|
||||
* @return Count of the data nodes.
|
||||
*/
|
||||
uint32_t ly_log_location_dnode_count(void);
|
||||
|
||||
/**
|
||||
* @brief Update location schema/data nodes for logger, not provided arguments (NULLs) are kept (does not override).
|
||||
*
|
||||
* @param[in] SCNODE Compiled schema node.
|
||||
* @param[in] DNODE Data node.
|
||||
*/
|
||||
#define LOG_LOCSET(SCNODE, DNODE) \
|
||||
ly_log_location(SCNODE, DNODE, NULL, NULL)
|
||||
|
||||
/**
|
||||
* @brief Update location schema/data nodes for logger, not provided arguments (NULLs) are kept (does not override).
|
||||
*
|
||||
* @param[in] SCNODE_STEPS Number of the compiled schema nodes to remove from the stack.
|
||||
* @param[in] DNODE_STEPS Number of the data nodes to remove from the stack.
|
||||
*/
|
||||
#define LOG_LOCBACK(SCNODE_STEPS, DNODE_STEPS) \
|
||||
ly_log_location_revert(SCNODE_STEPS, DNODE_STEPS, 0, 0)
|
||||
|
||||
#define LOGERR(ctx, errno, ...) ly_log(ctx, LY_LLERR, errno, __VA_ARGS__)
|
||||
#define LOGWRN(ctx, ...) ly_log(ctx, LY_LLWRN, 0, __VA_ARGS__)
|
||||
#define LOGVRB(...) ly_log(NULL, LY_LLVRB, 0, __VA_ARGS__)
|
||||
|
||||
#ifdef NDEBUG
|
||||
# define LOGDBG(dbg_group, ...)
|
||||
#else
|
||||
void ly_log_dbg(uint32_t group, const char *format, ...);
|
||||
# define LOGDBG(dbg_group, ...) ly_log_dbg(dbg_group, __VA_ARGS__);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Simple EMEM message, it can be safely stored in ::ly_err_item structures without problems when freeing.
|
||||
*/
|
||||
#define LY_EMEM_MSG "Memory allocation failed."
|
||||
|
||||
#ifdef LOGMEM
|
||||
/* overwrite shadow definition from tree_edit.h */
|
||||
#undef LOGMEM
|
||||
#endif
|
||||
#define LOGMEM(CTX) LOGERR(CTX, LY_EMEM, "Memory allocation failed (%s()).", __func__)
|
||||
|
||||
#define LOGINT(CTX) LOGERR(CTX, LY_EINT, "Internal error (%s:%d).", __FILE__, __LINE__)
|
||||
#define LOGARG(CTX, ARG) LOGERR(CTX, LY_EINVAL, "Invalid argument %s (%s()).", #ARG, __func__)
|
||||
#define LOGVAL(CTX, ...) ly_vlog(CTX, NULL, __VA_ARGS__)
|
||||
#define LOGVAL_APPTAG(CTX, APPTAG, ...) ly_vlog(CTX, APPTAG, __VA_ARGS__)
|
||||
|
||||
#define LOGMEM_RET(CTX) LOGMEM(CTX); return LY_EMEM
|
||||
#define LOGINT_RET(CTX) LOGINT(CTX); return LY_EINT
|
||||
#define LOGARG_RET(CTX) LOGARG(CTX); return LY_EINVAL
|
||||
|
||||
/*
|
||||
* Common code to check return value and perform appropriate action.
|
||||
*/
|
||||
#define LY_CHECK_GOTO(COND, GOTO) if ((COND)) {goto GOTO;}
|
||||
#define LY_CHECK_ERR_GOTO(COND, ERR, GOTO) if ((COND)) {ERR; goto GOTO;}
|
||||
#define LY_CHECK_RET1(RETVAL) {LY_ERR ret__ = RETVAL;if (ret__ != LY_SUCCESS) {return ret__;}}
|
||||
#define LY_CHECK_RET2(COND, RETVAL) if ((COND)) {return RETVAL;}
|
||||
#define LY_CHECK_RET(...) GETMACRO2(__VA_ARGS__, LY_CHECK_RET2, LY_CHECK_RET1, DUMMY)(__VA_ARGS__)
|
||||
#define LY_CHECK_ERR_RET(COND, ERR, RETVAL) if ((COND)) {ERR; return RETVAL;}
|
||||
|
||||
#define LY_CHECK_ARG_GOTO1(CTX, ARG, GOTO) if (!(ARG)) {LOGARG(CTX, ARG);goto GOTO;}
|
||||
#define LY_CHECK_ARG_GOTO2(CTX, ARG1, ARG2, GOTO) LY_CHECK_ARG_GOTO1(CTX, ARG1, GOTO);LY_CHECK_ARG_GOTO1(CTX, ARG2, GOTO)
|
||||
#define LY_CHECK_ARG_GOTO3(CTX, ARG1, ARG2, ARG3, GOTO) LY_CHECK_ARG_GOTO2(CTX, ARG1, ARG2, GOTO);LY_CHECK_ARG_GOTO1(CTX, ARG3, GOTO)
|
||||
#define LY_CHECK_ARG_GOTO4(CTX, ARG1, ARG2, ARG3, ARG4, GOTO) LY_CHECK_ARG_GOTO3(CTX, ARG1, ARG2, ARG3, GOTO);\
|
||||
LY_CHECK_ARG_GOTO1(CTX, ARG4, GOTO)
|
||||
#define LY_CHECK_ARG_GOTO(CTX, ...) GETMACRO5(__VA_ARGS__, LY_CHECK_ARG_GOTO4, LY_CHECK_ARG_GOTO3, LY_CHECK_ARG_GOTO2, \
|
||||
LY_CHECK_ARG_GOTO1)(CTX, __VA_ARGS__)
|
||||
|
||||
#define LY_CHECK_ARG_RET1(CTX, ARG, RETVAL) if (!(ARG)) {LOGARG(CTX, ARG);return RETVAL;}
|
||||
#define LY_CHECK_ARG_RET2(CTX, ARG1, ARG2, RETVAL) LY_CHECK_ARG_RET1(CTX, ARG1, RETVAL);LY_CHECK_ARG_RET1(CTX, ARG2, RETVAL)
|
||||
#define LY_CHECK_ARG_RET3(CTX, ARG1, ARG2, ARG3, RETVAL) LY_CHECK_ARG_RET2(CTX, ARG1, ARG2, RETVAL);LY_CHECK_ARG_RET1(CTX, ARG3, RETVAL)
|
||||
#define LY_CHECK_ARG_RET4(CTX, ARG1, ARG2, ARG3, ARG4, RETVAL) LY_CHECK_ARG_RET3(CTX, ARG1, ARG2, ARG3, RETVAL);\
|
||||
LY_CHECK_ARG_RET1(CTX, ARG4, RETVAL)
|
||||
#define LY_CHECK_ARG_RET5(CTX, ARG1, ARG2, ARG3, ARG4, ARG5, RETVAL) LY_CHECK_ARG_RET4(CTX, ARG1, ARG2, ARG3, ARG4, RETVAL);\
|
||||
LY_CHECK_ARG_RET1(CTX, ARG5, RETVAL)
|
||||
#define LY_CHECK_ARG_RET6(CTX, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, RETVAL) LY_CHECK_ARG_RET5(CTX, ARG1, ARG2, ARG3, ARG4, ARG5, RETVAL);\
|
||||
LY_CHECK_ARG_RET1(CTX, ARG6, RETVAL)
|
||||
#define LY_CHECK_ARG_RET(CTX, ...) GETMACRO7(__VA_ARGS__, LY_CHECK_ARG_RET6, LY_CHECK_ARG_RET5, LY_CHECK_ARG_RET4, \
|
||||
LY_CHECK_ARG_RET3, LY_CHECK_ARG_RET2, LY_CHECK_ARG_RET1, DUMMY) (CTX, __VA_ARGS__)
|
||||
|
||||
#define LY_CHECK_CTX_EQUAL_RET2(CTX1, CTX2, RETVAL) if ((CTX1) && (CTX2) && ((CTX1) != (CTX2))) \
|
||||
{LOGERR(CTX1, LY_EINVAL, "Different contexts mixed in a single function call."); return RETVAL;}
|
||||
#define LY_CHECK_CTX_EQUAL_RET3(CTX1, CTX2, CTX3, RETVAL) LY_CHECK_CTX_EQUAL_RET2(CTX1, CTX2, RETVAL); \
|
||||
LY_CHECK_CTX_EQUAL_RET2(CTX2, CTX3, RETVAL); LY_CHECK_CTX_EQUAL_RET2(CTX1, CTX3, RETVAL)
|
||||
#define LY_CHECK_CTX_EQUAL_RET(CTX, ...) GETMACRO3(__VA_ARGS__, LY_CHECK_CTX_EQUAL_RET3, LY_CHECK_CTX_EQUAL_RET2, \
|
||||
DUMMY) (CTX, __VA_ARGS__)
|
||||
|
||||
/* count sequence size for LY_VCODE_INCHILDSTMT validation error code */
|
||||
int LY_VCODE_INSTREXP_len(const char *str);
|
||||
|
||||
/* default maximum characters to print in LY_VCODE_INCHILDSTMT */
|
||||
#define LY_VCODE_INSTREXP_MAXLEN 20
|
||||
|
||||
#define LY_VCODE_INCHAR LYVE_SYNTAX, "Invalid character 0x%hhx."
|
||||
#define LY_VCODE_INSTREXP LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected %s."
|
||||
#define LY_VCODE_EOF LYVE_SYNTAX, "Unexpected end-of-input."
|
||||
#define LY_VCODE_NTERM LYVE_SYNTAX, "%s not terminated."
|
||||
#define LY_VCODE_NSUPP LYVE_SYNTAX, "%s not supported."
|
||||
#define LY_VCODE_MOD_SUBOMD LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\"."
|
||||
#define LY_VCODE_TRAILING_MOD LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after module, expected end-of-input."
|
||||
#define LY_VCODE_TRAILING_SUBMOD LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after submodule, expected end-of-input."
|
||||
|
||||
#define LY_VCODE_INVAL_MINMAX LYVE_SEMANTICS, "Invalid combination of min-elements and max-elements: min value %" PRIu32 " is bigger than the max value %" PRIu32 "."
|
||||
#define LY_VCODE_NAME_COL LYVE_SEMANTICS, "Name collision between %s of name \"%s\"."
|
||||
#define LY_VCODE_NAME2_COL LYVE_SEMANTICS, "Name collision between %s and %s of name \"%s\"."
|
||||
|
||||
#define LY_VCODE_INSTMT LYVE_SYNTAX_YANG, "Invalid keyword \"%s\"."
|
||||
#define LY_VCODE_INCHILDSTMT LYVE_SYNTAX_YANG, "Invalid keyword \"%s\" as a child of \"%s\"."
|
||||
#define LY_VCODE_INCHILDSTMT2 LYVE_SYNTAX_YANG, "Invalid keyword \"%s\" as a child of \"%s\" - the statement is allowed only in YANG 1.1 modules."
|
||||
#define LY_VCODE_INCHILDSTMSCOMB LYVE_SYNTAX_YANG, "Invalid combination of keywords \"%s\" and \"%s\" as substatements of \"%s\"."
|
||||
#define LY_VCODE_DUPSTMT LYVE_SYNTAX_YANG, "Duplicate keyword \"%s\"."
|
||||
#define LY_VCODE_DUPIDENT LYVE_SYNTAX_YANG, "Duplicate identifier \"%s\" of %s statement."
|
||||
#define LY_VCODE_DUPIDENT2 LYVE_SYNTAX_YANG, "Duplicate identifier \"%s\" of %s statement - %s."
|
||||
#define LY_VCODE_INVAL LYVE_SYNTAX_YANG, "Invalid value \"%.*s\" of \"%s\"."
|
||||
#define LY_VCODE_MISSTMT LYVE_SYNTAX_YANG, "Missing mandatory keyword \"%s\" as a child of \"%s\"."
|
||||
#define LY_VCODE_MISSCHILDSTMT LYVE_SYNTAX_YANG, "Missing %s substatement for %s%s."
|
||||
#define LY_VCODE_INORD LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", it cannot appear after \"%s\"."
|
||||
#define LY_VCODE_OOB LYVE_SYNTAX_YANG, "Value \"%.*s\" is out of \"%s\" bounds."
|
||||
#define LY_VCODE_INDEV LYVE_SYNTAX_YANG, "Deviate \"%s\" does not support keyword \"%s\"."
|
||||
#define LY_VCODE_INREGEXP LYVE_SYNTAX_YANG, "Regular expression \"%s\" is not valid (\"%s\": %s)."
|
||||
|
||||
#define LY_VCODE_INSUBELEM2 LYVE_SYNTAX_YIN, "Invalid sub-elemnt \"%s\" of \"%s\" element - this sub-element is allowed only in modules with version 1.1 or newer."
|
||||
#define LY_VCODE_INVAL_YIN LYVE_SYNTAX_YIN, "Invalid value \"%s\" of \"%s\" attribute in \"%s\" element."
|
||||
#define LY_VCODE_UNEXP_SUBELEM LYVE_SYNTAX_YIN, "Unexpected sub-element \"%.*s\" of \"%s\" element."
|
||||
#define LY_VCODE_INDEV_YIN LYVE_SYNTAX_YIN, "Deviate of this type doesn't allow \"%s\" as it's sub-element."
|
||||
#define LY_VCODE_INORDER_YIN LYVE_SYNTAX_YIN, "Invalid order of %s\'s sub-elements \"%s\" can't appear after \"%s\"."
|
||||
#define LY_VCODE_OOB_YIN LYVE_SYNTAX_YIN, "Value \"%s\" of \"%s\" attribute in \"%s\" element is out of bounds."
|
||||
#define LY_VCODE_INCHILDSTMSCOMB_YIN LYVE_SYNTAX_YIN, "Invalid combination of sub-elemnts \"%s\" and \"%s\" in \"%s\" element."
|
||||
#define LY_VCODE_DUP_ATTR LYVE_SYNTAX_YIN, "Duplicit definition of \"%s\" attribute in \"%s\" element."
|
||||
#define LY_VCODE_UNEXP_ATTR LYVE_SYNTAX_YIN, "Unexpected attribute \"%.*s\" of \"%s\" element."
|
||||
#define LY_VCODE_MAND_SUBELEM LYVE_SYNTAX_YIN, "Missing mandatory sub-element \"%s\" of \"%s\" element."
|
||||
#define LY_VCODE_FIRT_SUBELEM LYVE_SYNTAX_YIN, "Sub-element \"%s\" of \"%s\" element must be defined as it's first sub-element."
|
||||
#define LY_VCODE_SUBELEM_REDEF LYVE_SYNTAX_YIN, "Redefinition of \"%s\" sub-element in \"%s\" element."
|
||||
|
||||
#define LY_VCODE_XP_EOE LYVE_XPATH, "Unterminated string delimited with %c (%.15s)."
|
||||
#define LY_VCODE_XP_INEXPR LYVE_XPATH, "Invalid character '%c'[%" PRIu32 "] of expression \'%s\'."
|
||||
#define LY_VCODE_XP_EOF LYVE_XPATH, "Unexpected XPath expression end."
|
||||
#define LY_VCODE_XP_INTOK LYVE_XPATH, "Unexpected XPath token \"%s\" (\"%.15s\")."
|
||||
#define LY_VCODE_XP_INTOK2 LYVE_XPATH, "Unexpected XPath token \"%s\" (\"%.15s\"), expected \"%s\"."
|
||||
#define LY_VCODE_XP_INFUNC LYVE_XPATH, "Unknown XPath function \"%.*s\"."
|
||||
#define LY_VCODE_XP_INARGCOUNT LYVE_XPATH, "Invalid number of arguments (%" PRIu32 ") for the XPath function %.*s."
|
||||
#define LY_VCODE_XP_INARGTYPE LYVE_XPATH, "Wrong type of argument #%d (%s) for the XPath function %s."
|
||||
#define LY_VCODE_XP_INCTX LYVE_XPATH, "Invalid context type %s in %s."
|
||||
#define LY_VCODE_XP_INOP_1 LYVE_XPATH, "Cannot apply XPath operation %s on %s."
|
||||
#define LY_VCODE_XP_INOP_2 LYVE_XPATH, "Cannot apply XPath operation %s on %s and %s."
|
||||
#define LY_VCODE_XP_INMOD LYVE_XPATH, "Unknown/non-implemented module \"%.*s\"."
|
||||
#define LY_VCODE_XP_DEPTH LYVE_XPATH, "The maximum nesting of expressions has been exceeded."
|
||||
|
||||
#define LY_VCODE_DEV_NOT_PRESENT LYVE_REFERENCE, "Invalid deviation %s \"%s\" property \"%s\" which is not present."
|
||||
|
||||
#define LY_VCODE_NOWHEN LYVE_DATA, "When condition \"%s\" not satisfied."
|
||||
#define LY_VCODE_NOMAND LYVE_DATA, "Mandatory node \"%s\" instance does not exist."
|
||||
#define LY_VCODE_DUP LYVE_DATA, "Duplicate instance of \"%s\"."
|
||||
#define LY_VCODE_DUPCASE LYVE_DATA, "Data for both cases \"%s\" and \"%s\" exist."
|
||||
#define LY_VCODE_UNEXPNODE LYVE_DATA, "Unexpected data %s node \"%s\" found."
|
||||
#define LY_VCODE_NOKEY LYVE_DATA, "List instance is missing its key \"%s\"."
|
||||
|
||||
#define LY_ERRMSG_NOPATTERN /* LYVE_DATA */ "Unsatisfied pattern - \"%.*s\" does not conform to %s\"%s\"."
|
||||
#define LY_ERRMSG_NOLENGTH /* LYVE_DATA */ "Unsatisfied length - string \"%.*s\" length is not allowed."
|
||||
#define LY_ERRMSG_NORANGE /* LYVE_DATA */ "Unsatisfied range - value \"%.*s\" is out of the allowed range."
|
||||
|
||||
/* RFC 7950 section 15 errors */
|
||||
#define LY_VCODE_NOUNIQ LYVE_DATA, "Unique data leaf(s) \"%s\" not satisfied in \"%s\" and \"%s\"."
|
||||
#define LY_VCODE_NOMAX LYVE_DATA, "Too many \"%s\" instances."
|
||||
#define LY_VCODE_NOMIN LYVE_DATA, "Too few \"%s\" instances."
|
||||
#define LY_VCODE_NOMUST LYVE_DATA, "Must condition \"%s\" not satisfied."
|
||||
#define LY_VCODE_NOMAND_CHOIC LYVE_DATA, "Mandatory choice \"%s\" data do not exist."
|
||||
|
||||
/* RFC 7950 section 15 error messages used in type plugin validation callbacks */
|
||||
#define LY_ERRMSG_NOLREF_VAL /* LYVE_DATA */ "Invalid leafref value \"%s\" - no target instance \"%s\" with the same value."
|
||||
#define LY_ERRMSG_NOINST /* LYVE_DATA */ "Invalid instance-identifier \"%s\" value - required instance not found."
|
||||
|
||||
/******************************************************************************
|
||||
* Context
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Context error hash table record.
|
||||
*/
|
||||
struct ly_ctx_err_rec {
|
||||
struct ly_err_item *err; /** pointer to the error items, if any */
|
||||
pthread_t tid; /** pthread thread ID */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Context of the YANG schemas
|
||||
*/
|
||||
struct ly_ctx {
|
||||
struct ly_dict dict; /**< dictionary to effectively store strings used in the context related structures */
|
||||
struct ly_set search_paths; /**< set of directories where to search for schema's imports/includes */
|
||||
struct ly_set list; /**< set of loaded YANG schemas */
|
||||
ly_module_imp_clb imp_clb; /**< optional callback for retrieving missing included or imported models */
|
||||
void *imp_clb_data; /**< optional private data for ::ly_ctx.imp_clb */
|
||||
struct lys_glob_unres unres; /**< global unres, should be empty unless there are modules prepared for
|
||||
compilation if ::LY_CTX_EXPLICIT_COMPILE flag is set */
|
||||
uint16_t change_count; /**< count of changes of the context, on some changes it could be incremented
|
||||
more times */
|
||||
uint16_t flags; /**< context settings, see @ref contextoptions */
|
||||
|
||||
ly_ext_data_clb ext_clb; /**< optional callback for providing extension-specific run-time data for extensions */
|
||||
void *ext_clb_data; /**< optional private data for ::ly_ctx.ext_clb */
|
||||
struct ly_ht *err_ht; /**< hash table of thread-specific list of errors related to the context */
|
||||
pthread_mutex_t lyb_hash_lock; /**< lock for storing LYB schema hashes in schema nodes */
|
||||
struct ly_ht *leafref_links_ht; /**< hash table of leafref links between term data nodes */
|
||||
struct ly_set plugins_types; /**< context specific set of type plugins */
|
||||
struct ly_set plugins_extensions; /**< contets specific set of extension plugins */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Get the (only) implemented YANG module specified by its name.
|
||||
*
|
||||
* @param[in] ctx Context where to search.
|
||||
* @param[in] name Name of the YANG module to get.
|
||||
* @param[in] name_len Optional length of the @p name. If zero, NULL-terminated name is expected.
|
||||
* @return The only implemented YANG module revision of the given name in the given context. NULL if there is no
|
||||
* implemented module of the given name.
|
||||
*/
|
||||
struct lys_module *ly_ctx_get_module_implemented2(const struct ly_ctx *ctx, const char *name, size_t name_len);
|
||||
|
||||
/******************************************************************************
|
||||
* Generic useful functions.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Insert string into dictionary.
|
||||
*
|
||||
* @param[in] CTX libyang context.
|
||||
* @param[in] STRING string to store.
|
||||
* @param[in] LEN length of the string in WORD to store.
|
||||
* @param[in,out] DYNAMIC Set to 1 if @p STRING is dynamically allocated, 0 otherwise.
|
||||
* If set to 1, zerocopy version of lydict_insert is used.
|
||||
* @param[out] TARGET pointer is set to @p STRING value stored in the dictionary.
|
||||
*/
|
||||
#define INSERT_STRING_RET(CTX, STRING, LEN, DYNAMIC, TARGET) \
|
||||
if (DYNAMIC) { \
|
||||
LY_CHECK_RET(lydict_insert_zc(CTX, (char *)(STRING), &(TARGET))); \
|
||||
} else { \
|
||||
LY_CHECK_RET(lydict_insert(CTX, LEN ? (STRING) : "", LEN, &(TARGET))); \
|
||||
} \
|
||||
DYNAMIC = 0
|
||||
|
||||
/**
|
||||
* @brief Wrapper for realloc() call. The only difference is that if it fails to
|
||||
* allocate the requested memory, the original memory is freed as well.
|
||||
*
|
||||
* @param[in] ptr Memory to reallocate.
|
||||
* @param[in] size New size of the memory block.
|
||||
* @return Pointer to the new memory, NULL on error.
|
||||
*/
|
||||
void *ly_realloc(void *ptr, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Just like strchr() function except limit the number of examined characters.
|
||||
*
|
||||
* @param[in] s String to search in.
|
||||
* @param[in] c Character to search for.
|
||||
* @param[in] len Limit the search to this number of characters in @p s.
|
||||
* @return Pointer to first @p c occurrence in @p s, NULL if not found in first @p len characters.
|
||||
*/
|
||||
char *ly_strnchr(const char *s, int c, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Compare NULL-terminated @p refstr with @p str_len bytes from @p str.
|
||||
*
|
||||
* @param[in] refstr NULL-terminated string which must match @p str_len bytes from @p str followed by NULL-byte.
|
||||
* @param[in] str String to compare.
|
||||
* @param[in] str_len Number of bytes to take into comparison from @p str.
|
||||
* @return An integer less than, equal to, or greater than zero if @p refstr matches,
|
||||
* respectively, to be less than, to match, or be greater than @p str.
|
||||
*/
|
||||
int ly_strncmp(const char *refstr, const char *str, size_t str_len);
|
||||
|
||||
/**
|
||||
* @brief Similar functionality to strtoul() except number length in the string
|
||||
* must be specified and the whole number must be parsed for success.
|
||||
*
|
||||
* @param[in] nptr Number string.
|
||||
* @param[in] len Number string length starting at @p nptr.
|
||||
* @param[out] ret Parsed number.
|
||||
* @return LY_EDENIED on overflow.
|
||||
* @return LY_EVALID on encountering a non-digit character.
|
||||
* @return LY_SUCCESS on success.
|
||||
*/
|
||||
LY_ERR ly_strntou8(const char *nptr, size_t len, uint8_t *ret);
|
||||
|
||||
/**
|
||||
* @brief Get all possible value prefixes from an YANG value by iteratively returning specific substrings.
|
||||
*
|
||||
* The function looks for possible prefix ending in a colon at the beginning of @p str_begin.
|
||||
* If @p str_begin does not contain the prefix at the beginning, then either:
|
||||
* 1. Returns the entire input string if the input string does not contain the prefix at all.
|
||||
* 2. Returns a substring before the prefix. The substring is terminated by any character
|
||||
* that is not allowed to be present in prefix (except colon).
|
||||
*
|
||||
* Examples of inputs and outputs are shown in the table below.
|
||||
* Output string @p str_next is used in the next iteration as input parameter @p str_begin.
|
||||
@verbatim
|
||||
| INPUT | OUTPUT |
|
||||
| | iteration 1 | iteration 2 | iteration 3 |
|
||||
|------------------------------ |------------------|------------------|-----------------|
|
||||
| /namespace_prefix:some_string | / | namespace_prefix | some_string |
|
||||
| namespace_prefix:some_string | namespace_prefix | some_string | NULL |
|
||||
| /some_string | /some_string | NULL | NULL |
|
||||
@endverbatim
|
||||
*
|
||||
*
|
||||
* @param[in] str_begin Begin of the input string.
|
||||
* @param[in] str_end Length of the @p str_begin. If set to NULL then the @p str_begin must be NULL-terminated string.
|
||||
* @param[out] len Number of bytes (length) of the found prefix/substring starting at @p str_begin.
|
||||
* @param[out] is_prefix Type of substring found. Set to True for prefix, otherwise False.
|
||||
* @param[out] str_next Remaining string starting after prefix/substring and ending with @p str_end.
|
||||
* If the @p is_prefix is set to True then the colon character is skipped.
|
||||
* If no string remains, it is set to NULL.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
LY_ERR ly_value_prefix_next(const char *str_begin, const char *str_end, uint32_t *len, ly_bool *is_prefix,
|
||||
const char **str_next);
|
||||
|
||||
/**
|
||||
* @brief Wrapper around strlen() to handle NULL strings.
|
||||
*/
|
||||
#define ly_strlen(STR) (STR ? strlen(STR) : 0)
|
||||
|
||||
/**
|
||||
* @brief Compile-time strlen() for string constants.
|
||||
*
|
||||
* Use to avoid magic numbers usage
|
||||
*/
|
||||
#define ly_strlen_const(STR) (sizeof STR - 1)
|
||||
|
||||
/**
|
||||
* @brief Macro to simply put couple of string length and the string as
|
||||
* printf's arguments for %.*s. Use only with constant strings.
|
||||
*/
|
||||
#define LY_PRI_LENSTR(STR) (int)ly_strlen_const(STR), STR
|
||||
|
||||
#define ly_sizeofarray(ARRAY) (sizeof ARRAY / sizeof *ARRAY)
|
||||
|
||||
/**
|
||||
* @brief Check for overflow during the addition of two unsigned integers.
|
||||
*/
|
||||
#define LY_OVERFLOW_ADD(MAX, X, Y) (X > MAX - Y)
|
||||
|
||||
/**
|
||||
* @brief Check for overflow during the multiplication of two unsigned integers.
|
||||
*/
|
||||
#define LY_OVERFLOW_MUL(MAX, X, Y) (X > MAX / Y)
|
||||
|
||||
/*
|
||||
* Numerical bases for use in functions like strtoll() instead of magic numbers
|
||||
*/
|
||||
#define LY_BASE_DEC 10 /**< Decimal numeral base */
|
||||
#define LY_BASE_OCT 8 /**< Octal numeral base */
|
||||
#define LY_BASE_HEX 16 /**< Hexadecimal numeral base */
|
||||
|
||||
/**
|
||||
* Maximal length of (needed storage for) a number encoded as a string.
|
||||
*
|
||||
* Applies not only for standard numbers, but also for YANG's decimal64.
|
||||
*/
|
||||
#define LY_NUMBER_MAXLEN 22
|
||||
|
||||
/**
|
||||
* @brief Get UTF8 code point of the next character in the input string.
|
||||
*
|
||||
* @param[in,out] input Input string to process, updated according to the processed/read data.
|
||||
* @param[out] utf8_char UTF8 code point of the next character.
|
||||
* @param[out] bytes_read Number of bytes used to encode the read utf8_char.
|
||||
* @return LY_ERR value
|
||||
*/
|
||||
LY_ERR ly_getutf8(const char **input, uint32_t *utf8_char, size_t *bytes_read);
|
||||
|
||||
/**
|
||||
* @brief Check an UTF-8 character is valid.
|
||||
*
|
||||
* @param[in] input Input string to process.
|
||||
* @param[in] in_len Bytes left to read in @p input.
|
||||
* @param[out] utf8_len Length of a valid UTF-8 character.
|
||||
* @return LY_SUCCESS on success
|
||||
* @return LY_EINVAL in case of invalid UTF-8 character.
|
||||
*/
|
||||
LY_ERR ly_checkutf8(const char *input, size_t in_len, size_t *utf8_len);
|
||||
|
||||
/**
|
||||
* @brief Store UTF-8 character specified as 4byte integer into the dst buffer.
|
||||
*
|
||||
* UTF-8 mapping:
|
||||
* 00000000 -- 0000007F: 0xxxxxxx
|
||||
* 00000080 -- 000007FF: 110xxxxx 10xxxxxx
|
||||
* 00000800 -- 0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
|
||||
* 00010000 -- 001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
*
|
||||
* Includes checking for valid characters (following RFC 7950, sec 9.4)
|
||||
*
|
||||
* @param[in,out] dst Destination buffer to store the UTF-8 character, must provide enough space (up to 4 bytes) for storing the UTF-8 character.
|
||||
* @param[in] value 32b value of the UTF-8 character to store.
|
||||
* @param[out] bytes_written Number of bytes written into @p dst (size of the written UTF-8 character).
|
||||
* @return LY_SUCCESS on success
|
||||
* @return LY_EINVAL in case of invalid UTF-8 @p value to store.
|
||||
*/
|
||||
LY_ERR ly_pututf8(char *dst, uint32_t value, size_t *bytes_written);
|
||||
|
||||
/**
|
||||
* @brief Get number of characters in the @p str, taking multibyte characters into account.
|
||||
*
|
||||
* @param[in] str String to examine.
|
||||
* @param[in] bytes Number of valid bytes that are supposed to be taken into account in @p str.
|
||||
* This parameter is useful mainly for non NULL-terminated strings. In case of NULL-terminated
|
||||
* string, strlen() can be used.
|
||||
* @return Number of characters in (possibly) multibyte characters string.
|
||||
*/
|
||||
size_t ly_utf8len(const char *str, size_t bytes);
|
||||
|
||||
/**
|
||||
* @brief Parse signed integer with possible limitation.
|
||||
*
|
||||
* @param[in] val_str String value containing signed integer, note that
|
||||
* nothing else than whitespaces are expected after the value itself.
|
||||
* @param[in] val_len Length of the @p val_str string.
|
||||
* @param[in] min Limitation for the value which must not be lower than min.
|
||||
* @param[in] max Limitation for the value which must not be higher than max.
|
||||
* @param[in] base Numeric base for parsing:
|
||||
* 0 - to accept decimal, octal, hexadecimal (e.g. in default value)
|
||||
* 10 - to accept only decimal (e.g. data instance value)
|
||||
* @param[out] ret Resulting value.
|
||||
* @return LY_ERR value:
|
||||
* LY_EDENIED - the value breaks the limits,
|
||||
* LY_EVALID - string contains invalid value,
|
||||
* LY_SUCCESS - successful parsing.
|
||||
*/
|
||||
LY_ERR ly_parse_int(const char *val_str, size_t val_len, int64_t min, int64_t max, int base, int64_t *ret);
|
||||
|
||||
/**
|
||||
* @brief Parse unsigned integer with possible limitation.
|
||||
*
|
||||
* @param[in] val_str String value containing unsigned integer, note that
|
||||
* nothing else than whitespaces are expected after the value itself.
|
||||
* @param[in] val_len Length of the @p val_str string.
|
||||
* @param[in] max Limitation for the value which must not be higher than max.
|
||||
* @param[in] base Numeric base for parsing:
|
||||
* 0 - to accept decimal, octal, hexadecimal (e.g. in default value)
|
||||
* 10 - to accept only decimal (e.g. data instance value)
|
||||
* @param[out] ret Resulting value.
|
||||
* @return LY_ERR value:
|
||||
* LY_EDENIED - the value breaks the limits,
|
||||
* LY_EVALID - string contains invalid value,
|
||||
* LY_SUCCESS - successful parsing.
|
||||
*/
|
||||
LY_ERR ly_parse_uint(const char *val_str, size_t val_len, uint64_t max, int base, uint64_t *ret);
|
||||
|
||||
/**
|
||||
* @brief Parse a node-identifier.
|
||||
*
|
||||
* node-identifier = [prefix ":"] identifier
|
||||
*
|
||||
* @param[in,out] id Identifier to parse. When returned, it points to the first character which is not part of the identifier.
|
||||
* @param[out] prefix Node's prefix, NULL if there is not any.
|
||||
* @param[out] prefix_len Length of the node's prefix, 0 if there is not any.
|
||||
* @param[out] name Node's name.
|
||||
* @param[out] name_len Length of the node's name.
|
||||
* @return LY_ERR value: LY_SUCCESS or LY_EINVAL in case of invalid character in the id.
|
||||
*/
|
||||
LY_ERR ly_parse_nodeid(const char **id, const char **prefix, size_t *prefix_len, const char **name, size_t *name_len);
|
||||
|
||||
/**
|
||||
* @brief parse instance-identifier's predicate, supports key-predicate, leaf-list-predicate and pos rules from YANG ABNF Grammar.
|
||||
*
|
||||
* @param[in,out] pred Predicate string (including the leading '[') to parse. The string is updated according to what was parsed
|
||||
* (even for error case, so it can be used to determine which substring caused failure).
|
||||
* @param[in] limit Limiting length of the @p pred. Function expects NULL terminated string which is not overread.
|
||||
* The limit value is not checked with each character, so it can be overread and the failure is detected later.
|
||||
* @param[in] format Input format of the data containing the @p pred.
|
||||
* @param[out] prefix Start of the node-identifier's prefix if any, NULL in case of pos or leaf-list-predicate rules.
|
||||
* @param[out] prefix_len Length of the parsed @p prefix.
|
||||
* @param[out] id Start of the node-identifier's identifier string, NULL in case of pos rule, "." in case of leaf-list-predicate rule.
|
||||
* @param[out] id_len Length of the parsed @p id.
|
||||
* @param[out] value Start of the quoted-string (without quotation marks), not NULL in case of success.
|
||||
* @param[out] value_len Length of the parsed @p value.
|
||||
* @param[out] errmsg Error message string in case of error.
|
||||
* @return LY_SUCCESS in case a complete predicate was parsed.
|
||||
* @return LY_EVALID in case of invalid predicate form.
|
||||
* @return LY_EINVAL in case of reaching @p limit when parsing @p pred.
|
||||
*/
|
||||
LY_ERR ly_parse_instance_predicate(const char **pred, size_t limit, LYD_FORMAT format,
|
||||
const char **prefix, size_t *prefix_len, const char **id, size_t *id_len,
|
||||
const char **value, size_t *value_len, const char **errmsg);
|
||||
|
||||
/**
|
||||
* @brief mmap(2) wrapper to map input files into memory to unify parsing.
|
||||
*
|
||||
* The address space is allocate only for reading.
|
||||
*
|
||||
* @param[in] ctx libyang context for logging
|
||||
* @param[in] fd Open file descriptor of a file to map.
|
||||
* @param[out] length Allocated size.
|
||||
* @param[out] addr Address where the file is mapped.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
LY_ERR ly_mmap(struct ly_ctx *ctx, int fd, size_t *length, void **addr);
|
||||
|
||||
/**
|
||||
* @brief munmap(2) wrapper to free the memory mapped by ::ly_mmap()
|
||||
*
|
||||
* @param[in] addr Address where the input file is mapped.
|
||||
* @param[in] length Allocated size of the address space.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
LY_ERR ly_munmap(void *addr, size_t length);
|
||||
|
||||
/**
|
||||
* @brief Concatenate formating string to the @p dest.
|
||||
*
|
||||
* @param[in,out] dest String to be concatenated by @p format.
|
||||
* Note that the input string can be reallocated during concatenation.
|
||||
* @param[in] format Formating string (as for printf) which is supposed to be added after @p dest.
|
||||
* @return LY_SUCCESS or LY_EMEM.
|
||||
*/
|
||||
LY_ERR ly_strcat(char **dest, const char *format, ...) _FORMAT_PRINTF(2, 3);
|
||||
|
||||
#endif /* LY_COMMON_H_ */
|
75
src/ly_config.h.in
Normal file
75
src/ly_config.h.in
Normal file
|
@ -0,0 +1,75 @@
|
|||
/**
|
||||
* @file ly_config.h
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @uathor Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief Various variables provided by cmake and compile time options.
|
||||
*
|
||||
* Copyright (c) 2021 - 2024 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef LY_CONFIG_H_
|
||||
#define LY_CONFIG_H_
|
||||
|
||||
#ifdef _WIN32
|
||||
/* headers are broken on Windows, which means that some of them simply *have* to come first */
|
||||
# include <winsock2.h>
|
||||
# include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
/** size of fixed_mem in lyd_value, minimum is 8 (B) */
|
||||
#define LYD_VALUE_FIXED_MEM_SIZE @LYD_VALUE_SIZE@
|
||||
|
||||
/** plugins */
|
||||
#define LYPLG_SUFFIX "@CMAKE_SHARED_MODULE_SUFFIX@"
|
||||
#define LYPLG_SUFFIX_LEN (sizeof LYPLG_SUFFIX - 1)
|
||||
#define LYPLG_TYPE_DIR "@PLUGINS_DIR_TYPES@"
|
||||
#define LYPLG_EXT_DIR "@PLUGINS_DIR_EXTENSIONS@"
|
||||
|
||||
/** atomic compiler operations, to be able to use uint32_t */
|
||||
#ifndef _WIN32
|
||||
# define LY_ATOMIC_INC_BARRIER(var) __sync_fetch_and_add(&(var), 1)
|
||||
# define LY_ATOMIC_DEC_BARRIER(var) __sync_fetch_and_sub(&(var), 1)
|
||||
#else
|
||||
# include <windows.h>
|
||||
# define LY_ATOMIC_INC_BARRIER(var) InterlockedExchangeAdd(&(var), 1)
|
||||
# define LY_ATOMIC_DEC_BARRIER(var) InterlockedExchangeAdd(&(var), -1)
|
||||
#endif
|
||||
|
||||
/** printf compiler attribute */
|
||||
#ifdef __GNUC__
|
||||
# define _FORMAT_PRINTF(FORM, ARGS) __attribute__((format (printf, FORM, ARGS)))
|
||||
#else
|
||||
# define _FORMAT_PRINTF(FORM, ARGS)
|
||||
#endif
|
||||
|
||||
/** Exporting symbols to a shared library and importing back afterwards
|
||||
*
|
||||
* - use LIBYANG_API_DECL to mark a declaration in the public header
|
||||
* - use LIBYANG_API_DEF to mark a definition (in the source code for the actual implementaiton)
|
||||
* */
|
||||
#ifdef _MSC_VER
|
||||
# ifndef STATIC
|
||||
# define LIBYANG_API_DEF __declspec(dllexport)
|
||||
# ifdef LIBYANG_BUILD
|
||||
# define LIBYANG_API_DECL __declspec(dllexport)
|
||||
# else
|
||||
# define LIBYANG_API_DECL __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
/*
|
||||
* If the compiler supports attribute to mark objects as hidden, mark all
|
||||
* objects as hidden and export only objects explicitly marked to be part of
|
||||
* the public API.
|
||||
*/
|
||||
# define LIBYANG_API_DEF __attribute__((visibility("default")))
|
||||
# define LIBYANG_API_DECL
|
||||
#endif
|
||||
|
||||
#endif /* LY_CONFIG_H_ */
|
125
src/lyb.c
Normal file
125
src/lyb.c
Normal file
|
@ -0,0 +1,125 @@
|
|||
/**
|
||||
* @file lyb.c
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief LYB format common functionality.
|
||||
*
|
||||
* Copyright (c) 2021 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "lyb.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "compat.h"
|
||||
#include "ly_common.h"
|
||||
#include "tree_schema.h"
|
||||
|
||||
/**
|
||||
* @brief Generate single hash for a schema node to be used for LYB data.
|
||||
*
|
||||
* @param[in] node Node to hash.
|
||||
* @param[in] collision_id Collision ID of the hash to generate.
|
||||
* @return Generated hash.
|
||||
*/
|
||||
static LYB_HASH
|
||||
lyb_generate_hash(const struct lysc_node *node, uint8_t collision_id)
|
||||
{
|
||||
const struct lys_module *mod = node->module;
|
||||
uint32_t full_hash;
|
||||
LYB_HASH hash;
|
||||
|
||||
/* generate full hash */
|
||||
full_hash = lyht_hash_multi(0, mod->name, strlen(mod->name));
|
||||
full_hash = lyht_hash_multi(full_hash, node->name, strlen(node->name));
|
||||
if (collision_id) {
|
||||
size_t ext_len;
|
||||
|
||||
if (collision_id > strlen(mod->name)) {
|
||||
/* fine, we will not hash more bytes, just use more bits from the hash than previously */
|
||||
ext_len = strlen(mod->name);
|
||||
} else {
|
||||
/* use one more byte from the module name than before */
|
||||
ext_len = collision_id;
|
||||
}
|
||||
full_hash = lyht_hash_multi(full_hash, mod->name, ext_len);
|
||||
}
|
||||
full_hash = lyht_hash_multi(full_hash, NULL, 0);
|
||||
|
||||
/* use the shortened hash */
|
||||
hash = full_hash & (LYB_HASH_MASK >> collision_id);
|
||||
/* add collision identificator */
|
||||
hash |= LYB_HASH_COLLISION_ID >> collision_id;
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
LYB_HASH
|
||||
lyb_get_hash(const struct lysc_node *node, uint8_t collision_id)
|
||||
{
|
||||
/* hashes must be cached */
|
||||
assert(node->hash[0]);
|
||||
|
||||
if (collision_id < LYS_NODE_HASH_COUNT) {
|
||||
/* read from cache */
|
||||
return node->hash[collision_id];
|
||||
}
|
||||
|
||||
/* generate */
|
||||
return lyb_generate_hash(node, collision_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Module DFS callback filling all cached hashes of a schema node.
|
||||
*/
|
||||
static LY_ERR
|
||||
lyb_cache_node_hash_cb(struct lysc_node *node, void *UNUSED(data), ly_bool *UNUSED(dfs_continue))
|
||||
{
|
||||
if (node->hash[0]) {
|
||||
/* already cached, stop the DFS */
|
||||
return LY_EEXIST;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < LYS_NODE_HASH_COUNT; ++i) {
|
||||
/* store the hash in the cache */
|
||||
node->hash[i] = lyb_generate_hash(node, i);
|
||||
}
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
lyb_cache_module_hash(const struct lys_module *mod)
|
||||
{
|
||||
/* LOCK */
|
||||
pthread_mutex_lock(&mod->ctx->lyb_hash_lock);
|
||||
|
||||
/* store all cached hashes for all the nodes */
|
||||
lysc_module_dfs_full(mod, lyb_cache_node_hash_cb, NULL);
|
||||
|
||||
/* UNLOCK */
|
||||
pthread_mutex_unlock(&mod->ctx->lyb_hash_lock);
|
||||
}
|
||||
|
||||
ly_bool
|
||||
lyb_has_schema_model(const struct lysc_node *node, const struct lys_module **models)
|
||||
{
|
||||
LY_ARRAY_COUNT_TYPE u;
|
||||
|
||||
LY_ARRAY_FOR(models, u) {
|
||||
if (node->module == models[u]) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
199
src/lyb.h
Normal file
199
src/lyb.h
Normal file
|
@ -0,0 +1,199 @@
|
|||
/**
|
||||
* @file lyb.h
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief Header for LYB format printer & parser
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef LY_LYB_H_
|
||||
#define LY_LYB_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "parser_internal.h"
|
||||
|
||||
struct ly_ctx;
|
||||
struct lysc_node;
|
||||
|
||||
/*
|
||||
* LYB format
|
||||
*
|
||||
* Unlike XML or JSON, it is binary format so most data are represented in similar way but in binary.
|
||||
* Some notable differences:
|
||||
*
|
||||
* - schema nodes are identified based on their hash instead of their string name. In case of collisions
|
||||
* an array of hashes is created with each next hash one bit shorter until a unique sequence of all these
|
||||
* hashes is found and then all of them are stored.
|
||||
*
|
||||
* - tree structure is represented as individual strictly bounded "siblings". Each "siblings" begins
|
||||
* with its metadata, which consist of 1) the whole "sibling" length in bytes and 2) number
|
||||
* of included metadata chunks of nested "siblings".
|
||||
*
|
||||
* - since length of a "sibling" is not known before it is printed, holes are first written and
|
||||
* after the "sibling" is printed, they are filled with actual valid metadata. As a consequence,
|
||||
* LYB data cannot be directly printed into streams!
|
||||
*
|
||||
* - data are preceded with information about all the used modules. It is needed because of
|
||||
* possible augments and deviations which must be known beforehand, otherwise schema hashes
|
||||
* could be matched to the wrong nodes.
|
||||
*
|
||||
* This is a short summary of the format:
|
||||
* @verbatim
|
||||
|
||||
sb = siblings_start
|
||||
se = siblings_end
|
||||
siblings = zero-LYB_SIZE_BYTES | (sb instance+ se)
|
||||
instance = node_type model hash node
|
||||
model = 16bit_zero | (model_name_length model_name revision)
|
||||
node = opaq | leaflist | list | any | inner | leaf
|
||||
opaq = opaq_data siblings
|
||||
leaflist = sb leaf+ se
|
||||
list = sb (node_header siblings)+ se
|
||||
any = node_header anydata_data
|
||||
inner = node_header siblings
|
||||
leaf = node_header term_value
|
||||
node_header = metadata node_flags
|
||||
|
||||
@endverbatim
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief LYB data node type
|
||||
*/
|
||||
enum lylyb_node_type {
|
||||
LYB_NODE_TOP, /**< top-level node */
|
||||
LYB_NODE_CHILD, /**< child node with a parent */
|
||||
LYB_NODE_OPAQ, /**< opaque node */
|
||||
LYB_NODE_EXT /**< nested extension data node */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief LYB format parser context
|
||||
*/
|
||||
struct lylyb_ctx {
|
||||
const struct ly_ctx *ctx;
|
||||
uint64_t line; /* current line */
|
||||
struct ly_in *in; /* input structure */
|
||||
|
||||
const struct lys_module **models;
|
||||
|
||||
struct lyd_lyb_sibling {
|
||||
size_t written;
|
||||
size_t position;
|
||||
uint16_t inner_chunks;
|
||||
} *siblings;
|
||||
LY_ARRAY_COUNT_TYPE sibling_size;
|
||||
|
||||
/* LYB printer only */
|
||||
struct lyd_lyb_sib_ht {
|
||||
struct lysc_node *first_sibling;
|
||||
struct ly_ht *ht;
|
||||
} *sib_hts;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Destructor for the lylyb_ctx structure
|
||||
*/
|
||||
void lyd_lyb_ctx_free(struct lyd_ctx *lydctx);
|
||||
|
||||
/* just a shortcut */
|
||||
#define LYB_LAST_SIBLING(lybctx) lybctx->siblings[LY_ARRAY_COUNT(lybctx->siblings) - 1]
|
||||
|
||||
/* struct lyd_lyb_sibling allocation step */
|
||||
#define LYB_SIBLING_STEP 4
|
||||
|
||||
/* current LYB format version */
|
||||
#define LYB_VERSION_NUM 0x05
|
||||
|
||||
/* LYB format version mask of the header byte */
|
||||
#define LYB_VERSION_MASK 0x0F
|
||||
|
||||
/**
|
||||
* LYB schema hash constants
|
||||
*
|
||||
* Hash is divided to collision ID and hash itself.
|
||||
*
|
||||
* @anchor collisionid
|
||||
*
|
||||
* First bits are collision ID until 1 is found. The rest is truncated 32b hash.
|
||||
* 1xxx xxxx - collision ID 0 (no collisions)
|
||||
* 01xx xxxx - collision ID 1 (collision ID 0 hash collided)
|
||||
* 001x xxxx - collision ID 2 ...
|
||||
*
|
||||
* When finding a match for a unique schema (siblings) hash (sequence of hashes with increasing collision ID), the highest
|
||||
* collision ID can be read from the last hash (LYB parser).
|
||||
*
|
||||
* To learn what is the highest collision ID of a hash that must be included in a unique schema (siblings) hash,
|
||||
* collisions with all the preceding sibling schema hashes must be checked (LYB printer).
|
||||
*/
|
||||
|
||||
/* Number of bits the whole hash will take (including hash collision ID) */
|
||||
#define LYB_HASH_BITS 8
|
||||
|
||||
/* Masking 32b hash (collision ID 0) */
|
||||
#define LYB_HASH_MASK 0x7f
|
||||
|
||||
/* Type for storing the whole hash (used only internally, publicly defined directly) */
|
||||
#define LYB_HASH uint8_t
|
||||
|
||||
/* Need to move this first >> collision number (from 0) to get collision ID hash part */
|
||||
#define LYB_HASH_COLLISION_ID 0x80
|
||||
|
||||
/* How many bytes are reserved for one data chunk SIZE (8B is maximum) */
|
||||
#define LYB_SIZE_BYTES 2
|
||||
|
||||
/* Maximum size that will be written into LYB_SIZE_BYTES (must be large enough) */
|
||||
#define LYB_SIZE_MAX UINT16_MAX
|
||||
|
||||
/* How many bytes are reserved for one data chunk inner chunk count */
|
||||
#define LYB_INCHUNK_BYTES 2
|
||||
|
||||
/* Maximum size that will be written into LYB_INCHUNK_BYTES (must be large enough) */
|
||||
#define LYB_INCHUNK_MAX UINT16_MAX
|
||||
|
||||
/* Just a helper macro */
|
||||
#define LYB_META_BYTES (LYB_INCHUNK_BYTES + LYB_SIZE_BYTES)
|
||||
|
||||
/* model revision as XXXX XXXX XXXX XXXX (2B) (year is offset from 2000)
|
||||
* YYYY YYYM MMMD DDDD */
|
||||
#define LYB_REV_YEAR_OFFSET 2000
|
||||
#define LYB_REV_YEAR_MASK 0xfe00U
|
||||
#define LYB_REV_YEAR_SHIFT 9
|
||||
#define LYB_REV_MONTH_MASK 0x01E0U
|
||||
#define LYB_REV_MONTH_SHIFT 5
|
||||
#define LYB_REV_DAY_MASK 0x001fU
|
||||
|
||||
/**
|
||||
* @brief Get single hash for a schema node to be used for LYB data. Read from cache, if possible.
|
||||
*
|
||||
* @param[in] node Node to hash.
|
||||
* @param[in] collision_id Collision ID of the hash to generate, see @ref collisionid.
|
||||
* @return Generated hash.
|
||||
*/
|
||||
LYB_HASH lyb_get_hash(const struct lysc_node *node, uint8_t collision_id);
|
||||
|
||||
/**
|
||||
* @brief Fill the hash cache of all the schema nodes of a module.
|
||||
*
|
||||
* @param[in] mod Module to process.
|
||||
*/
|
||||
void lyb_cache_module_hash(const struct lys_module *mod);
|
||||
|
||||
/**
|
||||
* @brief Check whether a node's module is in a module array.
|
||||
*
|
||||
* @param[in] node Node to check.
|
||||
* @param[in] models Modules in a sized array.
|
||||
* @return Boolean value whether @p node's module was found in the given @p models array.
|
||||
*/
|
||||
ly_bool lyb_has_schema_model(const struct lysc_node *node, const struct lys_module **models);
|
||||
|
||||
#endif /* LY_LYB_H_ */
|
788
src/out.c
Normal file
788
src/out.c
Normal file
|
@ -0,0 +1,788 @@
|
|||
/**
|
||||
* @file out.c
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @brief libyang output functions.
|
||||
*
|
||||
* Copyright (c) 2015 - 2020 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE /* asprintf, strdup */
|
||||
|
||||
#include "out.h"
|
||||
#include "out_internal.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "compat.h"
|
||||
#include "log.h"
|
||||
#include "ly_common.h"
|
||||
#include "metadata.h"
|
||||
#include "printer_data.h"
|
||||
#include "tree_data.h"
|
||||
#include "tree_schema.h"
|
||||
|
||||
/**
|
||||
* @brief Align the desired size to 1 KB.
|
||||
*/
|
||||
#define REALLOC_CHUNK(NEW_SIZE) \
|
||||
NEW_SIZE + (1024 - (NEW_SIZE % 1024))
|
||||
|
||||
LIBYANG_API_DEF ly_bool
|
||||
lyd_node_should_print(const struct lyd_node *node, uint32_t options)
|
||||
{
|
||||
const struct lyd_node *elem;
|
||||
|
||||
if (options & LYD_PRINT_WD_TRIM) {
|
||||
/* do not print default nodes */
|
||||
if (node->flags & LYD_DEFAULT) {
|
||||
/* implicit default node/NP container with only default nodes */
|
||||
return 0;
|
||||
} else if (node->schema && (node->schema->nodetype & LYD_NODE_TERM)) {
|
||||
if (lyd_is_default(node)) {
|
||||
/* explicit default node */
|
||||
return 0;
|
||||
}
|
||||
} else if (lysc_is_np_cont(node->schema)) {
|
||||
if (options & LYD_PRINT_KEEPEMPTYCONT) {
|
||||
/* explicit request to print, redundant to check */
|
||||
return 1;
|
||||
}
|
||||
|
||||
LY_LIST_FOR(lyd_child(node), elem) {
|
||||
if (lyd_node_should_print(elem, options)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* NP container without any printed children (such as other NP containers with only nodes set to their default values) */
|
||||
return 0;
|
||||
}
|
||||
} else if ((node->flags & LYD_DEFAULT) && (node->schema->nodetype == LYS_CONTAINER)) {
|
||||
if (options & LYD_PRINT_KEEPEMPTYCONT) {
|
||||
/* explicit request to print */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* avoid empty default containers */
|
||||
LYD_TREE_DFS_BEGIN(node, elem) {
|
||||
if ((elem != node) && lyd_node_should_print(elem, options)) {
|
||||
return 1;
|
||||
}
|
||||
assert(elem->flags & LYD_DEFAULT);
|
||||
LYD_TREE_DFS_END(node, elem)
|
||||
}
|
||||
return 0;
|
||||
} else if ((node->flags & LYD_DEFAULT) && !(options & LYD_PRINT_WD_MASK) && !(node->schema->flags & LYS_CONFIG_R)) {
|
||||
/* LYD_PRINT_WD_EXPLICIT, find out if this is some input/output */
|
||||
if (!(node->schema->flags & (LYS_IS_INPUT | LYS_IS_OUTPUT | LYS_IS_NOTIF)) && (node->schema->flags & LYS_CONFIG_W)) {
|
||||
/* print only if it contains status data in its subtree */
|
||||
LYD_TREE_DFS_BEGIN(node, elem) {
|
||||
if ((elem->schema->nodetype != LYS_CONTAINER) || (elem->schema->flags & LYS_PRESENCE)) {
|
||||
if (elem->schema->flags & LYS_CONFIG_R) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
LYD_TREE_DFS_END(node, elem)
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF ly_bool
|
||||
lyd_metadata_should_print(const struct lyd_meta *meta)
|
||||
{
|
||||
return !lyd_meta_is_internal(meta);
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_OUT_TYPE
|
||||
ly_out_type(const struct ly_out *out)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, out, LY_OUT_ERROR);
|
||||
return out->type;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
ly_out_new_clb(ly_write_clb writeclb, void *user_data, struct ly_out **out)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, out, writeclb, LY_EINVAL);
|
||||
|
||||
*out = calloc(1, sizeof **out);
|
||||
LY_CHECK_ERR_RET(!*out, LOGMEM(NULL), LY_EMEM);
|
||||
|
||||
(*out)->type = LY_OUT_CALLBACK;
|
||||
(*out)->method.clb.func = writeclb;
|
||||
(*out)->method.clb.arg = user_data;
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF ly_write_clb
|
||||
ly_out_clb(struct ly_out *out, ly_write_clb writeclb)
|
||||
{
|
||||
ly_write_clb prev_clb;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, out, out->type == LY_OUT_CALLBACK, NULL);
|
||||
|
||||
prev_clb = out->method.clb.func;
|
||||
|
||||
if (writeclb) {
|
||||
out->method.clb.func = writeclb;
|
||||
}
|
||||
|
||||
return prev_clb;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF void *
|
||||
ly_out_clb_arg(struct ly_out *out, void *arg)
|
||||
{
|
||||
void *prev_arg;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, out, out->type == LY_OUT_CALLBACK, NULL);
|
||||
|
||||
prev_arg = out->method.clb.arg;
|
||||
|
||||
if (arg) {
|
||||
out->method.clb.arg = arg;
|
||||
}
|
||||
|
||||
return prev_arg;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
ly_out_new_fd(int fd, struct ly_out **out)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, out, fd != -1, LY_EINVAL);
|
||||
|
||||
*out = calloc(1, sizeof **out);
|
||||
LY_CHECK_ERR_RET(!*out, LOGMEM(NULL), LY_EMEM);
|
||||
(*out)->type = LY_OUT_FD;
|
||||
(*out)->method.fd = fd;
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF int
|
||||
ly_out_fd(struct ly_out *out, int fd)
|
||||
{
|
||||
int prev_fd;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, out, out->type <= LY_OUT_FDSTREAM, -1);
|
||||
|
||||
if (out->type == LY_OUT_FDSTREAM) {
|
||||
prev_fd = out->method.fdstream.fd;
|
||||
} else { /* LY_OUT_FD */
|
||||
prev_fd = out->method.fd;
|
||||
}
|
||||
|
||||
if (fd != -1) {
|
||||
/* replace output stream */
|
||||
if (out->type == LY_OUT_FDSTREAM) {
|
||||
int streamfd;
|
||||
FILE *stream;
|
||||
|
||||
streamfd = dup(fd);
|
||||
if (streamfd < 0) {
|
||||
LOGERR(NULL, LY_ESYS, "Unable to duplicate provided file descriptor (%d) for printing the output (%s).", fd, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
stream = fdopen(streamfd, "a");
|
||||
if (!stream) {
|
||||
LOGERR(NULL, LY_ESYS, "Unable to open provided file descriptor (%d) for printing the output (%s).", fd, strerror(errno));
|
||||
close(streamfd);
|
||||
return -1;
|
||||
}
|
||||
/* close only the internally created stream, file descriptor is returned and supposed to be closed by the caller */
|
||||
fclose(out->method.fdstream.f);
|
||||
out->method.fdstream.f = stream;
|
||||
out->method.fdstream.fd = streamfd;
|
||||
} else { /* LY_OUT_FD */
|
||||
out->method.fd = fd;
|
||||
}
|
||||
}
|
||||
|
||||
return prev_fd;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
ly_out_new_file(FILE *f, struct ly_out **out)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, out, f, LY_EINVAL);
|
||||
|
||||
*out = calloc(1, sizeof **out);
|
||||
LY_CHECK_ERR_RET(!*out, LOGMEM(NULL), LY_EMEM);
|
||||
|
||||
(*out)->type = LY_OUT_FILE;
|
||||
(*out)->method.f = f;
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF FILE *
|
||||
ly_out_file(struct ly_out *out, FILE *f)
|
||||
{
|
||||
FILE *prev_f;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, out, out->type == LY_OUT_FILE, NULL);
|
||||
|
||||
prev_f = out->method.f;
|
||||
|
||||
if (f) {
|
||||
out->method.f = f;
|
||||
}
|
||||
|
||||
return prev_f;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
ly_out_new_memory(char **strp, size_t size, struct ly_out **out)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, out, strp, LY_EINVAL);
|
||||
|
||||
*out = calloc(1, sizeof **out);
|
||||
LY_CHECK_ERR_RET(!*out, LOGMEM(NULL), LY_EMEM);
|
||||
|
||||
(*out)->type = LY_OUT_MEMORY;
|
||||
(*out)->method.mem.buf = strp;
|
||||
if (!size) {
|
||||
/* buffer is supposed to be allocated */
|
||||
*strp = NULL;
|
||||
} else if (*strp) {
|
||||
/* there is already buffer to use */
|
||||
(*out)->method.mem.size = size;
|
||||
}
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
char *
|
||||
ly_out_memory(struct ly_out *out, char **strp, size_t size)
|
||||
{
|
||||
char *data;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, out, out->type == LY_OUT_MEMORY, NULL);
|
||||
|
||||
data = *out->method.mem.buf;
|
||||
|
||||
if (strp) {
|
||||
out->method.mem.buf = strp;
|
||||
out->method.mem.len = out->method.mem.size = 0;
|
||||
out->printed = 0;
|
||||
if (!size) {
|
||||
/* buffer is supposed to be allocated */
|
||||
*strp = NULL;
|
||||
} else if (*strp) {
|
||||
/* there is already buffer to use */
|
||||
out->method.mem.size = size;
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
ly_out_reset(struct ly_out *out)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, out, LY_EINVAL);
|
||||
|
||||
switch (out->type) {
|
||||
case LY_OUT_ERROR:
|
||||
LOGINT(NULL);
|
||||
return LY_EINT;
|
||||
case LY_OUT_FD:
|
||||
if ((lseek(out->method.fd, 0, SEEK_SET) == -1) && (errno != ESPIPE)) {
|
||||
LOGERR(NULL, LY_ESYS, "Seeking output file descriptor failed (%s).", strerror(errno));
|
||||
return LY_ESYS;
|
||||
}
|
||||
if ((errno != ESPIPE) && (ftruncate(out->method.fd, 0) == -1)) {
|
||||
LOGERR(NULL, LY_ESYS, "Truncating output file failed (%s).", strerror(errno));
|
||||
return LY_ESYS;
|
||||
}
|
||||
break;
|
||||
case LY_OUT_FDSTREAM:
|
||||
case LY_OUT_FILE:
|
||||
case LY_OUT_FILEPATH:
|
||||
if ((fseek(out->method.f, 0, SEEK_SET) == -1) && (errno != ESPIPE)) {
|
||||
LOGERR(NULL, LY_ESYS, "Seeking output file stream failed (%s).", strerror(errno));
|
||||
return LY_ESYS;
|
||||
}
|
||||
if ((errno != ESPIPE) && (ftruncate(fileno(out->method.f), 0) == -1)) {
|
||||
LOGERR(NULL, LY_ESYS, "Truncating output file failed (%s).", strerror(errno));
|
||||
return LY_ESYS;
|
||||
}
|
||||
break;
|
||||
case LY_OUT_MEMORY:
|
||||
if (out->method.mem.buf && *out->method.mem.buf) {
|
||||
memset(*out->method.mem.buf, 0, out->method.mem.len);
|
||||
}
|
||||
out->printed = 0;
|
||||
out->method.mem.len = 0;
|
||||
break;
|
||||
case LY_OUT_CALLBACK:
|
||||
/* nothing to do (not seekable) */
|
||||
break;
|
||||
}
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
ly_out_new_filepath(const char *filepath, struct ly_out **out)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, out, filepath, LY_EINVAL);
|
||||
|
||||
*out = calloc(1, sizeof **out);
|
||||
LY_CHECK_ERR_RET(!*out, LOGMEM(NULL), LY_EMEM);
|
||||
|
||||
(*out)->type = LY_OUT_FILEPATH;
|
||||
(*out)->method.fpath.f = fopen(filepath, "wb");
|
||||
if (!(*out)->method.fpath.f) {
|
||||
LOGERR(NULL, LY_ESYS, "Failed to open file \"%s\" (%s).", filepath, strerror(errno));
|
||||
free(*out);
|
||||
*out = NULL;
|
||||
return LY_ESYS;
|
||||
}
|
||||
(*out)->method.fpath.filepath = strdup(filepath);
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF const char *
|
||||
ly_out_filepath(struct ly_out *out, const char *filepath)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, out, out->type == LY_OUT_FILEPATH, filepath ? NULL : ((void *)-1));
|
||||
|
||||
if (!filepath) {
|
||||
return out->method.fpath.filepath;
|
||||
}
|
||||
|
||||
/* replace filepath */
|
||||
f = out->method.fpath.f;
|
||||
out->method.fpath.f = fopen(filepath, "wb");
|
||||
if (!out->method.fpath.f) {
|
||||
LOGERR(NULL, LY_ESYS, "Failed to open file \"%s\" (%s).", filepath, strerror(errno));
|
||||
out->method.fpath.f = f;
|
||||
return (void *)-1;
|
||||
}
|
||||
fclose(f);
|
||||
free(out->method.fpath.filepath);
|
||||
out->method.fpath.filepath = strdup(filepath);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF void
|
||||
ly_out_free(struct ly_out *out, void (*clb_arg_destructor)(void *arg), ly_bool destroy)
|
||||
{
|
||||
if (!out) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (out->type) {
|
||||
case LY_OUT_CALLBACK:
|
||||
if (clb_arg_destructor) {
|
||||
clb_arg_destructor(out->method.clb.arg);
|
||||
}
|
||||
break;
|
||||
case LY_OUT_FDSTREAM:
|
||||
fclose(out->method.fdstream.f);
|
||||
if (destroy) {
|
||||
close(out->method.fdstream.fd);
|
||||
}
|
||||
break;
|
||||
case LY_OUT_FD:
|
||||
if (destroy) {
|
||||
close(out->method.fd);
|
||||
}
|
||||
break;
|
||||
case LY_OUT_FILE:
|
||||
if (destroy) {
|
||||
fclose(out->method.f);
|
||||
}
|
||||
break;
|
||||
case LY_OUT_MEMORY:
|
||||
if (destroy) {
|
||||
free(*out->method.mem.buf);
|
||||
}
|
||||
break;
|
||||
case LY_OUT_FILEPATH:
|
||||
free(out->method.fpath.filepath);
|
||||
fclose(out->method.fpath.f);
|
||||
break;
|
||||
case LY_OUT_ERROR:
|
||||
LOGINT(NULL);
|
||||
}
|
||||
|
||||
free(out->buffered);
|
||||
free(out);
|
||||
}
|
||||
|
||||
static LY_ERR
|
||||
ly_vprint_(struct ly_out *out, const char *format, va_list ap)
|
||||
{
|
||||
LY_ERR ret;
|
||||
int written = 0;
|
||||
char *msg = NULL;
|
||||
|
||||
switch (out->type) {
|
||||
case LY_OUT_FD:
|
||||
written = vdprintf(out->method.fd, format, ap);
|
||||
break;
|
||||
case LY_OUT_FDSTREAM:
|
||||
case LY_OUT_FILEPATH:
|
||||
case LY_OUT_FILE:
|
||||
written = vfprintf(out->method.f, format, ap);
|
||||
break;
|
||||
case LY_OUT_MEMORY:
|
||||
if ((written = vasprintf(&msg, format, ap)) < 0) {
|
||||
break;
|
||||
}
|
||||
if (out->method.mem.len + written + 1 > out->method.mem.size) {
|
||||
*out->method.mem.buf = ly_realloc(*out->method.mem.buf, out->method.mem.len + written + 1);
|
||||
if (!*out->method.mem.buf) {
|
||||
out->method.mem.len = 0;
|
||||
out->method.mem.size = 0;
|
||||
free(msg);
|
||||
LOGMEM(NULL);
|
||||
return LY_EMEM;
|
||||
}
|
||||
out->method.mem.size = out->method.mem.len + written + 1;
|
||||
}
|
||||
if (written) {
|
||||
memcpy(&(*out->method.mem.buf)[out->method.mem.len], msg, written);
|
||||
}
|
||||
out->method.mem.len += written;
|
||||
(*out->method.mem.buf)[out->method.mem.len] = '\0';
|
||||
free(msg);
|
||||
break;
|
||||
case LY_OUT_CALLBACK:
|
||||
if ((written = vasprintf(&msg, format, ap)) < 0) {
|
||||
break;
|
||||
}
|
||||
written = out->method.clb.func(out->method.clb.arg, msg, written);
|
||||
free(msg);
|
||||
break;
|
||||
case LY_OUT_ERROR:
|
||||
LOGINT(NULL);
|
||||
return LY_EINT;
|
||||
}
|
||||
|
||||
if (written < 0) {
|
||||
LOGERR(NULL, LY_ESYS, "%s: writing data failed (%s).", __func__, strerror(errno));
|
||||
written = 0;
|
||||
ret = LY_ESYS;
|
||||
} else {
|
||||
if (out->type == LY_OUT_FDSTREAM) {
|
||||
/* move the original file descriptor to the end of the output file */
|
||||
lseek(out->method.fdstream.fd, 0, SEEK_END);
|
||||
}
|
||||
ret = LY_SUCCESS;
|
||||
}
|
||||
|
||||
out->printed += written;
|
||||
out->func_printed += written;
|
||||
return ret;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
ly_print_(struct ly_out *out, const char *format, ...)
|
||||
{
|
||||
LY_ERR ret;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
ret = ly_vprint_(out, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
ly_print(struct ly_out *out, const char *format, ...)
|
||||
{
|
||||
LY_ERR ret;
|
||||
va_list ap;
|
||||
|
||||
out->func_printed = 0;
|
||||
|
||||
va_start(ap, format);
|
||||
ret = ly_vprint_(out, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF void
|
||||
ly_print_flush(struct ly_out *out)
|
||||
{
|
||||
switch (out->type) {
|
||||
case LY_OUT_FDSTREAM:
|
||||
/* move the original file descriptor to the end of the output file */
|
||||
lseek(out->method.fdstream.fd, 0, SEEK_END);
|
||||
fflush(out->method.fdstream.f);
|
||||
break;
|
||||
case LY_OUT_FILEPATH:
|
||||
case LY_OUT_FILE:
|
||||
fflush(out->method.f);
|
||||
break;
|
||||
case LY_OUT_FD:
|
||||
fsync(out->method.fd);
|
||||
break;
|
||||
case LY_OUT_MEMORY:
|
||||
case LY_OUT_CALLBACK:
|
||||
/* nothing to do */
|
||||
break;
|
||||
case LY_OUT_ERROR:
|
||||
LOGINT(NULL);
|
||||
}
|
||||
|
||||
free(out->buffered);
|
||||
out->buf_size = out->buf_len = 0;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
ly_write_(struct ly_out *out, const char *buf, size_t len)
|
||||
{
|
||||
LY_ERR ret = LY_SUCCESS;
|
||||
size_t written = 0, new_mem_size;
|
||||
|
||||
if (out->hole_count) {
|
||||
/* we are buffering data after a hole */
|
||||
if (out->buf_len + len > out->buf_size) {
|
||||
out->buffered = ly_realloc(out->buffered, out->buf_len + len);
|
||||
if (!out->buffered) {
|
||||
out->buf_len = 0;
|
||||
out->buf_size = 0;
|
||||
LOGMEM(NULL);
|
||||
return LY_EMEM;
|
||||
}
|
||||
out->buf_size = out->buf_len + len;
|
||||
}
|
||||
|
||||
if (len) {
|
||||
memcpy(&out->buffered[out->buf_len], buf, len);
|
||||
}
|
||||
out->buf_len += len;
|
||||
|
||||
out->printed += len;
|
||||
out->func_printed += len;
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
repeat:
|
||||
switch (out->type) {
|
||||
case LY_OUT_MEMORY:
|
||||
new_mem_size = out->method.mem.len + len + 1;
|
||||
if (new_mem_size > out->method.mem.size) {
|
||||
new_mem_size = REALLOC_CHUNK(new_mem_size);
|
||||
*out->method.mem.buf = ly_realloc(*out->method.mem.buf, new_mem_size);
|
||||
if (!*out->method.mem.buf) {
|
||||
out->method.mem.len = 0;
|
||||
out->method.mem.size = 0;
|
||||
LOGMEM(NULL);
|
||||
return LY_EMEM;
|
||||
}
|
||||
out->method.mem.size = new_mem_size;
|
||||
}
|
||||
if (len) {
|
||||
memcpy(&(*out->method.mem.buf)[out->method.mem.len], buf, len);
|
||||
}
|
||||
out->method.mem.len += len;
|
||||
(*out->method.mem.buf)[out->method.mem.len] = '\0';
|
||||
|
||||
written = len;
|
||||
break;
|
||||
case LY_OUT_FD: {
|
||||
ssize_t r;
|
||||
|
||||
r = write(out->method.fd, buf, len);
|
||||
if (r < 0) {
|
||||
ret = LY_ESYS;
|
||||
} else {
|
||||
written = (size_t)r;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LY_OUT_FDSTREAM:
|
||||
case LY_OUT_FILEPATH:
|
||||
case LY_OUT_FILE:
|
||||
written = fwrite(buf, sizeof *buf, len, out->method.f);
|
||||
if (written != len) {
|
||||
ret = LY_ESYS;
|
||||
}
|
||||
break;
|
||||
case LY_OUT_CALLBACK: {
|
||||
ssize_t r;
|
||||
|
||||
r = out->method.clb.func(out->method.clb.arg, buf, len);
|
||||
if (r < 0) {
|
||||
ret = LY_ESYS;
|
||||
} else {
|
||||
written = (size_t)r;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LY_OUT_ERROR:
|
||||
LOGINT(NULL);
|
||||
return LY_EINT;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
|
||||
ret = LY_SUCCESS;
|
||||
goto repeat;
|
||||
}
|
||||
LOGERR(NULL, LY_ESYS, "%s: writing data failed (%s).", __func__, strerror(errno));
|
||||
written = 0;
|
||||
} else if (written != len) {
|
||||
LOGERR(NULL, LY_ESYS, "%s: writing data failed (unable to write %" PRIu32 " from %" PRIu32 " data).", __func__,
|
||||
(uint32_t)(len - written), (uint32_t)len);
|
||||
ret = LY_ESYS;
|
||||
} else {
|
||||
if (out->type == LY_OUT_FDSTREAM) {
|
||||
/* move the original file descriptor to the end of the output file */
|
||||
lseek(out->method.fdstream.fd, 0, SEEK_END);
|
||||
}
|
||||
ret = LY_SUCCESS;
|
||||
}
|
||||
|
||||
out->printed += written;
|
||||
out->func_printed += written;
|
||||
return ret;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
ly_write(struct ly_out *out, const char *buf, size_t len)
|
||||
{
|
||||
out->func_printed = 0;
|
||||
|
||||
return ly_write_(out, buf, len);
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF size_t
|
||||
ly_out_printed(const struct ly_out *out)
|
||||
{
|
||||
return out->func_printed;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
ly_write_skip(struct ly_out *out, size_t count, size_t *position)
|
||||
{
|
||||
switch (out->type) {
|
||||
case LY_OUT_MEMORY:
|
||||
if (out->method.mem.len + count > out->method.mem.size) {
|
||||
*out->method.mem.buf = ly_realloc(*out->method.mem.buf, out->method.mem.len + count);
|
||||
if (!(*out->method.mem.buf)) {
|
||||
out->method.mem.len = 0;
|
||||
out->method.mem.size = 0;
|
||||
LOGMEM(NULL);
|
||||
return LY_EMEM;
|
||||
}
|
||||
out->method.mem.size = out->method.mem.len + count;
|
||||
}
|
||||
|
||||
/* save the current position */
|
||||
*position = out->method.mem.len;
|
||||
|
||||
/* skip the memory */
|
||||
out->method.mem.len += count;
|
||||
break;
|
||||
case LY_OUT_FD:
|
||||
case LY_OUT_FDSTREAM:
|
||||
case LY_OUT_FILEPATH:
|
||||
case LY_OUT_FILE:
|
||||
case LY_OUT_CALLBACK:
|
||||
/* buffer the hole */
|
||||
if (out->buf_len + count > out->buf_size) {
|
||||
out->buffered = ly_realloc(out->buffered, out->buf_len + count);
|
||||
if (!out->buffered) {
|
||||
out->buf_len = 0;
|
||||
out->buf_size = 0;
|
||||
LOGMEM(NULL);
|
||||
return LY_EMEM;
|
||||
}
|
||||
out->buf_size = out->buf_len + count;
|
||||
}
|
||||
|
||||
/* save the current position */
|
||||
*position = out->buf_len;
|
||||
|
||||
/* skip the memory */
|
||||
out->buf_len += count;
|
||||
|
||||
/* increase hole counter */
|
||||
++out->hole_count;
|
||||
break;
|
||||
case LY_OUT_ERROR:
|
||||
LOGINT(NULL);
|
||||
return LY_EINT;
|
||||
}
|
||||
|
||||
/* update printed bytes counter despite we actually printed just a hole */
|
||||
out->printed += count;
|
||||
out->func_printed += count;
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
ly_write_skipped(struct ly_out *out, size_t position, const char *buf, size_t count)
|
||||
{
|
||||
LY_ERR ret = LY_SUCCESS;
|
||||
|
||||
assert(count);
|
||||
|
||||
switch (out->type) {
|
||||
case LY_OUT_MEMORY:
|
||||
/* write */
|
||||
memcpy(&(*out->method.mem.buf)[position], buf, count);
|
||||
break;
|
||||
case LY_OUT_FD:
|
||||
case LY_OUT_FDSTREAM:
|
||||
case LY_OUT_FILEPATH:
|
||||
case LY_OUT_FILE:
|
||||
case LY_OUT_CALLBACK:
|
||||
if (out->buf_len < position + count) {
|
||||
LOGMEM(NULL);
|
||||
return LY_EMEM;
|
||||
}
|
||||
|
||||
/* write into the hole */
|
||||
memcpy(&out->buffered[position], buf, count);
|
||||
|
||||
/* decrease hole counter */
|
||||
--out->hole_count;
|
||||
|
||||
if (!out->hole_count) {
|
||||
/* all holes filled, we can write the buffer,
|
||||
* printed bytes counter is updated by ly_write_() */
|
||||
ret = ly_write_(out, out->buffered, out->buf_len);
|
||||
out->buf_len = 0;
|
||||
}
|
||||
break;
|
||||
case LY_OUT_ERROR:
|
||||
LOGINT(NULL);
|
||||
return LY_EINT;
|
||||
}
|
||||
|
||||
if (out->type == LY_OUT_FILEPATH) {
|
||||
/* move the original file descriptor to the end of the output file */
|
||||
lseek(out->method.fdstream.fd, 0, SEEK_END);
|
||||
}
|
||||
return ret;
|
||||
}
|
307
src/out.h
Normal file
307
src/out.h
Normal file
|
@ -0,0 +1,307 @@
|
|||
/**
|
||||
* @file out.h
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @brief libyang output structures and functions
|
||||
*
|
||||
* Copyright (c) 2015-2020 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef LY_OUT_H_
|
||||
#define LY_OUT_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef _MSC_VER
|
||||
# define ssize_t SSIZE_T
|
||||
#endif
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @page howtoOutput Output Processing
|
||||
*
|
||||
* libyang provides a mechanism to generalize work with the outputs (and [inputs](@ref howtoInput)) of
|
||||
* the different types. The ::ly_out handler can be created providing necessary information connected with the specific
|
||||
* output type and then used throughout the printers functions. The API allows to combine output from libyang (data or schema)
|
||||
* printers and output directly provided by the caller (via ::ly_print() or ::ly_write()).
|
||||
*
|
||||
* Using a generic output handler avoids need to have a set of functions for each printer functionality and results in simpler API.
|
||||
*
|
||||
* The API allows to alter the target of the data behind the handler by another target (of the same type). Also resetting
|
||||
* a seekable output is possible with ::ly_out_reset() to re-write the output.
|
||||
*
|
||||
* @note
|
||||
* This mechanism was introduced in libyang 2.0. To simplify transition from libyang 1.0 to version 2.0 and also for
|
||||
* some simple use case where using the output handler would be an overkill, there are some basic printer functions
|
||||
* that do not require output handler. But remember, that functionality of these function can be limited in particular cases
|
||||
* in contrast to the functions using output handlers.
|
||||
*
|
||||
* Functions List
|
||||
* --------------
|
||||
* - ::ly_out_new_clb()
|
||||
* - ::ly_out_new_fd()
|
||||
* - ::ly_out_new_file()
|
||||
* - ::ly_out_new_filepath()
|
||||
* - ::ly_out_new_memory()
|
||||
*
|
||||
* - ::ly_out_clb()
|
||||
* - ::ly_out_clb_arg()
|
||||
* - ::ly_out_fd()
|
||||
* - ::ly_out_file()
|
||||
* - ::ly_out_filepath()
|
||||
* - ::ly_out_memory()
|
||||
*
|
||||
* - ::ly_out_type()
|
||||
* - ::ly_out_printed()
|
||||
*
|
||||
* - ::ly_out_reset()
|
||||
* - ::ly_out_free()
|
||||
*
|
||||
* - ::ly_print()
|
||||
* - ::ly_print_flush()
|
||||
* - ::ly_write()
|
||||
*
|
||||
* libyang Printers List
|
||||
* --------------------
|
||||
* - @subpage howtoSchemaPrinters
|
||||
* - @subpage howtoDataPrinters
|
||||
*/
|
||||
|
||||
/**
|
||||
* @struct ly_out
|
||||
* @brief Printer output structure specifying where the data are printed.
|
||||
*/
|
||||
struct ly_out;
|
||||
|
||||
/**
|
||||
* @brief Common value for data as well as schema printers to avoid formatting indentations and new lines
|
||||
*/
|
||||
#define LY_PRINT_SHRINK 0x02
|
||||
|
||||
/**
|
||||
* @brief Types of the printer's output
|
||||
*/
|
||||
typedef enum LY_OUT_TYPE {
|
||||
LY_OUT_ERROR = -1, /**< error value to indicate failure of the functions returning LY_OUT_TYPE */
|
||||
LY_OUT_FD, /**< file descriptor printer */
|
||||
LY_OUT_FDSTREAM, /**< internal replacement for LY_OUT_FD in case vdprintf() is not available */
|
||||
LY_OUT_FILE, /**< FILE stream printer */
|
||||
LY_OUT_FILEPATH, /**< filepath printer */
|
||||
LY_OUT_MEMORY, /**< memory printer */
|
||||
LY_OUT_CALLBACK /**< callback printer */
|
||||
} LY_OUT_TYPE;
|
||||
|
||||
/**
|
||||
* @brief Get output type of the printer handler.
|
||||
*
|
||||
* @param[in] out Printer handler.
|
||||
* @return Type of the printer's output.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_OUT_TYPE ly_out_type(const struct ly_out *out);
|
||||
|
||||
/**
|
||||
* @brief Reset the output medium to write from its beginning, so the following printer function will rewrite the current data
|
||||
* instead of appending.
|
||||
*
|
||||
* Note that in case the underlying output is not seekable (stream referring a pipe/FIFO/socket or the callback output type),
|
||||
* nothing actually happens despite the function succeeds. Also note that the medium is not returned to the state it was when
|
||||
* the handler was created. For example, file is seeked into the offset zero and truncated, the content from the time it was opened with
|
||||
* ::ly_out_new_file() is not restored.
|
||||
*
|
||||
* @param[in] out Printer handler.
|
||||
* @return LY_SUCCESS in case of success
|
||||
* @return LY_ESYS in case of failure
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_out_reset(struct ly_out *out);
|
||||
|
||||
/**
|
||||
* @brief Generic write callback for data printed by libyang.
|
||||
*
|
||||
* @param[in] user_data Optional caller-specific argument.
|
||||
* @param[in] buf Data to write.
|
||||
* @param[in] count Number of bytes to write.
|
||||
* @return Number of printed bytes.
|
||||
* @return Negative value in case of error.
|
||||
*/
|
||||
typedef ssize_t (*ly_write_clb)(void *user_data, const void *buf, size_t count);
|
||||
|
||||
/**
|
||||
* @brief Create printer handler using callback printer function.
|
||||
*
|
||||
* @param[in] writeclb Pointer to the printer callback function writing the data (see write(2)).
|
||||
* @param[in] user_data Optional caller-specific argument to be passed to the @p writeclb callback.
|
||||
* @param[out] out Created printer handler supposed to be passed to different ly*_print() functions.
|
||||
* @return LY_SUCCESS in case of success
|
||||
* @return LY_EMEM in case allocating the @p out handler fails.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_out_new_clb(ly_write_clb writeclb, void *user_data, struct ly_out **out);
|
||||
|
||||
/**
|
||||
* @brief Get or reset callback function associated with a callback printer handler.
|
||||
*
|
||||
* @param[in] out Printer handler.
|
||||
* @param[in] writeclb Optional argument providing a new printer callback function for the handler. If NULL, only the current
|
||||
* printer callback is returned.
|
||||
* @return Previous printer callback.
|
||||
*/
|
||||
LIBYANG_API_DECL ly_write_clb ly_out_clb(struct ly_out *out, ly_write_clb writeclb);
|
||||
|
||||
/**
|
||||
* @brief Get or reset callback function's argument associated with a callback printer handler.
|
||||
*
|
||||
* @param[in] out Printer handler.
|
||||
* @param[in] arg caller-specific argument to be passed to the callback function associated with the printer handler.
|
||||
* If NULL, only the current file descriptor value is returned.
|
||||
* @return The previous callback argument.
|
||||
*/
|
||||
LIBYANG_API_DECL void *ly_out_clb_arg(struct ly_out *out, void *arg);
|
||||
|
||||
/**
|
||||
* @brief Create printer handler using file descriptor.
|
||||
*
|
||||
* @param[in] fd File descriptor to use.
|
||||
* @param[out] out Created printer handler supposed to be passed to different ly*_print() functions.
|
||||
* @return LY_SUCCESS in case of success
|
||||
* @return LY_ERR value in case of failure.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_out_new_fd(int fd, struct ly_out **out);
|
||||
|
||||
/**
|
||||
* @brief Get or reset file descriptor printer handler.
|
||||
*
|
||||
* @param[in] out Printer handler.
|
||||
* @param[in] fd Optional value of a new file descriptor for the handler. If -1, only the current file descriptor value is returned.
|
||||
* @return Previous value of the file descriptor. Note that caller is responsible for closing the returned file descriptor in case of setting new descriptor @p fd.
|
||||
* @return -1 in case of error when setting up the new file descriptor.
|
||||
*/
|
||||
LIBYANG_API_DECL int ly_out_fd(struct ly_out *out, int fd);
|
||||
|
||||
/**
|
||||
* @brief Create printer handler using file stream.
|
||||
*
|
||||
* @param[in] f File stream to use.
|
||||
* @param[out] out Created printer handler supposed to be passed to different ly*_print() functions.
|
||||
* @return LY_SUCCESS in case of success
|
||||
* @return LY_ERR value in case of failure.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_out_new_file(FILE *f, struct ly_out **out);
|
||||
|
||||
/**
|
||||
* @brief Get or reset file stream printer handler.
|
||||
*
|
||||
* @param[in] out Printer handler.
|
||||
* @param[in] f Optional new file stream for the handler. If NULL, only the current file stream is returned.
|
||||
* @return Previous file stream of the handler. Note that caller is responsible for closing the returned stream in case of setting new stream @p f.
|
||||
*/
|
||||
LIBYANG_API_DECL FILE *ly_out_file(struct ly_out *out, FILE *f);
|
||||
|
||||
/**
|
||||
* @brief Create printer handler using memory to dump data.
|
||||
*
|
||||
* @param[in] strp Pointer to store the resulting data. If it points to a pointer to an allocated buffer and
|
||||
* @p size of the buffer is set, the buffer is used (and extended if needed) to store the printed data.
|
||||
* @param[in] size Size of the buffer provided via @p strp. In case it is 0, the buffer for the printed data
|
||||
* is newly allocated even if @p strp points to a pointer to an existing buffer.
|
||||
* @param[out] out Created printer handler supposed to be passed to different ly*_print() functions.
|
||||
* @return LY_SUCCESS in case of success
|
||||
* @return LY_ERR value in case of failure.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_out_new_memory(char **strp, size_t size, struct ly_out **out);
|
||||
|
||||
/**
|
||||
* @brief Get or change memory where the data are dumped.
|
||||
*
|
||||
* @param[in] out Printer handler.
|
||||
* @param[in] strp Optional new string pointer to store the resulting data, same rules as in ::ly_out_new_memory() are applied.
|
||||
* @param[in] size Size of the buffer provided via @p strp. In case it is 0, the buffer for the printed data
|
||||
* is newly allocated even if @p strp points to a pointer to an existing buffer. In case the @p strp is NULL, this
|
||||
* parameter is ignored.
|
||||
* @return Previous dumped data. Note that the caller is responsible to free the data in case of changing string pointer @p strp.
|
||||
*/
|
||||
LIBYANG_API_DECL char *ly_out_memory(struct ly_out *out, char **strp, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Create printer handler file of the given filename.
|
||||
*
|
||||
* @param[in] filepath Path of the file where to write data.
|
||||
* @param[out] out Created printer handler supposed to be passed to different ly*_print() functions.
|
||||
* @return NULL in case of error.
|
||||
* @return Created printer handler supposed to be passed to different ly*_print_*() functions.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_out_new_filepath(const char *filepath, struct ly_out **out);
|
||||
|
||||
/**
|
||||
* @brief Get or change the filepath of the file where the printer prints the data.
|
||||
*
|
||||
* Note that in case of changing the filepath, the current file is closed and a new one is
|
||||
* created/opened instead of renaming the previous file. Also note that the previous filepath
|
||||
* string is returned only in case of not changing it's value.
|
||||
*
|
||||
* @param[in] out Printer handler.
|
||||
* @param[in] filepath Optional new filepath for the handler. If and only if NULL, the current filepath string is returned.
|
||||
* @return Previous filepath string in case the @p filepath argument is NULL.
|
||||
* @return NULL if changing filepath succeeds and ((void *)-1) otherwise.
|
||||
*/
|
||||
LIBYANG_API_DECL const char *ly_out_filepath(struct ly_out *out, const char *filepath);
|
||||
|
||||
/**
|
||||
* @brief Generic printer of the given format string into the specified output.
|
||||
*
|
||||
* Alternatively, ::ly_write() can be used.
|
||||
*
|
||||
* @param[in] out Output specification.
|
||||
* @param[in] format Format string to be printed.
|
||||
* @return LY_ERR value, get number of the printed bytes using ::ly_out_printed.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_print(struct ly_out *out, const char *format, ...);
|
||||
|
||||
/**
|
||||
* @brief Flush the output from any internal buffers and clean any auxiliary data.
|
||||
* @param[in] out Output specification.
|
||||
*/
|
||||
LIBYANG_API_DECL void ly_print_flush(struct ly_out *out);
|
||||
|
||||
/**
|
||||
* @brief Generic printer of the given string buffer into the specified output.
|
||||
*
|
||||
* Alternatively, ::ly_print() can be used.
|
||||
*
|
||||
* @param[in] out Output specification.
|
||||
* @param[in] buf Memory buffer with the data to print.
|
||||
* @param[in] len Length of the data to print in the @p buf.
|
||||
* @return LY_ERR value, get number of the printed bytes using ::ly_out_printed.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR ly_write(struct ly_out *out, const char *buf, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Get the number of printed bytes by the last function.
|
||||
*
|
||||
* @param[in] out Out structure used.
|
||||
* @return Number of printed bytes.
|
||||
*/
|
||||
LIBYANG_API_DECL size_t ly_out_printed(const struct ly_out *out);
|
||||
|
||||
/**
|
||||
* @brief Free the printer handler.
|
||||
* @param[in] out Printer handler to free.
|
||||
* @param[in] clb_arg_destructor Freeing function for printer callback (LY_OUT_CALLBACK) argument.
|
||||
* @param[in] destroy Flag to free allocated buffer (for LY_OUT_MEMORY) or to
|
||||
* close stream/file descriptor (for LY_OUT_FD, LY_OUT_FDSTREAM and LY_OUT_FILE)
|
||||
*/
|
||||
LIBYANG_API_DECL void ly_out_free(struct ly_out *out, void (*clb_arg_destructor)(void *arg), ly_bool destroy);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LY_OUT_H_ */
|
110
src/out_internal.h
Normal file
110
src/out_internal.h
Normal file
|
@ -0,0 +1,110 @@
|
|||
/**
|
||||
* @file out_internal.h
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @brief Internal structures and functions for libyang
|
||||
*
|
||||
* Copyright (c) 2015-2020 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef LY_OUT_INTERNAL_H_
|
||||
#define LY_OUT_INTERNAL_H_
|
||||
|
||||
#include "out.h"
|
||||
|
||||
struct lyd_node;
|
||||
|
||||
/**
|
||||
* @brief Printer output structure specifying where the data are printed.
|
||||
*/
|
||||
struct ly_out {
|
||||
LY_OUT_TYPE type; /**< type of the output to select the output method */
|
||||
|
||||
union {
|
||||
int fd; /**< file descriptor for LY_OUT_FD type */
|
||||
FILE *f; /**< file structure for LY_OUT_FILE, LY_OUT_FDSTREAM and LY_OUT_FILEPATH types */
|
||||
|
||||
struct {
|
||||
FILE *f; /**< file stream from the original file descriptor, variable is mapped to the LY_OUT_FILE's f */
|
||||
int fd; /**< original file descriptor, which was not used directly because of missing vdprintf() */
|
||||
} fdstream; /**< structure for LY_OUT_FDSTREAM type, which is LY_OUT_FD when vdprintf() is missing */
|
||||
struct {
|
||||
FILE *f; /**< file structure for LY_OUT_FILEPATH, variable is mapped to the LY_OUT_FILE's f */
|
||||
char *filepath; /**< stored original filepath */
|
||||
} fpath; /**< filepath structure for LY_OUT_FILEPATH */
|
||||
struct {
|
||||
char **buf; /**< storage for the pointer to the memory buffer to store the output */
|
||||
size_t len; /**< number of used bytes in the buffer */
|
||||
size_t size; /**< allocated size of the buffer */
|
||||
} mem; /**< memory buffer information for LY_OUT_MEMORY type */
|
||||
struct {
|
||||
ssize_t (*func)(void *arg, const void *buf, size_t count); /**< callback function */
|
||||
void *arg; /**< optional argument for the callback function */
|
||||
} clb; /**< printer callback for LY_OUT_CALLBACK type */
|
||||
} method; /**< type-specific information about the output */
|
||||
|
||||
/* LYB only */
|
||||
char *buffered; /**< additional buffer for holes */
|
||||
size_t buf_len; /**< number of used bytes in the additional buffer for holes */
|
||||
size_t buf_size; /**< allocated size of the buffer for holes */
|
||||
size_t hole_count; /**< hole counter */
|
||||
|
||||
size_t printed; /**< Total number of printed bytes */
|
||||
size_t func_printed; /**< Number of bytes printed by the last function */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Generic printer of the given format string into the specified output.
|
||||
*
|
||||
* Does not reset printed bytes. Adds to printed bytes.
|
||||
*
|
||||
* @param[in] out Output specification.
|
||||
* @param[in] format Format string to be printed.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
LY_ERR ly_print_(struct ly_out *out, const char *format, ...);
|
||||
|
||||
/**
|
||||
* @brief Generic printer of the given string buffer into the specified output.
|
||||
*
|
||||
* Does not reset printed bytes. Adds to printed bytes.
|
||||
*
|
||||
* @param[in] out Output specification.
|
||||
* @param[in] buf Memory buffer with the data to print.
|
||||
* @param[in] len Length of the data to print in the @p buf.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
LY_ERR ly_write_(struct ly_out *out, const char *buf, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Create a hole in the output data that will be filled later.
|
||||
*
|
||||
* Adds printed bytes.
|
||||
*
|
||||
* @param[in] out Output specification.
|
||||
* @param[in] len Length of the created hole.
|
||||
* @param[out] position Position of the hole, value must be later provided to the ::ly_write_skipped() call.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
LY_ERR ly_write_skip(struct ly_out *out, size_t len, size_t *position);
|
||||
|
||||
/**
|
||||
* @brief Write data into the hole at given position.
|
||||
*
|
||||
* Does not change printed bytes.
|
||||
*
|
||||
* @param[in] out Output specification.
|
||||
* @param[in] position Position of the hole to fill, the value was provided by ::ly_write_skip().
|
||||
* @param[in] buf Memory buffer with the data to print.
|
||||
* @param[in] len Length of the data to print in the @p buf. Not that the length must correspond
|
||||
* to the len value specified in the corresponding ::ly_write_skip() call.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
LY_ERR ly_write_skipped(struct ly_out *out, size_t position, const char *buf, size_t len);
|
||||
|
||||
#endif /* LY_OUT_INTERNAL_H_ */
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue