Merging upstream version 3.12.2.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
6375ddbe5b
commit
580fa3f55c
66 changed files with 4041 additions and 2142 deletions
25
.github/workflows/ci.yml
vendored
25
.github/workflows/ci.yml
vendored
|
@ -25,7 +25,7 @@ jobs:
|
|||
options: "-DENABLE_TESTS=ON",
|
||||
packager: "sudo apt-get",
|
||||
# no expect because stdout seems to be redirected
|
||||
packages: "libcmocka-dev shunit2",
|
||||
packages: "libcmocka-dev libxxhash-dev shunit2",
|
||||
snaps: "",
|
||||
build-cmd: "make"
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ jobs:
|
|||
cc: "clang",
|
||||
options: "-DENABLE_TESTS=ON",
|
||||
packager: "sudo apt-get",
|
||||
packages: "libcmocka-dev shunit2",
|
||||
packages: "libcmocka-dev libxxhash-dev shunit2",
|
||||
snaps: "",
|
||||
build-cmd: "make"
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ jobs:
|
|||
cc: "gcc",
|
||||
options: "",
|
||||
packager: "sudo apt-get",
|
||||
packages: "libcmocka-dev valgrind shunit2",
|
||||
packages: "libcmocka-dev libxxhash-dev valgrind shunit2",
|
||||
snaps: "",
|
||||
build-cmd: "make"
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ jobs:
|
|||
options: "",
|
||||
packager: "sudo apt-get",
|
||||
# no valgrind because it does not support DWARF5 yet generated by clang 14
|
||||
packages: "libcmocka-dev shunit2",
|
||||
packages: "libcmocka-dev libxxhash-dev shunit2",
|
||||
snaps: "",
|
||||
build-cmd: "make"
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ jobs:
|
|||
cc: "clang",
|
||||
options: "-DENABLE_TESTS=ON -DPATH_EXPECT=",
|
||||
packager: "brew",
|
||||
packages: "cmocka shunit2 tcl-tk",
|
||||
packages: "cmocka xxhash shunit2 tcl-tk",
|
||||
snaps: "",
|
||||
build-cmd: "make"
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ jobs:
|
|||
cc: "clang",
|
||||
options: "-DCMAKE_C_FLAGS=-fsanitize=address,undefined -DENABLE_TESTS=ON -DENABLE_VALGRIND_TESTS=OFF",
|
||||
packager: "sudo apt-get",
|
||||
packages: "libcmocka-dev",
|
||||
packages: "libcmocka-dev libxxhash-dev",
|
||||
snaps: "",
|
||||
build-cmd: "make"
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ jobs:
|
|||
cc: "gcc",
|
||||
options: "",
|
||||
packager: "sudo apt-get",
|
||||
packages: "libcmocka-dev abi-dumper abi-compliance-checker",
|
||||
packages: "libcmocka-dev libxxhash-dev abi-dumper abi-compliance-checker",
|
||||
snaps: "core universal-ctags",
|
||||
build-cmd: "make abi-check"
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ jobs:
|
|||
cc: "gcc",
|
||||
options: "",
|
||||
packager: "sudo apt-get",
|
||||
packages: "cmake debhelper libcmocka-dev python3-pip",
|
||||
packages: "cmake debhelper libcmocka-dev libxxhash-dev python3-pip",
|
||||
snaps: "",
|
||||
build-cmd: ""
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ jobs:
|
|||
cd uncrustify
|
||||
mkdir build
|
||||
cd build
|
||||
CC=${{ matrix.config.cc }} cmake ..
|
||||
CC=${{ matrix.config.cc }} cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 ..
|
||||
make
|
||||
sudo make install
|
||||
if: ${{ matrix.config.name == 'Debug, gcc' }}
|
||||
|
@ -209,8 +209,13 @@ jobs:
|
|||
id: cpu-cores
|
||||
uses: SimenB/github-actions-cpu-cores@v1
|
||||
|
||||
- name: pin CMake to the latest 3.x series
|
||||
uses: jwlawson/actions-setup-cmake@09fd9b0fb3b239b4b68d9256cd65adf8d6b91da0
|
||||
with:
|
||||
cmake-version: '3.31.6'
|
||||
|
||||
- name: Install Windows dependencies
|
||||
run: vcpkg install --triplet=${{ matrix.triplet }} pcre2 pthreads dirent dlfcn-win32 cmocka getopt
|
||||
run: vcpkg install --triplet=${{ matrix.triplet }} pcre2 pthreads dirent dlfcn-win32 cmocka getopt xxhash
|
||||
|
||||
- name: Configure
|
||||
shell: bash
|
||||
|
|
2
.github/workflows/cifuzz.yml
vendored
2
.github/workflows/cifuzz.yml
vendored
|
@ -17,7 +17,7 @@ jobs:
|
|||
fuzz-seconds: 300
|
||||
dry-run: false
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@main
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
with:
|
||||
name: artifacts
|
||||
|
|
2
.github/workflows/devel-push.yml
vendored
2
.github/workflows/devel-push.yml
vendored
|
@ -34,7 +34,7 @@ jobs:
|
|||
cc: "gcc",
|
||||
options: "-DENABLE_COVERAGE=ON",
|
||||
packager: "sudo apt-get",
|
||||
packages: "libcmocka-dev lcov",
|
||||
packages: "libcmocka-dev libxxhash-dev lcov",
|
||||
snaps: "",
|
||||
make-prepend: "",
|
||||
make-target: ""
|
||||
|
|
|
@ -59,14 +59,14 @@ set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
|||
|
||||
# set version of the project
|
||||
set(LIBYANG_MAJOR_VERSION 3)
|
||||
set(LIBYANG_MINOR_VERSION 7)
|
||||
set(LIBYANG_MICRO_VERSION 8)
|
||||
set(LIBYANG_MINOR_VERSION 12)
|
||||
set(LIBYANG_MICRO_VERSION 2)
|
||||
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 6)
|
||||
set(LIBYANG_MICRO_SOVERSION 10)
|
||||
set(LIBYANG_MINOR_SOVERSION 9)
|
||||
set(LIBYANG_MICRO_SOVERSION 1)
|
||||
set(LIBYANG_SOVERSION_FULL ${LIBYANG_MAJOR_SOVERSION}.${LIBYANG_MINOR_SOVERSION}.${LIBYANG_MICRO_SOVERSION})
|
||||
set(LIBYANG_SOVERSION ${LIBYANG_MAJOR_SOVERSION})
|
||||
|
||||
|
@ -411,6 +411,17 @@ find_package(PCRE2 10.21 REQUIRED)
|
|||
include_directories(${PCRE2_INCLUDE_DIRS})
|
||||
target_link_libraries(yang ${PCRE2_LIBRARIES})
|
||||
|
||||
# XXHash include and library
|
||||
find_package(XXHash)
|
||||
if(XXHASH_FOUND)
|
||||
add_definitions(-DLY_XXHASH_SUPPORT)
|
||||
include_directories(${XXHASH_INCLUDE_DIR})
|
||||
target_link_libraries(yang ${XXHASH_LIBRARY})
|
||||
message(STATUS "Hash algorithm: xxhash")
|
||||
else()
|
||||
message(STATUS "Hash algorithm: internal Jenkin's one-at-a-time")
|
||||
endif()
|
||||
|
||||
# generated header list
|
||||
foreach(h IN LISTS gen_headers)
|
||||
list(APPEND g_headers ${PROJECT_BINARY_DIR}/libyang/${h})
|
||||
|
|
38
CMakeModules/FindXXHash.cmake
Normal file
38
CMakeModules/FindXXHash.cmake
Normal file
|
@ -0,0 +1,38 @@
|
|||
# Try to find XXHash
|
||||
# Once done this will define
|
||||
#
|
||||
# Read-Only variables:
|
||||
# XXHASH_FOUND - system has XXHash
|
||||
# XXHASH_INCLUDE_DIR - the XXHash include directory
|
||||
# XXHASH_LIBRARY - Link these to use XXHash
|
||||
|
||||
find_path(XXHASH_INCLUDE_DIR
|
||||
NAMES
|
||||
xxhash.h
|
||||
PATHS
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
${CMAKE_INCLUDE_PATH}
|
||||
${CMAKE_INSTALL_PREFIX}/include
|
||||
)
|
||||
|
||||
find_library(XXHASH_LIBRARY
|
||||
NAMES
|
||||
xxhash
|
||||
libxxhash
|
||||
PATHS
|
||||
PATHS
|
||||
/usr/lib
|
||||
/usr/lib64
|
||||
/usr/local/lib
|
||||
/usr/local/lib64
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
${CMAKE_LIBRARY_PATH}
|
||||
${CMAKE_INSTALL_PREFIX}/lib
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(XXHash FOUND_VAR XXHASH_FOUND REQUIRED_VARS XXHASH_INCLUDE_DIR XXHASH_LIBRARY)
|
|
@ -61,6 +61,7 @@ the `distro` directory.
|
|||
|
||||
#### Optional
|
||||
|
||||
* xxhash (for faster hashing)
|
||||
* doxygen (for generating documentation)
|
||||
* cmocka >= 1.0.1 (for [tests](#Tests))
|
||||
* valgrind (for enhanced testing)
|
||||
|
|
|
@ -1,485 +0,0 @@
|
|||
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
|
||||
};
|
565
models/yang@2025-01-29.h
Normal file
565
models/yang@2025-01-29.h
Normal file
|
@ -0,0 +1,565 @@
|
|||
char yang_2025_01_29_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, 0x35, 0x2d, 0x30, 0x31, 0x2d,
|
||||
0x32, 0x39, 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, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64,
|
||||
0x61, 0x74, 0x61, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 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, 0x74, 0x79,
|
||||
0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61,
|
||||
0x74, 0x61, 0x2d, 0x63, 0x68, 0x61, 0x6e, 0x67, 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, 0x52, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e,
|
||||
0x74, 0x73, 0x20, 0x61, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
|
||||
0x61, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x76,
|
||||
0x61, 0x6c, 0x75, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x20,
|
||||
0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x73,
|
||||
0x20, 0x6f, 0x66, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
|
||||
0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x27, 0x3c, 0x6d, 0x6f, 0x64,
|
||||
0x75, 0x6c, 0x65, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x3e, 0x3a, 0x3c, 0x61,
|
||||
0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x6e, 0x61,
|
||||
0x6d, 0x65, 0x3e, 0x3d, 0x3c, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3e, 0x27,
|
||||
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, 0x0a, 0x20,
|
||||
0x20, 0x6d, 0x64, 0x3a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x2d, 0x63, 0x72, 0x65, 0x61,
|
||||
0x74, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x79, 0x70,
|
||||
0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x63,
|
||||
0x68, 0x61, 0x6e, 0x67, 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, 0x72, 0x65, 0x61, 0x74, 0x65,
|
||||
0x64, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x20, 0x69,
|
||||
0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68,
|
||||
0x20, 0x69, 0x74, 0x73, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x76, 0x61, 0x6c,
|
||||
0x75, 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, 0x6d, 0x65, 0x74, 0x61, 0x2d, 0x64, 0x65, 0x6c, 0x65,
|
||||
0x74, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x79, 0x70,
|
||||
0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x63,
|
||||
0x68, 0x61, 0x6e, 0x67, 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, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65,
|
||||
0x64, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x20, 0x69,
|
||||
0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68,
|
||||
0x20, 0x69, 0x74, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x76, 0x61, 0x6c,
|
||||
0x75, 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, 0x6d, 0x65, 0x74, 0x61, 0x2d, 0x72, 0x65, 0x70, 0x6c,
|
||||
0x61, 0x63, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x79,
|
||||
0x70, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2d,
|
||||
0x63, 0x68, 0x61, 0x6e, 0x67, 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, 0x68, 0x61, 0x6e, 0x67,
|
||||
0x65, 0x64, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x20,
|
||||
0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x77, 0x69, 0x74,
|
||||
0x68, 0x20, 0x69, 0x74, 0x73, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x6f, 0x6c, 0x64,
|
||||
0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x69, 0x73, 0x20, 0x73, 0x74,
|
||||
0x6f, 0x72, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x27, 0x6d, 0x65, 0x74,
|
||||
0x61, 0x2d, 0x6f, 0x72, 0x69, 0x67, 0x27, 0x20, 0x6d, 0x65, 0x74, 0x61,
|
||||
0x64, 0x61, 0x74, 0x61, 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, 0x6d, 0x65, 0x74, 0x61, 0x2d, 0x6f, 0x72,
|
||||
0x69, 0x67, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x79, 0x70,
|
||||
0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x63,
|
||||
0x68, 0x61, 0x6e, 0x67, 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, 0x68, 0x61, 0x6e, 0x67, 0x65,
|
||||
0x64, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x20, 0x69,
|
||||
0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68,
|
||||
0x20, 0x69, 0x74, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x76, 0x61, 0x6c,
|
||||
0x75, 0x65, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x77, 0x20,
|
||||
0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x69, 0x73, 0x20, 0x73, 0x74, 0x6f,
|
||||
0x72, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x27, 0x6d, 0x65, 0x74, 0x61,
|
||||
0x2d, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x27, 0x20, 0x6d, 0x65,
|
||||
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x22, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x7d, 0x0a, 0x7d, 0x0a, 0x00
|
||||
};
|
|
@ -21,6 +21,11 @@ module yang {
|
|||
of various metadata defined in RFC 6020 and RFC 7950. There are
|
||||
additional metadata used in libyang diff data format.";
|
||||
|
||||
revision 2025-01-29 {
|
||||
description
|
||||
"Added metadata for diff of metadata.";
|
||||
}
|
||||
|
||||
revision 2022-06-16 {
|
||||
description
|
||||
"Added typedef for key metadata type.";
|
||||
|
@ -59,6 +64,13 @@ module yang {
|
|||
"The key predicates of the full instance-identifier built-in type.";
|
||||
}
|
||||
|
||||
typedef metadata-change {
|
||||
type string;
|
||||
description
|
||||
"Represents a metadata instance value change and consists of module name,
|
||||
annotation name, and the value in the form '<module-name>:<annotation-name>=<value>'.";
|
||||
}
|
||||
|
||||
md:annotation insert {
|
||||
type enumeration {
|
||||
enum first;
|
||||
|
@ -192,4 +204,28 @@ module yang {
|
|||
"Its meaning is the same as the \"position\" attribute but identifies
|
||||
the original list instance rather than the new one.";
|
||||
}
|
||||
|
||||
md:annotation meta-create {
|
||||
type metadata-change;
|
||||
description
|
||||
"Created metadata instance with its new value.";
|
||||
}
|
||||
|
||||
md:annotation meta-delete {
|
||||
type metadata-change;
|
||||
description
|
||||
"Deleted metadata instance with its old value.";
|
||||
}
|
||||
|
||||
md:annotation meta-replace {
|
||||
type metadata-change;
|
||||
description
|
||||
"Changed metadata instance with its new value. The old value is stored in 'meta-orig' metadata.";
|
||||
}
|
||||
|
||||
md:annotation meta-orig {
|
||||
type metadata-change;
|
||||
description
|
||||
"Changed metadata instance with its old value. The new value is stored in 'meta-replace' metadata.";
|
||||
}
|
||||
}
|
|
@ -55,7 +55,7 @@
|
|||
#include "../models/ietf-yang-schema-mount@2019-01-14.h"
|
||||
#include "../models/ietf-yang-structure-ext@2020-06-17.h"
|
||||
#include "../models/ietf-yang-types@2013-07-15.h"
|
||||
#include "../models/yang@2022-06-16.h"
|
||||
#include "../models/yang@2025-01-29.h"
|
||||
#define IETF_YANG_LIB_REV "2019-01-04"
|
||||
|
||||
static struct internal_modules_s {
|
||||
|
@ -66,7 +66,7 @@ static struct internal_modules_s {
|
|||
LYS_INFORMAT format;
|
||||
} internal_modules[] = {
|
||||
{"ietf-yang-metadata", "2016-08-05", (const char *)ietf_yang_metadata_2016_08_05_yang, 0, LYS_IN_YANG},
|
||||
{"yang", "2022-06-16", (const char *)yang_2022_06_16_yang, 1, LYS_IN_YANG},
|
||||
{"yang", "2025-01-29", (const char *)yang_2025_01_29_yang, 1, LYS_IN_YANG},
|
||||
{"ietf-inet-types", "2013-07-15", (const char *)ietf_inet_types_2013_07_15_yang, 0, LYS_IN_YANG},
|
||||
{"ietf-yang-types", "2013-07-15", (const char *)ietf_yang_types_2013_07_15_yang, 0, LYS_IN_YANG},
|
||||
{"ietf-yang-schema-mount", "2019-01-14", (const char *)ietf_yang_schema_mount_2019_01_14_yang, 1, LYS_IN_YANG},
|
||||
|
@ -272,9 +272,9 @@ ly_ctx_ht_err_equal_cb(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *UN
|
|||
static ly_bool
|
||||
ly_ctx_ht_leafref_links_equal_cb(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *UNUSED(cb_data))
|
||||
{
|
||||
struct lyd_leafref_links_rec *rec1 = val1_p, *rec2 = val2_p;
|
||||
struct lyd_leafref_links_rec **rec1 = val1_p, **rec2 = val2_p;
|
||||
|
||||
return rec1->node == rec2->node;
|
||||
return (*rec1)->node == (*rec2)->node;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -285,9 +285,10 @@ ly_ctx_ht_leafref_links_equal_cb(void *val1_p, void *val2_p, ly_bool UNUSED(mod)
|
|||
static void
|
||||
ly_ctx_ht_leafref_links_rec_free(void *val_p)
|
||||
{
|
||||
struct lyd_leafref_links_rec *rec = val_p;
|
||||
struct lyd_leafref_links_rec **rec = val_p;
|
||||
|
||||
lyd_free_leafref_links_rec(rec);
|
||||
lyd_free_leafref_links_rec(*rec);
|
||||
free(*rec);
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
|
@ -316,7 +317,12 @@ ly_ctx_new(const char *search_dir, uint16_t options, struct ly_ctx **new_ctx)
|
|||
LY_CHECK_ERR_GOTO(lyplg_init(builtin_plugins_only), LOGINT(NULL); rc = LY_EINT, cleanup);
|
||||
|
||||
if (options & LY_CTX_LEAFREF_LINKING) {
|
||||
ctx->leafref_links_ht = lyht_new(1, sizeof(struct lyd_leafref_links_rec), ly_ctx_ht_leafref_links_equal_cb, NULL, 1);
|
||||
/**
|
||||
* storing the pointer instead of record itself is needed to avoid invalid memory reads. Hash table can reallocate
|
||||
* its memory completely during various manipulation function (e.g. remove, insert). In case of using pointers, the
|
||||
* pointer can be reallocated safely, while record itself remains untouched and can be accessed/modified freely
|
||||
* */
|
||||
ctx->leafref_links_ht = lyht_new(1, sizeof(struct lyd_leafref_links_rec *), ly_ctx_ht_leafref_links_equal_cb, NULL, 1);
|
||||
LY_CHECK_ERR_GOTO(!ctx->leafref_links_ht, rc = LY_EMEM, cleanup);
|
||||
}
|
||||
|
||||
|
@ -367,7 +373,7 @@ ly_ctx_new(const char *search_dir, uint16_t options, struct ly_ctx **new_ctx)
|
|||
/* load internal modules */
|
||||
for (i = 0; i < ((options & LY_CTX_NO_YANGLIBRARY) ? (LY_INTERNAL_MODS_COUNT - 2) : LY_INTERNAL_MODS_COUNT); i++) {
|
||||
ly_in_memory(in, internal_modules[i].data);
|
||||
LY_CHECK_GOTO(rc = lys_parse_in(ctx, in, internal_modules[i].format, NULL, NULL, &unres.creating, &module), cleanup);
|
||||
LY_CHECK_GOTO(rc = lys_parse_in(ctx, in, internal_modules[i].format, NULL, &unres.creating, &module), cleanup);
|
||||
if (internal_modules[i].implemented || (ctx->flags & LY_CTX_ALL_IMPLEMENTED)) {
|
||||
imp_f = (ctx->flags & LY_CTX_ENABLE_IMP_FEATURES) ? all_f : NULL;
|
||||
LY_CHECK_GOTO(rc = lys_implement(module, imp_f, &unres), cleanup);
|
||||
|
@ -654,7 +660,7 @@ ly_ctx_set_options(struct ly_ctx *ctx, uint16_t option)
|
|||
}
|
||||
|
||||
if (!(ctx->flags & LY_CTX_LEAFREF_LINKING) && (option & LY_CTX_LEAFREF_LINKING)) {
|
||||
ctx->leafref_links_ht = lyht_new(1, sizeof(struct lyd_leafref_links_rec), ly_ctx_ht_leafref_links_equal_cb, NULL, 1);
|
||||
ctx->leafref_links_ht = lyht_new(1, sizeof(struct lyd_leafref_links_rec *), ly_ctx_ht_leafref_links_equal_cb, NULL, 1);
|
||||
LY_CHECK_ERR_RET(!ctx->leafref_links_ht, LOGARG(ctx, option), LY_EMEM);
|
||||
}
|
||||
|
||||
|
|
1198
src/diff.c
1198
src/diff.c
File diff suppressed because it is too large
Load diff
|
@ -3,7 +3,7 @@
|
|||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief internal diff header
|
||||
*
|
||||
* Copyright (c) 2020 CESNET, z.s.p.o.
|
||||
* Copyright (c) 2020 - 2025 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.
|
||||
|
@ -53,10 +53,11 @@ enum lyd_diff_op {
|
|||
* @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.
|
||||
* @param[out] diff_node Optional created diff node.
|
||||
* @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);
|
||||
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, struct lyd_node **diff_node);
|
||||
|
||||
#endif /* LY_DIFF_H_ */
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief libyang generic hash table implementation
|
||||
*
|
||||
* Copyright (c) 2015 - 2023 CESNET, z.s.p.o.
|
||||
* Copyright (c) 2015 - 2025 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.
|
||||
|
@ -26,9 +26,20 @@
|
|||
#include "log.h"
|
||||
#include "ly_common.h"
|
||||
|
||||
#ifdef LY_XXHASH_SUPPORT
|
||||
# include <xxhash.h>
|
||||
#endif
|
||||
|
||||
LIBYANG_API_DEF uint32_t
|
||||
lyht_hash_multi(uint32_t hash, const char *key_part, size_t len)
|
||||
{
|
||||
#ifdef LY_XXHASH_SUPPORT
|
||||
if (key_part && len) {
|
||||
return XXH3_64bits_withSeed(key_part, len, hash);
|
||||
}
|
||||
|
||||
return XXH3_64bits_withSeed(NULL, 0, hash);
|
||||
#else
|
||||
uint32_t i;
|
||||
|
||||
if (key_part && len) {
|
||||
|
@ -44,15 +55,20 @@ lyht_hash_multi(uint32_t hash, const char *key_part, size_t len)
|
|||
}
|
||||
|
||||
return hash;
|
||||
#endif
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF uint32_t
|
||||
lyht_hash(const char *key, size_t len)
|
||||
{
|
||||
#ifdef LY_XXHASH_SUPPORT
|
||||
return XXH3_64bits(key, len);
|
||||
#else
|
||||
uint32_t hash;
|
||||
|
||||
hash = lyht_hash_multi(0, key, len);
|
||||
return lyht_hash_multi(hash, NULL, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
static LY_ERR
|
||||
|
|
|
@ -54,6 +54,8 @@ LIBYANG_API_DECL uint32_t lyht_hash_multi(uint32_t hash, const char *key_part, s
|
|||
*
|
||||
* Spooky hash is faster, but it works only for little endian architectures.
|
||||
*
|
||||
* Uses XXH3_64bits internally if xxhash is available. See https://xxhash.com
|
||||
*
|
||||
* @param[in] key Key to hash.
|
||||
* @param[in] len Length of @p key.
|
||||
* @return Hash of the key.
|
||||
|
|
54
src/log.c
54
src/log.c
|
@ -579,6 +579,38 @@ log_stderr_path_line(const char *data_path, const char *schema_path, uint64_t li
|
|||
fprintf(stderr, par ? ")\n" : "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Learn whether a log is a no-operation or must be produced, based on current ly_log_opts.
|
||||
*
|
||||
* @param[in] level Message log level to compare to enabled logging level.
|
||||
* @param[out] will_log Optionally learn whether the log will be printed.
|
||||
* @param[out] will_store Optionally learn whether the log will be stored.
|
||||
* @return 1 if the log is a no-operation, 0 otherwise.
|
||||
*/
|
||||
static ly_bool
|
||||
log_is_noop(LY_LOG_LEVEL level, ly_bool *will_log, ly_bool *will_store)
|
||||
{
|
||||
ly_bool 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 (will_log) {
|
||||
*will_log = lolog;
|
||||
}
|
||||
if (will_store) {
|
||||
*will_store = lostore;
|
||||
}
|
||||
|
||||
return (level > ATOMIC_LOAD_RELAXED(ly_ll)) || (!lolog && !lostore);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Log a message.
|
||||
*
|
||||
|
@ -601,16 +633,7 @@ log_vprintf(const struct ly_ctx *ctx, LY_LOG_LEVEL level, LY_ERR err, LY_VECODE
|
|||
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)) {
|
||||
if (log_is_noop(level, &lolog, &lostore)) {
|
||||
/* do not print or store the message */
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -858,6 +881,10 @@ ly_vlog(const struct ly_ctx *ctx, const char *apptag, LY_VECODE code, const char
|
|||
char *data_path = NULL, *schema_path = NULL;
|
||||
uint64_t line = 0;
|
||||
|
||||
if (log_is_noop(LY_LLERR, NULL, NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx) {
|
||||
ly_vlog_build_path_line(ctx, &data_path, &schema_path, &line);
|
||||
}
|
||||
|
@ -887,9 +914,10 @@ ly_ext_log(const struct ly_ctx *ctx, const char *plugin_name, LY_LOG_LEVEL level
|
|||
{
|
||||
char *plugin_msg;
|
||||
|
||||
if (ATOMIC_LOAD_RELAXED(ly_ll) < level) {
|
||||
if (log_is_noop(level, NULL, NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (asprintf(&plugin_msg, "Ext plugin \"%s\": %s", plugin_name, format) == -1) {
|
||||
LOGMEM(ctx);
|
||||
return;
|
||||
|
@ -987,6 +1015,10 @@ _ly_err_print(const struct ly_ctx *ctx, const struct ly_err_item *eitem, const c
|
|||
|
||||
LY_CHECK_ARG_RET(ctx, eitem, );
|
||||
|
||||
if (log_is_noop(eitem->level, NULL, NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (eitem->data_path) {
|
||||
data_path = strdup(eitem->data_path);
|
||||
}
|
||||
|
|
|
@ -154,7 +154,7 @@ const struct lyd_node *ly_log_location_dnode(uint32_t idx);
|
|||
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).
|
||||
* @brief Update location schema/data nodes for logger. If both NULL, root data node is added.
|
||||
*
|
||||
* @param[in] SCNODE Compiled schema node.
|
||||
* @param[in] DNODE Data node.
|
||||
|
@ -232,12 +232,12 @@ void ly_log_dbg(uint32_t group, const char *format, ...);
|
|||
#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__)
|
||||
#define LY_CHECK_CTX_EQUAL_RET2(FUNC, CTX1, CTX2, RETVAL) if ((CTX1) && (CTX2) && ((CTX1) != (CTX2))) \
|
||||
{LOGERR(CTX1, LY_EINVAL, "Different contexts mixed in a \"%s\" function call.", FUNC); return RETVAL;}
|
||||
#define LY_CHECK_CTX_EQUAL_RET3(FUNC, CTX1, CTX2, CTX3, RETVAL) LY_CHECK_CTX_EQUAL_RET2(FUNC, CTX1, CTX2, RETVAL); \
|
||||
LY_CHECK_CTX_EQUAL_RET2(FUNC, CTX2, CTX3, RETVAL); LY_CHECK_CTX_EQUAL_RET2(FUNC, CTX1, CTX3, RETVAL)
|
||||
#define LY_CHECK_CTX_EQUAL_RET(FUNC, CTX, ...) GETMACRO3(__VA_ARGS__, LY_CHECK_CTX_EQUAL_RET3, LY_CHECK_CTX_EQUAL_RET2, \
|
||||
DUMMY) (FUNC, CTX, __VA_ARGS__)
|
||||
|
||||
/* count sequence size for LY_VCODE_INCHILDSTMT validation error code */
|
||||
int LY_VCODE_INSTREXP_len(const char *str);
|
||||
|
|
|
@ -179,7 +179,10 @@ struct ly_in;
|
|||
#define LYD_PARSE_JSON_NULL 0x4000000 /**< Allow using JSON empty value 'null' within JSON input, such nodes are
|
||||
silently skipped and treated as non-existent. By default, such values
|
||||
are invalid. */
|
||||
|
||||
#define LYD_PARSE_JSON_STRING_DATATYPES 0x8000000 /**< By default, JSON data values are expected to be in the correct
|
||||
format according to RFC 7951 based on their type. Using this
|
||||
option the validation can be softened to accept boolean and
|
||||
number type values enclosed in quotes. */
|
||||
#define LYD_PARSE_OPTS_MASK 0xFFFF0000 /**< Mask for all the LYD_PARSE_ options. */
|
||||
|
||||
/** @} dataparseroptions */
|
||||
|
|
|
@ -340,7 +340,7 @@ cleanup:
|
|||
/**
|
||||
* @brief Get the hint for the data type parsers according to the current JSON parser context.
|
||||
*
|
||||
* @param[in] jsonctx JSON parser context. The context is supposed to be on a value.
|
||||
* @param[in] lydctx JSON data parser context.
|
||||
* @param[in,out] status Pointer to the current context status,
|
||||
* in some circumstances the function manipulates with the context so the status is updated.
|
||||
* @param[out] type_hint_p Pointer to the variable to store the result.
|
||||
|
@ -348,8 +348,10 @@ cleanup:
|
|||
* @return LY_EINVAL in case of invalid context status not referring to a value.
|
||||
*/
|
||||
static LY_ERR
|
||||
lydjson_value_type_hint(struct lyjson_ctx *jsonctx, enum LYJSON_PARSER_STATUS *status_p, uint32_t *type_hint_p)
|
||||
lydjson_value_type_hint(struct lyd_json_ctx *lydctx, enum LYJSON_PARSER_STATUS *status_p, uint32_t *type_hint_p)
|
||||
{
|
||||
struct lyjson_ctx *jsonctx = lydctx->jsonctx;
|
||||
|
||||
*type_hint_p = 0;
|
||||
|
||||
if (*status_p == LYJSON_ARRAY) {
|
||||
|
@ -383,6 +385,10 @@ lydjson_value_type_hint(struct lyjson_ctx *jsonctx, enum LYJSON_PARSER_STATUS *s
|
|||
return LY_EINVAL;
|
||||
}
|
||||
|
||||
if (lydctx->parse_opts & LYD_PARSE_JSON_STRING_DATATYPES) {
|
||||
*type_hint_p |= LYD_VALHINT_STRING_DATATYPES;
|
||||
}
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -391,15 +397,16 @@ lydjson_value_type_hint(struct lyjson_ctx *jsonctx, enum LYJSON_PARSER_STATUS *s
|
|||
*
|
||||
* Checks for all the list's keys. Function does not revert the context state.
|
||||
*
|
||||
* @param[in] jsonctx JSON parser context.
|
||||
* @param[in] lydctx JSON data parser context.
|
||||
* @param[in] list List schema node corresponding to the input data object.
|
||||
* @return LY_SUCCESS in case the data are ok for the @p list
|
||||
* @return LY_ENOT in case the input data are not sufficient to fully parse the list instance.
|
||||
*/
|
||||
static LY_ERR
|
||||
lydjson_check_list(struct lyjson_ctx *jsonctx, const struct lysc_node *list)
|
||||
lydjson_check_list(struct lyd_json_ctx *lydctx, const struct lysc_node *list)
|
||||
{
|
||||
LY_ERR rc = LY_SUCCESS;
|
||||
struct lyjson_ctx *jsonctx = lydctx->jsonctx;
|
||||
enum LYJSON_PARSER_STATUS status = lyjson_ctx_status(jsonctx);
|
||||
struct ly_set key_set = {0};
|
||||
const struct lysc_node *snode;
|
||||
|
@ -451,7 +458,7 @@ lydjson_check_list(struct lyjson_ctx *jsonctx, const struct lysc_node *list)
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
rc = lydjson_value_type_hint(jsonctx, &status, &hints);
|
||||
rc = lydjson_value_type_hint(lydctx, &status, &hints);
|
||||
LY_CHECK_GOTO(rc, cleanup);
|
||||
rc = ly_value_validate(NULL, snode, jsonctx->value, jsonctx->value_len, LY_VALUE_JSON, NULL, hints);
|
||||
LY_CHECK_GOTO(rc, cleanup);
|
||||
|
@ -521,7 +528,7 @@ lydjson_data_check_opaq(struct lyd_json_ctx *lydctx, const struct lysc_node *sno
|
|||
case LYS_LEAFLIST:
|
||||
case LYS_LEAF:
|
||||
/* value may not be valid in which case we parse it as an opaque node */
|
||||
if ((ret = lydjson_value_type_hint(jsonctx, &status, type_hint_p))) {
|
||||
if ((ret = lydjson_value_type_hint(lydctx, &status, type_hint_p))) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -533,14 +540,14 @@ lydjson_data_check_opaq(struct lyd_json_ctx *lydctx, const struct lysc_node *sno
|
|||
break;
|
||||
case LYS_LIST:
|
||||
/* lists may not have all its keys */
|
||||
if (lydjson_check_list(jsonctx, snode)) {
|
||||
if (lydjson_check_list(lydctx, snode)) {
|
||||
/* invalid list, parse as opaque if it misses/has invalid some keys */
|
||||
ret = LY_ENOT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (snode->nodetype & LYD_NODE_TERM) {
|
||||
ret = lydjson_value_type_hint(jsonctx, &status, type_hint_p);
|
||||
ret = lydjson_value_type_hint(lydctx, &status, type_hint_p);
|
||||
}
|
||||
|
||||
/* restore parser */
|
||||
|
@ -852,7 +859,7 @@ next_entry:
|
|||
LY_CHECK_GOTO(rc = lyjson_ctx_next(lydctx->jsonctx, &status), cleanup);
|
||||
|
||||
/* get value hints */
|
||||
LY_CHECK_GOTO(rc = lydjson_value_type_hint(lydctx->jsonctx, &status, &val_hints), cleanup);
|
||||
LY_CHECK_GOTO(rc = lydjson_value_type_hint(lydctx, &status, &val_hints), cleanup);
|
||||
|
||||
if (node->schema) {
|
||||
/* create metadata */
|
||||
|
@ -981,7 +988,7 @@ lydjson_create_opaq(struct lyd_json_ctx *lydctx, const char *name, size_t name_l
|
|||
dynamic = lydctx->jsonctx->dynamic;
|
||||
lydctx->jsonctx->dynamic = 0;
|
||||
|
||||
LY_CHECK_RET(lydjson_value_type_hint(lydctx->jsonctx, status_inner_p, &type_hint));
|
||||
LY_CHECK_RET(lydjson_value_type_hint(lydctx, status_inner_p, &type_hint));
|
||||
}
|
||||
|
||||
/* get the module name */
|
||||
|
|
419
src/parser_xml.c
419
src/parser_xml.c
|
@ -4,7 +4,7 @@
|
|||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief XML data parser for libyang
|
||||
*
|
||||
* Copyright (c) 2019 - 2022 CESNET, z.s.p.o.
|
||||
* Copyright (c) 2019 - 2025 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.
|
||||
|
@ -1392,396 +1392,10 @@ cleanup:
|
|||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse an XML element as an opaque node subtree.
|
||||
*
|
||||
* @param[in] xmlctx XML parser context.
|
||||
* @param[in] parent Parent to append nodes to.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
static LY_ERR
|
||||
lydxml_opaq_r(struct lyxml_ctx *xmlctx, struct lyd_node *parent)
|
||||
{
|
||||
LY_ERR rc = LY_SUCCESS;
|
||||
const struct lyxml_ns *ns;
|
||||
struct lyd_attr *attr = NULL;
|
||||
struct lyd_node *node = NULL;
|
||||
struct lyd_node_opaq *opaq;
|
||||
const char *name, *prefix, *value = NULL;
|
||||
size_t name_len, prefix_len, value_len;
|
||||
ly_bool ws_only, dynamic = 0;
|
||||
|
||||
assert(xmlctx->status == LYXML_ELEMENT);
|
||||
|
||||
name = xmlctx->name;
|
||||
name_len = xmlctx->name_len;
|
||||
prefix = xmlctx->prefix;
|
||||
prefix_len = xmlctx->prefix_len;
|
||||
ns = lyxml_ns_get(&xmlctx->ns, prefix, prefix_len);
|
||||
if (!ns) {
|
||||
lydxml_log_namespace_err(xmlctx, prefix, prefix_len, NULL, 0);
|
||||
return LY_EVALID;
|
||||
}
|
||||
|
||||
LY_CHECK_RET(lyxml_ctx_next(xmlctx));
|
||||
|
||||
/* create attributes */
|
||||
if (xmlctx->status == LYXML_ATTRIBUTE) {
|
||||
LY_CHECK_RET(lydxml_attrs(xmlctx, &attr));
|
||||
}
|
||||
|
||||
/* remember the value */
|
||||
assert(xmlctx->status == LYXML_ELEM_CONTENT);
|
||||
value = xmlctx->value;
|
||||
value_len = xmlctx->value_len;
|
||||
ws_only = xmlctx->ws_only;
|
||||
dynamic = xmlctx->dynamic;
|
||||
if (dynamic) {
|
||||
xmlctx->dynamic = 0;
|
||||
}
|
||||
|
||||
/* create the node without value */
|
||||
rc = lyd_create_opaq(xmlctx->ctx, name, name_len, prefix, prefix_len, ns->uri, strlen(ns->uri), NULL, 0, NULL,
|
||||
LY_VALUE_XML, NULL, 0, &node);
|
||||
LY_CHECK_GOTO(rc, cleanup);
|
||||
|
||||
/* assign atributes */
|
||||
((struct lyd_node_opaq *)node)->attr = attr;
|
||||
attr = NULL;
|
||||
|
||||
/* parser next element */
|
||||
LY_CHECK_GOTO(rc = lyxml_ctx_next(xmlctx), cleanup);
|
||||
|
||||
/* parse all the descendants */
|
||||
while (xmlctx->status == LYXML_ELEMENT) {
|
||||
rc = lydxml_opaq_r(xmlctx, node);
|
||||
LY_CHECK_GOTO(rc, cleanup);
|
||||
}
|
||||
|
||||
/* insert */
|
||||
lyd_insert_node(parent, NULL, node, LYD_INSERT_NODE_LAST);
|
||||
|
||||
/* update the value */
|
||||
opaq = (struct lyd_node_opaq *)node;
|
||||
if (opaq->child) {
|
||||
if (!ws_only) {
|
||||
LOGVAL(xmlctx->ctx, LYVE_SYNTAX_XML, "Mixed XML content node \"%s\" found, not supported.", LYD_NAME(node));
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
} else if (value_len) {
|
||||
lydict_remove(xmlctx->ctx, opaq->value);
|
||||
if (dynamic) {
|
||||
LY_CHECK_GOTO(rc = lydict_insert_zc(xmlctx->ctx, (char *)value, &opaq->value), cleanup);
|
||||
dynamic = 0;
|
||||
} else {
|
||||
LY_CHECK_GOTO(rc = lydict_insert(xmlctx->ctx, value, value_len, &opaq->value), cleanup);
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
lyd_free_attr_siblings(xmlctx->ctx, attr);
|
||||
if (dynamic) {
|
||||
free((char *)value);
|
||||
}
|
||||
if (rc) {
|
||||
lyd_free_tree(node);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse all expected non-data XML elements of the error-info element in NETCONF rpc-reply message.
|
||||
*
|
||||
* @param[in] xmlctx XML parser context.
|
||||
* @param[in] parent Parent to append nodes to.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
static LY_ERR
|
||||
lydxml_env_netconf_rpc_reply_error_info(struct lyxml_ctx *xmlctx, struct lyd_node *parent)
|
||||
{
|
||||
LY_ERR r;
|
||||
struct lyd_node *child, *iter;
|
||||
ly_bool no_dup;
|
||||
|
||||
/* there must be some child */
|
||||
if (xmlctx->status == LYXML_ELEM_CLOSE) {
|
||||
LOGVAL(xmlctx->ctx, LYVE_SYNTAX, "Missing child elements of \"error-info\".");
|
||||
return LY_EVALID;
|
||||
}
|
||||
|
||||
while (xmlctx->status == LYXML_ELEMENT) {
|
||||
child = NULL;
|
||||
|
||||
/*
|
||||
* session-id
|
||||
*/
|
||||
r = lydxml_envelope(xmlctx, "session-id", "urn:ietf:params:xml:ns:netconf:base:1.0", 1, &child);
|
||||
if (r == LY_SUCCESS) {
|
||||
no_dup = 1;
|
||||
goto check_child;
|
||||
} else if (r != LY_ENOT) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* bad-attribute
|
||||
*/
|
||||
r = lydxml_envelope(xmlctx, "bad-attribute", "urn:ietf:params:xml:ns:netconf:base:1.0", 1, &child);
|
||||
if (r == LY_SUCCESS) {
|
||||
no_dup = 1;
|
||||
goto check_child;
|
||||
} else if (r != LY_ENOT) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* bad-element
|
||||
*/
|
||||
r = lydxml_envelope(xmlctx, "bad-element", "urn:ietf:params:xml:ns:netconf:base:1.0", 1, &child);
|
||||
if (r == LY_SUCCESS) {
|
||||
no_dup = 1;
|
||||
goto check_child;
|
||||
} else if (r != LY_ENOT) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* bad-namespace
|
||||
*/
|
||||
r = lydxml_envelope(xmlctx, "bad-namespace", "urn:ietf:params:xml:ns:netconf:base:1.0", 1, &child);
|
||||
if (r == LY_SUCCESS) {
|
||||
no_dup = 1;
|
||||
goto check_child;
|
||||
} else if (r != LY_ENOT) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (r == LY_ENOT) {
|
||||
assert(xmlctx->status == LYXML_ELEMENT);
|
||||
|
||||
/* custom elements, parse all the siblings */
|
||||
while (xmlctx->status == LYXML_ELEMENT) {
|
||||
LY_CHECK_GOTO(r = lydxml_opaq_r(xmlctx, parent), error);
|
||||
LY_CHECK_GOTO(r = lyxml_ctx_next(xmlctx), error);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
check_child:
|
||||
/* check for duplicates */
|
||||
if (no_dup) {
|
||||
LY_LIST_FOR(lyd_child(parent), iter) {
|
||||
if ((((struct lyd_node_opaq *)iter)->name.name == ((struct lyd_node_opaq *)child)->name.name) &&
|
||||
(((struct lyd_node_opaq *)iter)->name.module_ns == ((struct lyd_node_opaq *)child)->name.module_ns)) {
|
||||
LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Duplicate element \"%s\" in \"error-info\".",
|
||||
((struct lyd_node_opaq *)child)->name.name);
|
||||
r = LY_EVALID;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* finish child parsing */
|
||||
if (xmlctx->status != LYXML_ELEM_CLOSE) {
|
||||
assert(xmlctx->status == LYXML_ELEMENT);
|
||||
LOGVAL(xmlctx->ctx, LYVE_SYNTAX, "Unexpected child element \"%.*s\" of \"error-info\".",
|
||||
(int)xmlctx->name_len, xmlctx->name);
|
||||
r = LY_EVALID;
|
||||
goto error;
|
||||
}
|
||||
LY_CHECK_GOTO(r = lyxml_ctx_next(xmlctx), error);
|
||||
|
||||
/* insert */
|
||||
lyd_insert_node(parent, NULL, child, LYD_INSERT_NODE_LAST);
|
||||
}
|
||||
|
||||
return LY_SUCCESS;
|
||||
|
||||
error:
|
||||
lyd_free_tree(child);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse all expected non-data XML elements of the rpc-error element in NETCONF rpc-reply message.
|
||||
*
|
||||
* @param[in] xmlctx XML parser context.
|
||||
* @param[in] parent Parent to append nodes to.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
static LY_ERR
|
||||
lydxml_env_netconf_rpc_reply_error(struct lyxml_ctx *xmlctx, struct lyd_node *parent)
|
||||
{
|
||||
LY_ERR r;
|
||||
struct lyd_node *child, *iter;
|
||||
const char *val;
|
||||
ly_bool no_dup;
|
||||
|
||||
/* there must be some child */
|
||||
if (xmlctx->status == LYXML_ELEM_CLOSE) {
|
||||
LOGVAL(xmlctx->ctx, LYVE_SYNTAX, "Missing child elements of \"rpc-error\".");
|
||||
return LY_EVALID;
|
||||
}
|
||||
|
||||
while (xmlctx->status == LYXML_ELEMENT) {
|
||||
child = NULL;
|
||||
|
||||
/*
|
||||
* error-type
|
||||
*/
|
||||
r = lydxml_envelope(xmlctx, "error-type", "urn:ietf:params:xml:ns:netconf:base:1.0", 1, &child);
|
||||
if (r == LY_SUCCESS) {
|
||||
val = ((struct lyd_node_opaq *)child)->value;
|
||||
if (strcmp(val, "transport") && strcmp(val, "rpc") && strcmp(val, "protocol") && strcmp(val, "application")) {
|
||||
LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Invalid value \"%s\" of element \"%s\".", val,
|
||||
((struct lyd_node_opaq *)child)->name.name);
|
||||
r = LY_EVALID;
|
||||
goto error;
|
||||
}
|
||||
|
||||
no_dup = 1;
|
||||
goto check_child;
|
||||
} else if (r != LY_ENOT) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* error-tag
|
||||
*/
|
||||
r = lydxml_envelope(xmlctx, "error-tag", "urn:ietf:params:xml:ns:netconf:base:1.0", 1, &child);
|
||||
if (r == LY_SUCCESS) {
|
||||
val = ((struct lyd_node_opaq *)child)->value;
|
||||
if (strcmp(val, "in-use") && strcmp(val, "invalid-value") && strcmp(val, "too-big") &&
|
||||
strcmp(val, "missing-attribute") && strcmp(val, "bad-attribute") &&
|
||||
strcmp(val, "unknown-attribute") && strcmp(val, "missing-element") && strcmp(val, "bad-element") &&
|
||||
strcmp(val, "unknown-element") && strcmp(val, "unknown-namespace") && strcmp(val, "access-denied") &&
|
||||
strcmp(val, "lock-denied") && strcmp(val, "resource-denied") && strcmp(val, "rollback-failed") &&
|
||||
strcmp(val, "data-exists") && strcmp(val, "data-missing") && strcmp(val, "operation-not-supported") &&
|
||||
strcmp(val, "operation-failed") && strcmp(val, "malformed-message")) {
|
||||
LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Invalid value \"%s\" of element \"%s\".", val,
|
||||
((struct lyd_node_opaq *)child)->name.name);
|
||||
r = LY_EVALID;
|
||||
goto error;
|
||||
}
|
||||
|
||||
no_dup = 1;
|
||||
goto check_child;
|
||||
} else if (r != LY_ENOT) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* error-severity
|
||||
*/
|
||||
r = lydxml_envelope(xmlctx, "error-severity", "urn:ietf:params:xml:ns:netconf:base:1.0", 1, &child);
|
||||
if (r == LY_SUCCESS) {
|
||||
val = ((struct lyd_node_opaq *)child)->value;
|
||||
if (strcmp(val, "error") && strcmp(val, "warning")) {
|
||||
LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Invalid value \"%s\" of element \"%s\".", val,
|
||||
((struct lyd_node_opaq *)child)->name.name);
|
||||
r = LY_EVALID;
|
||||
goto error;
|
||||
}
|
||||
|
||||
no_dup = 1;
|
||||
goto check_child;
|
||||
} else if (r != LY_ENOT) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* error-app-tag
|
||||
*/
|
||||
r = lydxml_envelope(xmlctx, "error-app-tag", "urn:ietf:params:xml:ns:netconf:base:1.0", 1, &child);
|
||||
if (r == LY_SUCCESS) {
|
||||
no_dup = 1;
|
||||
goto check_child;
|
||||
} else if (r != LY_ENOT) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* error-path
|
||||
*/
|
||||
r = lydxml_envelope(xmlctx, "error-path", "urn:ietf:params:xml:ns:netconf:base:1.0", 1, &child);
|
||||
if (r == LY_SUCCESS) {
|
||||
no_dup = 1;
|
||||
goto check_child;
|
||||
} else if (r != LY_ENOT) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* error-message
|
||||
*/
|
||||
r = lydxml_envelope(xmlctx, "error-message", "urn:ietf:params:xml:ns:netconf:base:1.0", 1, &child);
|
||||
if (r == LY_SUCCESS) {
|
||||
no_dup = 1;
|
||||
goto check_child;
|
||||
} else if (r != LY_ENOT) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* error-info */
|
||||
r = lydxml_envelope(xmlctx, "error-info", "urn:ietf:params:xml:ns:netconf:base:1.0", 0, &child);
|
||||
if (r == LY_SUCCESS) {
|
||||
/* parse all the descendants */
|
||||
LY_CHECK_GOTO(r = lydxml_env_netconf_rpc_reply_error_info(xmlctx, child), error);
|
||||
|
||||
no_dup = 0;
|
||||
goto check_child;
|
||||
} else if (r != LY_ENOT) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (r == LY_ENOT) {
|
||||
assert(xmlctx->status == LYXML_ELEMENT);
|
||||
LOGVAL(xmlctx->ctx, LYVE_SYNTAX, "Unexpected child element \"%.*s\" of \"rpc-error\".",
|
||||
(int)xmlctx->name_len, xmlctx->name);
|
||||
r = LY_EVALID;
|
||||
goto error;
|
||||
}
|
||||
|
||||
check_child:
|
||||
/* check for duplicates */
|
||||
if (no_dup) {
|
||||
LY_LIST_FOR(lyd_child(parent), iter) {
|
||||
if ((((struct lyd_node_opaq *)iter)->name.name == ((struct lyd_node_opaq *)child)->name.name) &&
|
||||
(((struct lyd_node_opaq *)iter)->name.module_ns == ((struct lyd_node_opaq *)child)->name.module_ns)) {
|
||||
LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Duplicate element \"%s\" in \"rpc-error\".",
|
||||
((struct lyd_node_opaq *)child)->name.name);
|
||||
r = LY_EVALID;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* finish child parsing */
|
||||
if (xmlctx->status != LYXML_ELEM_CLOSE) {
|
||||
assert(xmlctx->status == LYXML_ELEMENT);
|
||||
LOGVAL(xmlctx->ctx, LYVE_SYNTAX, "Unexpected child element \"%.*s\" of \"rpc-error\".",
|
||||
(int)xmlctx->name_len, xmlctx->name);
|
||||
r = LY_EVALID;
|
||||
goto error;
|
||||
}
|
||||
LY_CHECK_GOTO(r = lyxml_ctx_next(xmlctx), error);
|
||||
|
||||
/* insert */
|
||||
lyd_insert_node(parent, NULL, child, LYD_INSERT_NODE_LAST);
|
||||
}
|
||||
|
||||
return LY_SUCCESS;
|
||||
|
||||
error:
|
||||
lyd_free_tree(child);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse all expected non-data XML elements of a NETCONF rpc-reply message.
|
||||
*
|
||||
* @param[in] xmlctx XML parser context.
|
||||
* @param[in] lydctx XML YANG data parser context.
|
||||
* @param[out] evnp Parsed envelope(s) (opaque node).
|
||||
* @param[out] int_opts Internal options for parsing the rest of YANG data.
|
||||
* @param[out] close_elem Number of parsed opened elements that need to be closed.
|
||||
|
@ -1789,14 +1403,19 @@ error:
|
|||
* @return LY_ERR value on error.
|
||||
*/
|
||||
static LY_ERR
|
||||
lydxml_env_netconf_reply(struct lyxml_ctx *xmlctx, struct lyd_node **envp, uint32_t *int_opts, uint32_t *close_elem)
|
||||
lydxml_env_netconf_reply(struct lyd_xml_ctx *lydctx, struct lyd_node **envp, uint32_t *int_opts, uint32_t *close_elem)
|
||||
{
|
||||
LY_ERR rc = LY_SUCCESS, r;
|
||||
struct lyxml_ctx *xmlctx = lydctx->xmlctx;
|
||||
struct lyd_node *child = NULL;
|
||||
const char *parsed_elem = NULL;
|
||||
|
||||
assert(envp && !*envp);
|
||||
|
||||
/* not all nodes are represented as internal schema nodes and there may even be custom additional nodes */
|
||||
lydctx->parse_opts &= ~LYD_PARSE_STRICT;
|
||||
lydctx->parse_opts |= LYD_PARSE_OPAQ;
|
||||
|
||||
/* parse "rpc-reply" */
|
||||
r = lydxml_envelope(xmlctx, "rpc-reply", "urn:ietf:params:xml:ns:netconf:base:1.0", 0, envp);
|
||||
LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
|
||||
|
@ -1833,24 +1452,8 @@ lydxml_env_netconf_reply(struct lyxml_ctx *xmlctx, struct lyd_node **envp, uint3
|
|||
}
|
||||
|
||||
/* try to parse all "rpc-error" elements */
|
||||
while (xmlctx->status == LYXML_ELEMENT) {
|
||||
r = lydxml_envelope(xmlctx, "rpc-error", "urn:ietf:params:xml:ns:netconf:base:1.0", 0, &child);
|
||||
if (r == LY_ENOT) {
|
||||
break;
|
||||
} else if (r) {
|
||||
rc = r;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* insert */
|
||||
lyd_insert_node(*envp, NULL, child, LYD_INSERT_NODE_LAST);
|
||||
|
||||
/* parse all children of "rpc-error" */
|
||||
LY_CHECK_GOTO(rc = lydxml_env_netconf_rpc_reply_error(xmlctx, child), cleanup);
|
||||
|
||||
/* finish child parsing */
|
||||
assert(xmlctx->status == LYXML_ELEM_CLOSE);
|
||||
LY_CHECK_GOTO(rc = lyxml_ctx_next(xmlctx), cleanup);
|
||||
while ((xmlctx->status == LYXML_ELEMENT) && !ly_strncmp("rpc-error", xmlctx->name, xmlctx->name_len)) {
|
||||
LY_CHECK_GOTO(rc = lydxml_subtree_r(lydctx, *envp, lyd_node_child_p(*envp), NULL), cleanup);
|
||||
|
||||
parsed_elem = "rpc-error";
|
||||
}
|
||||
|
@ -1929,7 +1532,7 @@ lyd_parse_xml_netconf(const struct ly_ctx *ctx, const struct lysc_ext_instance *
|
|||
break;
|
||||
case LYD_TYPE_REPLY_NETCONF:
|
||||
assert(parent);
|
||||
rc = lydxml_env_netconf_reply(lydctx->xmlctx, envp, &int_opts, &close_elem);
|
||||
rc = lydxml_env_netconf_reply(lydctx, envp, &int_opts, &close_elem);
|
||||
if (rc == LY_ENOT) {
|
||||
LOGVAL(ctx, LYVE_DATA, "Missing NETCONF <rpc-reply> envelope or in incorrect namespace.");
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ struct lys_glob_unres;
|
|||
goto ERR_LABEL; \
|
||||
} \
|
||||
if (KW == LY_STMT_SYNTAX_RIGHT_BRACE) { \
|
||||
if (EXTS && (RET = ly_set_add(&(CTX)->main_ctx->ext_inst, (EXTS), 1, NULL))) { \
|
||||
if (EXTS && (RET = ly_set_add(&(CTX)->ext_inst, (EXTS), 1, NULL))) { \
|
||||
goto ERR_LABEL; \
|
||||
} \
|
||||
__loop_end = 1; \
|
||||
|
@ -417,13 +417,11 @@ read_qstring(struct lysp_yang_ctx *ctx, enum yang_arg arg, char **word_p, char *
|
|||
break;
|
||||
case '\r':
|
||||
/* newline may be escaped */
|
||||
if ((ctx->in->current[1] != '\n') && strncmp(&ctx->in->current[1], "\\n", 2)) {
|
||||
LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, ctx->in->current[0]);
|
||||
return LY_EVALID;
|
||||
}
|
||||
if ((ctx->in->current[1] == '\n') || !strncmp(&ctx->in->current[1], "\\n", 2)) {
|
||||
/* skip this character, do not store it */
|
||||
++ctx->in->current;
|
||||
} /* else just store '\n' instead */
|
||||
|
||||
/* skip this character, do not store it */
|
||||
++ctx->in->current;
|
||||
/* fallthrough */
|
||||
case '\n':
|
||||
if (block_indent) {
|
||||
|
@ -437,9 +435,20 @@ read_qstring(struct lysp_yang_ctx *ctx, enum yang_arg arg, char **word_p, char *
|
|||
current_indent = 0;
|
||||
}
|
||||
|
||||
c = NULL;
|
||||
if (ctx->in->current[0] != '\n') {
|
||||
/* storing '\r' as '\n' */
|
||||
c = ctx->in->current;
|
||||
ctx->in->current = "\n";
|
||||
}
|
||||
|
||||
/* check and store character */
|
||||
LY_CHECK_RET(buf_store_char(ctx, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
|
||||
|
||||
if (c) {
|
||||
ctx->in->current = c + 1;
|
||||
}
|
||||
|
||||
/* reset context indentation counter for possible string after this one */
|
||||
ctx->indent = 0;
|
||||
trailing_ws = 0;
|
||||
|
@ -2833,8 +2842,7 @@ parse_typedef(struct lysp_yang_ctx *ctx, struct lysp_node *parent, struct lysp_t
|
|||
|
||||
/* store data for collision check */
|
||||
if (parent) {
|
||||
assert(ctx->main_ctx);
|
||||
LY_CHECK_RET(ly_set_add(&ctx->main_ctx->tpdfs_nodes, parent, 0, NULL));
|
||||
LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
@ -3175,8 +3183,7 @@ parse_grouping(struct lysp_yang_ctx *ctx, struct lysp_node *parent, struct lysp_
|
|||
|
||||
/* store data for collision check */
|
||||
if (parent) {
|
||||
assert(ctx->main_ctx);
|
||||
LY_CHECK_RET(ly_set_add(&ctx->main_ctx->grps_nodes, parent, 0, NULL));
|
||||
LY_CHECK_RET(ly_set_add(&ctx->grps_nodes, parent, 0, NULL));
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
|
|
@ -646,7 +646,7 @@ yin_unres_exts_add(struct lysp_yin_ctx *ctx, struct lysp_ext_instance *exts)
|
|||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
return ly_set_add(&ctx->main_ctx->ext_inst, exts, 1, NULL);
|
||||
return ly_set_add(&ctx->ext_inst, exts, 1, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1713,8 +1713,7 @@ yin_parse_typedef(struct lysp_yin_ctx *ctx, struct tree_node_meta *typedef_meta)
|
|||
|
||||
/* store data for collision check */
|
||||
if (typedef_meta->parent) {
|
||||
assert(ctx->main_ctx);
|
||||
LY_CHECK_RET(ly_set_add(&ctx->main_ctx->tpdfs_nodes, typedef_meta->parent, 0, NULL));
|
||||
LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0, NULL));
|
||||
}
|
||||
|
||||
return LY_SUCCESS;
|
||||
|
@ -2472,8 +2471,7 @@ yin_parse_grouping(struct lysp_yin_ctx *ctx, struct tree_node_meta *gr_meta)
|
|||
|
||||
/* store data for collision check */
|
||||
if (!ret && grp->parent) {
|
||||
assert(ctx->main_ctx);
|
||||
LY_CHECK_RET(ly_set_add(&ctx->main_ctx->grps_nodes, grp->parent, 0, NULL));
|
||||
LY_CHECK_RET(ly_set_add(&ctx->grps_nodes, grp->parent, 0, NULL));
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
240
src/path.c
240
src/path.c
|
@ -3,7 +3,7 @@
|
|||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief Path functions
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 CESNET, z.s.p.o.
|
||||
* Copyright (c) 2020 - 2025 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.
|
||||
|
@ -339,6 +339,17 @@ ly_path_parse(const struct ly_ctx *ctx, const struct lysc_node *ctx_node, const
|
|||
LOG_LOCSET(ctx_node, NULL);
|
||||
}
|
||||
|
||||
if (!path_len) {
|
||||
path_len = strlen(str_path);
|
||||
}
|
||||
|
||||
/* check if path begins with '/' if expected to and fail early if not */
|
||||
if ((begin == LY_PATH_BEGIN_ABSOLUTE) && (str_path[0] != '/')) {
|
||||
LOGVAL(ctx, LYVE_XPATH, "XPath \"%.*s\" was expected to be absolute.", (int)path_len, str_path);
|
||||
ret = LY_EVALID;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* parse as a generic XPath expression, reparse is performed manually */
|
||||
LY_CHECK_GOTO(ret = lyxp_expr_parse(ctx, str_path, path_len, 0, &exp), error);
|
||||
tok_idx = 0;
|
||||
|
@ -499,7 +510,7 @@ error:
|
|||
* @brief Parse NameTest and get the corresponding schema node.
|
||||
*
|
||||
* @param[in] ctx libyang context.
|
||||
* @param[in] cur_node Optional current (original context) node.
|
||||
* @param[in] cur_node Current (original context) node.
|
||||
* @param[in] cur_mod Current module of the path (where the path is "instantiated"). Needed for ::LY_VALUE_SCHEMA
|
||||
* and ::LY_VALUE_SCHEMA_RESOLVED.
|
||||
* @param[in] prev_ctx_node Previous context node.
|
||||
|
@ -519,7 +530,7 @@ ly_path_compile_snode(const struct ly_ctx *ctx, const struct lysc_node *cur_node
|
|||
void *prefix_data, const struct lysc_ext_instance *top_ext, uint32_t getnext_opts, const struct lysc_node **snode,
|
||||
struct lysc_ext_instance **ext)
|
||||
{
|
||||
LY_ERR ret;
|
||||
LY_ERR rc = LY_SUCCESS, r;
|
||||
const struct lys_module *mod = NULL;
|
||||
struct lysc_ext_instance *e = NULL;
|
||||
const char *pref, *name;
|
||||
|
@ -551,39 +562,37 @@ ly_path_compile_snode(const struct ly_ctx *ctx, const struct lysc_node *cur_node
|
|||
|
||||
/* find node module */
|
||||
if (pref) {
|
||||
if (cur_node) {
|
||||
LOG_LOCSET(cur_node, NULL);
|
||||
}
|
||||
|
||||
mod = ly_resolve_prefix(prev_ctx_node ? prev_ctx_node->module->ctx : ctx, pref, len, format, prefix_data);
|
||||
if ((!mod || !mod->implemented) && prev_ctx_node) {
|
||||
/* check for nested ext data */
|
||||
ret = ly_nested_ext_schema(NULL, prev_ctx_node, pref, len, format, prefix_data, name, name_len, snode, &e);
|
||||
if (!ret) {
|
||||
goto success;
|
||||
} else if (ret != LY_ENOT) {
|
||||
goto error;
|
||||
r = ly_nested_ext_schema(NULL, prev_ctx_node, pref, len, format, prefix_data, name, name_len, snode, &e);
|
||||
if (!r) {
|
||||
goto cleanup;
|
||||
} else if (r != LY_ENOT) {
|
||||
rc = r;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mod) {
|
||||
LOGVAL(ctx, LYVE_XPATH, "No module connected with the prefix \"%.*s\" found (prefix format %s).",
|
||||
(int)len, pref, ly_format2str(format));
|
||||
ret = LY_EVALID;
|
||||
goto error;
|
||||
LOGVAL_PATH(ctx, cur_node, prev_ctx_node, LYVE_XPATH,
|
||||
"No module connected with the prefix \"%.*s\" found (prefix format %s).", (int)len, pref,
|
||||
ly_format2str(format));
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
} else if (!mod->implemented) {
|
||||
LOGVAL(ctx, LYVE_XPATH, "Not implemented module \"%s\" in path.", mod->name);
|
||||
ret = LY_EVALID;
|
||||
goto error;
|
||||
LOGVAL_PATH(ctx, cur_node, prev_ctx_node, LYVE_XPATH, "Not implemented module \"%s\" in path.", mod->name);
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
LOG_LOCBACK(cur_node ? 1 : 0, 0);
|
||||
} else {
|
||||
switch (format) {
|
||||
case LY_VALUE_SCHEMA:
|
||||
case LY_VALUE_SCHEMA_RESOLVED:
|
||||
if (!cur_mod) {
|
||||
LOGINT_RET(ctx);
|
||||
LOGINT(ctx);
|
||||
rc = LY_EINT;
|
||||
goto cleanup;
|
||||
}
|
||||
/* use current module */
|
||||
mod = cur_mod;
|
||||
|
@ -591,7 +600,9 @@ ly_path_compile_snode(const struct ly_ctx *ctx, const struct lysc_node *cur_node
|
|||
case LY_VALUE_JSON:
|
||||
case LY_VALUE_LYB:
|
||||
if (!prev_ctx_node) {
|
||||
LOGINT_RET(ctx);
|
||||
LOGINT(ctx);
|
||||
rc = LY_EINT;
|
||||
goto cleanup;
|
||||
}
|
||||
/* inherit module of the previous node */
|
||||
mod = prev_ctx_node->module;
|
||||
|
@ -600,7 +611,9 @@ ly_path_compile_snode(const struct ly_ctx *ctx, const struct lysc_node *cur_node
|
|||
case LY_VALUE_XML:
|
||||
case LY_VALUE_STR_NS:
|
||||
/* not really defined or accepted */
|
||||
LOGINT_RET(ctx);
|
||||
LOGINT(ctx);
|
||||
rc = LY_EINT;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -610,24 +623,21 @@ ly_path_compile_snode(const struct ly_ctx *ctx, const struct lysc_node *cur_node
|
|||
} else {
|
||||
*snode = lys_find_child(prev_ctx_node, mod, name, name_len, 0, getnext_opts);
|
||||
if (!(*snode) && prev_ctx_node) {
|
||||
ret = ly_nested_ext_schema(NULL, prev_ctx_node, pref, len, format, prefix_data, name, name_len, snode, &e);
|
||||
LY_CHECK_RET(ret && (ret != LY_ENOT), ret);
|
||||
r = ly_nested_ext_schema(NULL, prev_ctx_node, pref, len, format, prefix_data, name, name_len, snode, &e);
|
||||
LY_CHECK_ERR_GOTO(r && (r != LY_ENOT), rc = r, cleanup);
|
||||
}
|
||||
}
|
||||
if (!(*snode)) {
|
||||
LOGVAL(ctx, LYVE_XPATH, "Not found node \"%.*s\" in path.", (int)name_len, name);
|
||||
return LY_ENOTFOUND;
|
||||
LOGVAL_PATH(ctx, cur_node, prev_ctx_node, LYVE_XPATH, "Not found node \"%.*s\" in path.", (int)name_len, name);
|
||||
rc = LY_ENOTFOUND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
success:
|
||||
if (ext) {
|
||||
cleanup:
|
||||
if (!rc && ext) {
|
||||
*ext = e;
|
||||
}
|
||||
return LY_SUCCESS;
|
||||
|
||||
error:
|
||||
LOG_LOCBACK(cur_node ? 1 : 0, 0);
|
||||
return ret;
|
||||
return rc;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
|
@ -635,7 +645,7 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_
|
|||
const struct lysc_node *ctx_node, const struct lyxp_expr *expr, uint32_t *tok_idx, LY_VALUE_FORMAT format,
|
||||
void *prefix_data, struct ly_path_predicate **predicates)
|
||||
{
|
||||
LY_ERR ret = LY_SUCCESS;
|
||||
LY_ERR rc = LY_SUCCESS;
|
||||
struct ly_path_predicate *p;
|
||||
const struct lysc_node *key;
|
||||
const char *val;
|
||||
|
@ -643,10 +653,6 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_
|
|||
|
||||
assert(ctx && ctx_node);
|
||||
|
||||
if (cur_node) {
|
||||
LOG_LOCSET(cur_node, NULL);
|
||||
}
|
||||
|
||||
*predicates = NULL;
|
||||
|
||||
if (lyxp_next_token(NULL, expr, tok_idx, LYXP_TOKEN_BRACK1)) {
|
||||
|
@ -656,31 +662,32 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_
|
|||
|
||||
if (expr->tokens[*tok_idx] == LYXP_TOKEN_NAMETEST) {
|
||||
if (ctx_node->nodetype != LYS_LIST) {
|
||||
LOGVAL(ctx, LYVE_XPATH, "List predicate defined for %s \"%s\" in path.",
|
||||
LOGVAL_PATH(ctx, cur_node, ctx_node, LYVE_XPATH, "List predicate defined for %s \"%s\" in path.",
|
||||
lys_nodetype2str(ctx_node->nodetype), ctx_node->name);
|
||||
ret = LY_EVALID;
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
} else if (ctx_node->flags & LYS_KEYLESS) {
|
||||
LOGVAL(ctx, LYVE_XPATH, "List predicate defined for keyless %s \"%s\" in path.",
|
||||
LOGVAL_PATH(ctx, cur_node, ctx_node, LYVE_XPATH, "List predicate defined for keyless %s \"%s\" in path.",
|
||||
lys_nodetype2str(ctx_node->nodetype), ctx_node->name);
|
||||
ret = LY_EVALID;
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
do {
|
||||
/* NameTest, find the key */
|
||||
LY_CHECK_RET(ly_path_compile_snode(ctx, cur_node, cur_mod, ctx_node, expr, *tok_idx, format, prefix_data,
|
||||
NULL, 0, &key, NULL));
|
||||
rc = ly_path_compile_snode(ctx, cur_node, cur_mod, ctx_node, expr, *tok_idx, format, prefix_data, NULL, 0,
|
||||
&key, NULL);
|
||||
LY_CHECK_GOTO(rc, cleanup);
|
||||
if ((key->nodetype != LYS_LEAF) || !(key->flags & LYS_KEY)) {
|
||||
LOGVAL(ctx, LYVE_XPATH, "Key expected instead of %s \"%s\" in path.", lys_nodetype2str(key->nodetype),
|
||||
key->name);
|
||||
ret = LY_EVALID;
|
||||
LOGVAL_PATH(ctx, cur_node, ctx_node, LYVE_XPATH, "Key expected instead of %s \"%s\" in path.",
|
||||
lys_nodetype2str(key->nodetype), key->name);
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
++(*tok_idx);
|
||||
|
||||
/* new predicate */
|
||||
LY_ARRAY_NEW_GOTO(ctx, *predicates, p, ret, cleanup);
|
||||
LY_ARRAY_NEW_GOTO(ctx, *predicates, p, rc, cleanup);
|
||||
p->key = key;
|
||||
|
||||
/* '=' */
|
||||
|
@ -691,7 +698,7 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_
|
|||
if (expr->tokens[*tok_idx] == LYXP_TOKEN_VARREF) {
|
||||
/* store the variable name */
|
||||
p->variable = strndup(expr->expr + expr->tok_pos[*tok_idx], expr->tok_len[*tok_idx]);
|
||||
LY_CHECK_ERR_GOTO(!p->variable, LOGMEM(ctx); ret = LY_EMEM, cleanup);
|
||||
LY_CHECK_ERR_GOTO(!p->variable, LOGMEM(ctx); rc = LY_EMEM, cleanup);
|
||||
|
||||
p->type = LY_PATH_PREDTYPE_LIST_VAR;
|
||||
++(*tok_idx);
|
||||
|
@ -708,10 +715,10 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_
|
|||
|
||||
/* store the value */
|
||||
LOG_LOCSET(key, NULL);
|
||||
ret = lyd_value_store(ctx_node->module->ctx, &p->value, ((struct lysc_node_leaf *)key)->type, val, val_len, 0, 0,
|
||||
rc = lyd_value_store(ctx_node->module->ctx, &p->value, ((struct lysc_node_leaf *)key)->type, val, val_len, 0, 0,
|
||||
NULL, format, prefix_data, LYD_HINT_DATA, key, NULL);
|
||||
LOG_LOCBACK(1, 0);
|
||||
LY_CHECK_ERR_GOTO(ret, p->value.realtype = NULL, cleanup);
|
||||
LY_CHECK_ERR_GOTO(rc, p->value.realtype = NULL, cleanup);
|
||||
|
||||
/* "allocate" the type to avoid problems when freeing the value after the type was freed */
|
||||
LY_ATOMIC_INC_BARRIER(((struct lysc_type *)p->value.realtype)->refcount);
|
||||
|
@ -734,23 +741,23 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_
|
|||
}
|
||||
if (LY_ARRAY_COUNT(*predicates) != key_count) {
|
||||
/* names (keys) are unique - it was checked when parsing */
|
||||
LOGVAL(ctx, LYVE_XPATH, "Predicate missing for a key of %s \"%s\" in path.",
|
||||
LOGVAL_PATH(ctx, cur_node, ctx_node, LYVE_XPATH, "Predicate missing for a key of %s \"%s\" in path.",
|
||||
lys_nodetype2str(ctx_node->nodetype), ctx_node->name);
|
||||
ret = LY_EVALID;
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
} else if (expr->tokens[*tok_idx] == LYXP_TOKEN_DOT) {
|
||||
if (ctx_node->nodetype != LYS_LEAFLIST) {
|
||||
LOGVAL(ctx, LYVE_XPATH, "Leaf-list predicate defined for %s \"%s\" in path.",
|
||||
LOGVAL_PATH(ctx, cur_node, ctx_node, LYVE_XPATH, "Leaf-list predicate defined for %s \"%s\" in path.",
|
||||
lys_nodetype2str(ctx_node->nodetype), ctx_node->name);
|
||||
ret = LY_EVALID;
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
++(*tok_idx);
|
||||
|
||||
/* new predicate */
|
||||
LY_ARRAY_NEW_GOTO(ctx, *predicates, p, ret, cleanup);
|
||||
LY_ARRAY_NEW_GOTO(ctx, *predicates, p, rc, cleanup);
|
||||
p->type = LY_PATH_PREDTYPE_LEAFLIST;
|
||||
|
||||
/* '=' */
|
||||
|
@ -769,11 +776,9 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_
|
|||
}
|
||||
|
||||
/* store the value */
|
||||
LOG_LOCSET(ctx_node, NULL);
|
||||
ret = lyd_value_store(ctx_node->module->ctx, &p->value, ((struct lysc_node_leaflist *)ctx_node)->type, val, val_len, 0, 0,
|
||||
rc = lyd_value_store(ctx_node->module->ctx, &p->value, ((struct lysc_node_leaflist *)ctx_node)->type, val, val_len, 0, 0,
|
||||
NULL, format, prefix_data, LYD_HINT_DATA, ctx_node, NULL);
|
||||
LOG_LOCBACK(1, 0);
|
||||
LY_CHECK_ERR_GOTO(ret, p->value.realtype = NULL, cleanup);
|
||||
LY_CHECK_ERR_GOTO(rc, p->value.realtype = NULL, cleanup);
|
||||
++(*tok_idx);
|
||||
|
||||
/* "allocate" the type to avoid problems when freeing the value after the type was freed */
|
||||
|
@ -785,19 +790,19 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_
|
|||
} else {
|
||||
assert(expr->tokens[*tok_idx] == LYXP_TOKEN_NUMBER);
|
||||
if (!(ctx_node->nodetype & (LYS_LEAFLIST | LYS_LIST))) {
|
||||
ret = LY_EVALID;
|
||||
LOGVAL(ctx, LYVE_XPATH, "Positional predicate defined for %s \"%s\" in path.",
|
||||
LOGVAL_PATH(ctx, cur_node, ctx_node, LYVE_XPATH, "Positional predicate defined for %s \"%s\" in path.",
|
||||
lys_nodetype2str(ctx_node->nodetype), ctx_node->name);
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
} else if (ctx_node->flags & LYS_CONFIG_W) {
|
||||
ret = LY_EVALID;
|
||||
LOGVAL(ctx, LYVE_XPATH, "Positional predicate defined for configuration %s \"%s\" in path.",
|
||||
LOGVAL_PATH(ctx, cur_node, ctx_node, LYVE_XPATH, "Positional predicate defined for configuration %s \"%s\" in path.",
|
||||
lys_nodetype2str(ctx_node->nodetype), ctx_node->name);
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* new predicate */
|
||||
LY_ARRAY_NEW_GOTO(ctx, *predicates, p, ret, cleanup);
|
||||
LY_ARRAY_NEW_GOTO(ctx, *predicates, p, rc, cleanup);
|
||||
p->type = LY_PATH_PREDTYPE_POSITION;
|
||||
|
||||
/* syntax was already checked */
|
||||
|
@ -810,12 +815,11 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_
|
|||
}
|
||||
|
||||
cleanup:
|
||||
LOG_LOCBACK(cur_node ? 1 : 0, 0);
|
||||
if (ret) {
|
||||
if (rc) {
|
||||
ly_path_predicates_free(ctx_node->module->ctx, *predicates);
|
||||
*predicates = NULL;
|
||||
}
|
||||
return ret;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -833,7 +837,7 @@ static LY_ERR
|
|||
ly_path_compile_predicate_leafref(const struct lysc_node *ctx_node, const struct lysc_node *cur_node,
|
||||
const struct lyxp_expr *expr, uint32_t *tok_idx, LY_VALUE_FORMAT format, void *prefix_data)
|
||||
{
|
||||
LY_ERR ret = LY_SUCCESS;
|
||||
LY_ERR rc = LY_SUCCESS;
|
||||
const struct lysc_node *key, *node, *node2;
|
||||
struct ly_ctx *ctx = cur_node->module->ctx;
|
||||
|
||||
|
@ -843,26 +847,26 @@ ly_path_compile_predicate_leafref(const struct lysc_node *ctx_node, const struct
|
|||
}
|
||||
|
||||
if (ctx_node->nodetype != LYS_LIST) {
|
||||
LOGVAL(ctx, LYVE_XPATH, "List predicate defined for %s \"%s\" in path.",
|
||||
LOGVAL_PATH(ctx, cur_node, ctx_node, LYVE_XPATH, "List predicate defined for %s \"%s\" in path.",
|
||||
lys_nodetype2str(ctx_node->nodetype), ctx_node->name);
|
||||
ret = LY_EVALID;
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
} else if (ctx_node->flags & LYS_KEYLESS) {
|
||||
LOGVAL(ctx, LYVE_XPATH, "List predicate defined for keyless %s \"%s\" in path.",
|
||||
LOGVAL_PATH(ctx, cur_node, ctx_node, LYVE_XPATH, "List predicate defined for keyless %s \"%s\" in path.",
|
||||
lys_nodetype2str(ctx_node->nodetype), ctx_node->name);
|
||||
ret = LY_EVALID;
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
do {
|
||||
/* NameTest, find the key */
|
||||
ret = ly_path_compile_snode(ctx, cur_node, cur_node->module, ctx_node, expr, *tok_idx, format, prefix_data,
|
||||
rc = ly_path_compile_snode(ctx, cur_node, cur_node->module, ctx_node, expr, *tok_idx, format, prefix_data,
|
||||
NULL, 0, &key, NULL);
|
||||
LY_CHECK_GOTO(ret, cleanup);
|
||||
LY_CHECK_GOTO(rc, cleanup);
|
||||
if ((key->nodetype != LYS_LEAF) || !(key->flags & LYS_KEY)) {
|
||||
LOGVAL(ctx, LYVE_XPATH, "Key expected instead of %s \"%s\" in path.",
|
||||
LOGVAL_PATH(ctx, cur_node, ctx_node, LYVE_XPATH, "Key expected instead of %s \"%s\" in path.",
|
||||
lys_nodetype2str(key->nodetype), key->name);
|
||||
ret = LY_EVALID;
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
++(*tok_idx);
|
||||
|
@ -896,8 +900,8 @@ ly_path_compile_predicate_leafref(const struct lysc_node *ctx_node, const struct
|
|||
|
||||
/* go to parent */
|
||||
if (!node) {
|
||||
LOGVAL(ctx, LYVE_XPATH, "Too many parent references in path.");
|
||||
ret = LY_EVALID;
|
||||
LOGVAL_PATH(ctx, cur_node, ctx_node, LYVE_XPATH, "Too many parent references in path.");
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
node = lysc_data_parent(node);
|
||||
|
@ -914,17 +918,18 @@ ly_path_compile_predicate_leafref(const struct lysc_node *ctx_node, const struct
|
|||
|
||||
/* NameTest */
|
||||
assert(expr->tokens[*tok_idx] == LYXP_TOKEN_NAMETEST);
|
||||
LY_CHECK_RET(ly_path_compile_snode(ctx, cur_node, cur_node->module, node, expr, *tok_idx, format,
|
||||
prefix_data, NULL, 0, &node2, NULL));
|
||||
rc = ly_path_compile_snode(ctx, cur_node, cur_node->module, node, expr, *tok_idx, format, prefix_data, NULL,
|
||||
0, &node2, NULL);
|
||||
LY_CHECK_GOTO(rc, cleanup);
|
||||
node = node2;
|
||||
++(*tok_idx);
|
||||
} while ((*tok_idx + 1 < expr->used) && (expr->tokens[*tok_idx + 1] == LYXP_TOKEN_NAMETEST));
|
||||
|
||||
/* check the last target node */
|
||||
if (node->nodetype != LYS_LEAF) {
|
||||
LOGVAL(ctx, LYVE_XPATH, "Leaf expected instead of %s \"%s\" in leafref predicate in path.",
|
||||
LOGVAL_PATH(ctx, cur_node, ctx_node, LYVE_XPATH, "Leaf expected instead of %s \"%s\" in leafref predicate in path.",
|
||||
lys_nodetype2str(node->nodetype), node->name);
|
||||
ret = LY_EVALID;
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
@ -939,7 +944,7 @@ ly_path_compile_predicate_leafref(const struct lysc_node *ctx_node, const struct
|
|||
} while (!lyxp_next_token(NULL, expr, tok_idx, LYXP_TOKEN_BRACK1));
|
||||
|
||||
cleanup:
|
||||
return (ret == LY_ENOTFOUND) ? LY_EVALID : ret;
|
||||
return (rc == LY_ENOTFOUND) ? LY_EVALID : rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1022,6 +1027,7 @@ cleanup:
|
|||
* @brief Compile deref XPath function into ly_path structure.
|
||||
*
|
||||
* @param[in] ctx libyang context.
|
||||
* @param[in] cur_node Current (original context) node.
|
||||
* @param[in] ctx_node Optional context node, mandatory of @p lref.
|
||||
* @param[in] top_ext Extension instance containing the definition of the data being created. It is used to find
|
||||
* the top-level node inside the extension instance instead of a module. Note that this is the case not only if
|
||||
|
@ -1037,7 +1043,7 @@ cleanup:
|
|||
* @return LY_ERR value.
|
||||
*/
|
||||
static LY_ERR
|
||||
ly_path_compile_deref(const struct ly_ctx *ctx, const struct lysc_node *ctx_node,
|
||||
ly_path_compile_deref(const struct ly_ctx *ctx, const struct lysc_node *cur_node, const struct lysc_node *ctx_node,
|
||||
const struct lysc_ext_instance *top_ext, const struct lyxp_expr *expr, uint16_t oper, uint16_t target,
|
||||
LY_VALUE_FORMAT format, void *prefix_data, uint32_t *tok_idx, struct ly_path **path)
|
||||
{
|
||||
|
@ -1081,13 +1087,14 @@ ly_path_compile_deref(const struct ly_ctx *ctx, const struct lysc_node *ctx_node
|
|||
&path2), cleanup);
|
||||
node2 = path2[LY_ARRAY_COUNT(path2) - 1].node;
|
||||
if ((node2->nodetype != LYS_LEAF) && (node2->nodetype != LYS_LEAFLIST)) {
|
||||
LOGVAL(ctx, LYVE_XPATH, "The deref function target node \"%s\" is not leaf nor leaflist", node2->name);
|
||||
LOGVAL_PATH(ctx, cur_node, node2, LYVE_XPATH, "Deref function target node \"%s\" is not leaf nor leaflist.",
|
||||
node2->name);
|
||||
ret = LY_EVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
deref_leaf_node = (const struct lysc_node_leaf *)node2;
|
||||
if (deref_leaf_node->type->basetype != LY_TYPE_LEAFREF) {
|
||||
LOGVAL(ctx, LYVE_XPATH, "The deref function target node \"%s\" is not leafref", node2->name);
|
||||
LOGVAL_PATH(ctx, cur_node, node2, LYVE_XPATH, "Deref function target node \"%s\" is not leafref.", node2->name);
|
||||
ret = LY_EVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -1160,9 +1167,9 @@ _ly_path_compile(const struct ly_ctx *ctx, const struct lys_module *cur_mod, con
|
|||
const struct lysc_ext_instance *top_ext, const struct lyxp_expr *expr, ly_bool lref, uint16_t oper, uint16_t target,
|
||||
ly_bool limit_access_tree, LY_VALUE_FORMAT format, void *prefix_data, struct ly_path **path)
|
||||
{
|
||||
LY_ERR ret = LY_SUCCESS;
|
||||
LY_ERR rc = LY_SUCCESS;
|
||||
uint32_t tok_idx = 0, getnext_opts;
|
||||
const struct lysc_node *node2, *cur_node, *op;
|
||||
const struct lysc_node *node2, *cur_node, *op, *prev_ctx_node = NULL;
|
||||
struct ly_path *p = NULL;
|
||||
struct lysc_ext_instance *ext = NULL;
|
||||
|
||||
|
@ -1182,9 +1189,6 @@ _ly_path_compile(const struct ly_ctx *ctx, const struct lys_module *cur_mod, con
|
|||
|
||||
/* remember original context node */
|
||||
cur_node = ctx_node;
|
||||
if (cur_node) {
|
||||
LOG_LOCSET(cur_node, NULL);
|
||||
}
|
||||
|
||||
if (oper == LY_PATH_OPER_OUTPUT) {
|
||||
getnext_opts = LYS_GETNEXT_OUTPUT;
|
||||
|
@ -1195,7 +1199,7 @@ _ly_path_compile(const struct ly_ctx *ctx, const struct lys_module *cur_mod, con
|
|||
if (lref && (ly_ctx_get_options(ctx) & LY_CTX_LEAFREF_EXTENDED) &&
|
||||
(expr->tokens[tok_idx] == LYXP_TOKEN_FUNCNAME)) {
|
||||
/* deref function */
|
||||
ret = ly_path_compile_deref(ctx, ctx_node, top_ext, expr, oper, target, format, prefix_data, &tok_idx, path);
|
||||
rc = ly_path_compile_deref(ctx, cur_node, ctx_node, top_ext, expr, oper, target, format, prefix_data, &tok_idx, path);
|
||||
goto cleanup;
|
||||
} else if (expr->tokens[tok_idx] == LYXP_TOKEN_OPER_PATH) {
|
||||
/* absolute path */
|
||||
|
@ -1206,19 +1210,20 @@ _ly_path_compile(const struct ly_ctx *ctx, const struct lys_module *cur_mod, con
|
|||
/* relative path */
|
||||
if (!ctx_node) {
|
||||
LOGVAL(ctx, LYVE_XPATH, "No initial schema parent for a relative path.");
|
||||
ret = LY_EVALID;
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* go up the parents for leafref */
|
||||
while (lref && (expr->tokens[tok_idx] == LYXP_TOKEN_DDOT)) {
|
||||
if (!ctx_node) {
|
||||
LOGVAL(ctx, LYVE_XPATH, "Too many parent references in path.");
|
||||
ret = LY_EVALID;
|
||||
LOGVAL_PATH(ctx, cur_node, prev_ctx_node, LYVE_XPATH, "Too many parent references in path.");
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* get parent */
|
||||
prev_ctx_node = ctx_node;
|
||||
ctx_node = lysc_data_parent(ctx_node);
|
||||
|
||||
++tok_idx;
|
||||
|
@ -1231,63 +1236,66 @@ _ly_path_compile(const struct ly_ctx *ctx, const struct lys_module *cur_mod, con
|
|||
do {
|
||||
/* check last compiled inner node, whether it is uniquely identified (even key-less list) */
|
||||
if (p && !lref && (target == LY_PATH_TARGET_SINGLE) && (p->node->nodetype == LYS_LIST) && !p->predicates) {
|
||||
LOGVAL(ctx, LYVE_XPATH, "Predicate missing for %s \"%s\" in path.",
|
||||
LOGVAL_PATH(ctx, cur_node, prev_ctx_node, LYVE_XPATH, "Predicate missing for %s \"%s\" in path.",
|
||||
lys_nodetype2str(p->node->nodetype), p->node->name);
|
||||
ret = LY_EVALID;
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* NameTest */
|
||||
LY_CHECK_ERR_GOTO(lyxp_check_token(ctx, expr, tok_idx, LYXP_TOKEN_NAMETEST), ret = LY_EVALID, cleanup);
|
||||
LY_CHECK_ERR_GOTO(lyxp_check_token(ctx, expr, tok_idx, LYXP_TOKEN_NAMETEST), rc = LY_EVALID, cleanup);
|
||||
|
||||
/* get schema node */
|
||||
LY_CHECK_GOTO(ret = ly_path_compile_snode(ctx, cur_node, cur_mod, ctx_node, expr, tok_idx, format, prefix_data,
|
||||
LY_CHECK_GOTO(rc = ly_path_compile_snode(ctx, cur_node, cur_mod, ctx_node, expr, tok_idx, format, prefix_data,
|
||||
top_ext, getnext_opts, &node2, &ext), cleanup);
|
||||
++tok_idx;
|
||||
if ((op && (node2->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) && (node2 != op))) {
|
||||
LOGVAL(ctx, LYVE_XPATH, "Not found node \"%s\" in path.", node2->name);
|
||||
ret = LY_EVALID;
|
||||
LOGVAL_PATH(ctx, cur_node, prev_ctx_node, LYVE_XPATH, "Not found node \"%s\" in path.", node2->name);
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* next node */
|
||||
prev_ctx_node = ctx_node;
|
||||
ctx_node = node2;
|
||||
|
||||
/* new path segment */
|
||||
LY_ARRAY_NEW_GOTO(ctx, *path, p, ret, cleanup);
|
||||
LY_ARRAY_NEW_GOTO(ctx, *path, p, rc, cleanup);
|
||||
p->node = ctx_node;
|
||||
p->ext = ext;
|
||||
|
||||
/* compile any predicates */
|
||||
if (lref) {
|
||||
ret = ly_path_compile_predicate_leafref(ctx_node, cur_node, expr, &tok_idx, format, prefix_data);
|
||||
rc = ly_path_compile_predicate_leafref(ctx_node, cur_node, expr, &tok_idx, format, prefix_data);
|
||||
} else {
|
||||
ret = ly_path_compile_predicate(ctx, cur_node, cur_mod, ctx_node, expr, &tok_idx, format, prefix_data,
|
||||
rc = ly_path_compile_predicate(ctx, cur_node, cur_mod, ctx_node, expr, &tok_idx, format, prefix_data,
|
||||
&p->predicates);
|
||||
}
|
||||
LY_CHECK_GOTO(ret, cleanup);
|
||||
LY_CHECK_GOTO(rc, cleanup);
|
||||
} while (!lyxp_next_token(NULL, expr, &tok_idx, LYXP_TOKEN_OPER_PATH));
|
||||
|
||||
/* check leftover tokens */
|
||||
if (tok_idx < expr->used) {
|
||||
LOGVAL(ctx, LY_VCODE_XP_INTOK, lyxp_token2str(expr->tokens[tok_idx]), &expr->expr[expr->tok_pos[tok_idx]]);
|
||||
ret = LY_EVALID;
|
||||
LOGVAL_PATH(ctx, cur_node, ctx_node, LY_VCODE_XP_INTOK, lyxp_token2str(expr->tokens[tok_idx]),
|
||||
&expr->expr[expr->tok_pos[tok_idx]]);
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* check last compiled node */
|
||||
if (!lref && (target == LY_PATH_TARGET_SINGLE) && (p->node->nodetype & (LYS_LIST | LYS_LEAFLIST)) && !p->predicates) {
|
||||
LOGVAL(ctx, LYVE_XPATH, "Predicate missing for %s \"%s\" in path.",
|
||||
LOGVAL_PATH(ctx, cur_node, ctx_node, LYVE_XPATH, "Predicate missing for %s \"%s\" in path.",
|
||||
lys_nodetype2str(p->node->nodetype), p->node->name);
|
||||
ret = LY_EVALID;
|
||||
rc = LY_EVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (ret) {
|
||||
if (rc) {
|
||||
ly_path_free(*path);
|
||||
*path = NULL;
|
||||
}
|
||||
LOG_LOCBACK(cur_node ? 1 : 0, 0);
|
||||
return (ret == LY_ENOTFOUND) ? LY_EVALID : ret;
|
||||
return (rc == LY_ENOTFOUND) ? LY_EVALID : rc;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
|
@ -1304,6 +1312,8 @@ ly_path_compile_leafref(const struct ly_ctx *ctx, const struct lysc_node *ctx_no
|
|||
const struct lyxp_expr *expr, uint16_t oper, uint16_t target, LY_VALUE_FORMAT format, void *prefix_data,
|
||||
struct ly_path **path)
|
||||
{
|
||||
assert(ctx_node);
|
||||
|
||||
return _ly_path_compile(ctx, ctx_node->module, ctx_node, top_ext, expr, 1, oper, target, 1, format, prefix_data, path);
|
||||
}
|
||||
|
||||
|
|
25
src/path.h
25
src/path.h
|
@ -3,7 +3,7 @@
|
|||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief Path structure and manipulation routines.
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 CESNET, z.s.p.o.
|
||||
* Copyright (c) 2020 - 2025 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.
|
||||
|
@ -28,6 +28,25 @@ struct lysc_ext_instance;
|
|||
struct lysc_node;
|
||||
struct lyxp_expr;
|
||||
|
||||
/**
|
||||
* @brief Similar to LOGVAL, but also logs path of CUR_SCNODE and if not set, CTX_SCNODE, in this order.
|
||||
*
|
||||
* @param[in] CTX Context to use.
|
||||
* @param[in] CUR_SCNODE Current (original context) node.
|
||||
* @param[in] CTX_SCNODE Context node.
|
||||
*/
|
||||
#define LOGVAL_PATH(CTX, CUR_SCNODE, CTX_SCNODE, ...) \
|
||||
if ((CUR_SCNODE) || (CTX_SCNODE)) { \
|
||||
LOG_LOCSET((CUR_SCNODE) ? (CUR_SCNODE) : (CTX_SCNODE), NULL); \
|
||||
} \
|
||||
ly_vlog(CTX, NULL, __VA_ARGS__); \
|
||||
if ((CUR_SCNODE) || (CTX_SCNODE)) { \
|
||||
LOG_LOCBACK(1, 0); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Common types of predicates.
|
||||
*/
|
||||
enum ly_path_pred_type {
|
||||
LY_PATH_PREDTYPE_POSITION, /**< position predicate - [2] */
|
||||
LY_PATH_PREDTYPE_LIST, /**< keys predicate - [key1='val1'][key2='val2']... */
|
||||
|
@ -99,7 +118,7 @@ struct ly_path {
|
|||
* @param[in] ctx libyang context.
|
||||
* @param[in] ctx_node Optional context node, used for logging.
|
||||
* @param[in] str_path Path to parse.
|
||||
* @param[in] path_len Length of @p str_path.
|
||||
* @param[in] path_len Length of @p str_path, may be 0 if @p str_path is 0-terminated.
|
||||
* @param[in] lref Whether leafref is being parsed or not.
|
||||
* @param[in] begin Begin option (@ref path_begin_options).
|
||||
* @param[in] prefix Prefix option (@ref path_prefix_options).
|
||||
|
@ -116,7 +135,7 @@ LY_ERR ly_path_parse(const struct ly_ctx *ctx, const struct lysc_node *ctx_node,
|
|||
* @param[in] ctx libyang context.
|
||||
* @param[in] cur_node Optional current (original context) node, used for logging.
|
||||
* @param[in] str_path Path to parse.
|
||||
* @param[in] path_len Length of @p str_path.
|
||||
* @param[in] path_len Length of @p str_path, may be 0 if @p str_path is 0-terminated.
|
||||
* @param[in] prefix Prefix option (@ref path_prefix_options).
|
||||
* @param[in] pred Predicate option (@ref path_pred_options).
|
||||
* @param[out] expr Parsed path.
|
||||
|
|
|
@ -318,7 +318,8 @@ structure_aug_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext)
|
|||
|
||||
/* augment-structure must define some data-def-stmt */
|
||||
LY_LIST_FOR(ext->child, stmt) {
|
||||
if (stmt->kw & LY_STMT_DATA_NODE_MASK) {
|
||||
if (stmt->kw & (LY_STMT_CONTAINER | LY_STMT_LEAF | LY_STMT_LEAF_LIST | LY_STMT_LIST | LY_STMT_CHOICE |
|
||||
LY_STMT_ANYDATA | LY_STMT_ANYXML | LY_STMT_USES)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -685,7 +685,8 @@ lyplg_type_check_hints(uint32_t hints, const char *value, size_t value_len, LY_D
|
|||
case LY_TYPE_INT32:
|
||||
LY_CHECK_ARG_RET(NULL, base, LY_EINVAL);
|
||||
|
||||
if (!(hints & (LYD_VALHINT_DECNUM | LYD_VALHINT_OCTNUM | LYD_VALHINT_HEXNUM))) {
|
||||
if (!(hints & (LYD_VALHINT_DECNUM | LYD_VALHINT_OCTNUM | LYD_VALHINT_HEXNUM)) &&
|
||||
!(hints & LYD_VALHINT_STRING_DATATYPES)) {
|
||||
return ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Invalid non-number-encoded %s value \"%.*s\".",
|
||||
lys_datatype2str(type), (int)value_len, value);
|
||||
}
|
||||
|
@ -695,7 +696,8 @@ lyplg_type_check_hints(uint32_t hints, const char *value, size_t value_len, LY_D
|
|||
case LY_TYPE_INT64:
|
||||
LY_CHECK_ARG_RET(NULL, base, LY_EINVAL);
|
||||
|
||||
if (!(hints & LYD_VALHINT_NUM64)) {
|
||||
if (!(hints & LYD_VALHINT_NUM64) &&
|
||||
!(hints & LYD_VALHINT_STRING_DATATYPES)) {
|
||||
return ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Invalid non-num64-encoded %s value \"%.*s\".",
|
||||
lys_datatype2str(type), (int)value_len, value);
|
||||
}
|
||||
|
@ -714,7 +716,8 @@ lyplg_type_check_hints(uint32_t hints, const char *value, size_t value_len, LY_D
|
|||
}
|
||||
break;
|
||||
case LY_TYPE_BOOL:
|
||||
if (!(hints & LYD_VALHINT_BOOLEAN)) {
|
||||
if (!(hints & LYD_VALHINT_BOOLEAN) &&
|
||||
!(hints & LYD_VALHINT_STRING_DATATYPES)) {
|
||||
return ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Invalid non-boolean-encoded %s value \"%.*s\".",
|
||||
lys_datatype2str(type), (int)value_len, value);
|
||||
}
|
||||
|
|
|
@ -150,6 +150,48 @@ lyb_parse_union(const void *lyb_data, size_t lyb_data_len, uint32_t *type_idx, c
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief For leafref failures, ensure the appropriate error is propagated, not a type validation failure.
|
||||
*
|
||||
* RFC7950 Section 15.5 defines the appropriate error app tag of "require-instance".
|
||||
*
|
||||
* @param[in,out] err Error record to be updated.
|
||||
* @param[in] type Leafref type used to extract target path.
|
||||
* @param[in] value Value attempted to be stored.
|
||||
* @param[in] value_len Length of @p value.
|
||||
* @return LY_ERR value. Only possible errors are LY_SUCCESS and LY_EMEM.
|
||||
*/
|
||||
static LY_ERR
|
||||
union_update_lref_err(struct ly_err_item *err, const struct lysc_type *type, const void *value, size_t value_len)
|
||||
{
|
||||
const struct lysc_type_leafref *lref;
|
||||
char *valstr = NULL;
|
||||
int r;
|
||||
|
||||
if (!err || (type->basetype != LY_TYPE_LEAFREF)) {
|
||||
/* nothing to do */
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
lref = (const struct lysc_type_leafref *)type;
|
||||
|
||||
/* update error-app-tag */
|
||||
free(err->apptag);
|
||||
err->apptag = strdup("instance-required");
|
||||
LY_CHECK_ERR_RET(!err->apptag, LOGMEM(NULL), LY_EMEM);
|
||||
|
||||
valstr = strndup((const char *)value, value_len);
|
||||
LY_CHECK_ERR_RET(!valstr, LOGMEM(NULL), LY_EMEM);
|
||||
|
||||
/* update error-message */
|
||||
free(err->msg);
|
||||
r = asprintf(&err->msg, LY_ERRMSG_NOLREF_VAL, valstr, lyxp_get_expr(lref->path));
|
||||
free(valstr);
|
||||
LY_CHECK_ERR_RET(r == -1, LOGMEM(NULL), LY_EMEM);
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Store (and validate) subvalue as a specific type.
|
||||
*
|
||||
|
@ -187,10 +229,13 @@ union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint3
|
|||
/* value of another type, first store the value properly and then use its JSON value for parsing */
|
||||
rc = type_u->types[ti]->plugin->store(ctx, type_u->types[ti], value, value_len, LYPLG_TYPE_STORE_ONLY,
|
||||
subvalue->format, subvalue->prefix_data, subvalue->hints, subvalue->ctx_node, &subvalue->value, unres, err);
|
||||
if ((rc != LY_SUCCESS) && (rc != LY_EINCOMPLETE)) {
|
||||
if (rc && (rc != LY_EINCOMPLETE)) {
|
||||
/* clear any leftover/freed garbage */
|
||||
memset(&subvalue->value, 0, sizeof subvalue->value);
|
||||
return rc;
|
||||
|
||||
/* if this is a leafref, lets make sure we propagate the appropriate error, and not a type validation failure */
|
||||
union_update_lref_err(*err, type_u->types[ti], value, value_len);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
assert(subvalue->value.realtype);
|
||||
|
@ -219,16 +264,16 @@ union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint3
|
|||
if (options & LYPLG_TYPE_STORE_ONLY) {
|
||||
opts |= LYPLG_TYPE_STORE_ONLY;
|
||||
}
|
||||
if (dynamic) {
|
||||
opts |= LYPLG_TYPE_STORE_DYNAMIC;
|
||||
}
|
||||
|
||||
rc = type->plugin->store(ctx, type, value, value_len, opts, format, prefix_data, subvalue->hints,
|
||||
subvalue->ctx_node, &subvalue->value, unres, err);
|
||||
if ((rc != LY_SUCCESS) && (rc != LY_EINCOMPLETE)) {
|
||||
if (rc && (rc != LY_EINCOMPLETE)) {
|
||||
/* clear any leftover/freed garbage */
|
||||
memset(&subvalue->value, 0, sizeof subvalue->value);
|
||||
return rc;
|
||||
|
||||
/* if this is a leafref, lets make sure we propagate the appropriate error, and not a type validation failure */
|
||||
union_update_lref_err(*err, type, value, value_len);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (validate && (rc == LY_EINCOMPLETE)) {
|
||||
|
@ -237,9 +282,14 @@ union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint3
|
|||
if (rc) {
|
||||
/* validate failed, we need to free the stored value */
|
||||
type->plugin->free(ctx, &subvalue->value);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (dynamic) {
|
||||
free((void *)value);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -267,8 +317,9 @@ union_find_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct
|
|||
LY_ARRAY_COUNT_TYPE u;
|
||||
struct ly_err_item **errs = NULL, *e;
|
||||
uint32_t *prev_lo, temp_lo = 0;
|
||||
char *msg = NULL;
|
||||
char *msg = NULL, *err_app_tag = NULL;
|
||||
int msg_len = 0;
|
||||
ly_bool use_err_app_tag = 0;
|
||||
|
||||
*err = NULL;
|
||||
|
||||
|
@ -299,6 +350,8 @@ union_find_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct
|
|||
}
|
||||
if (msg_len == -1) {
|
||||
LY_CHECK_ERR_GOTO(!errs, ret = LY_EMEM, cleanup);
|
||||
/* for further actions in function msg_len is just 0 */
|
||||
msg_len = 0;
|
||||
}
|
||||
for (u = 0; u < LY_ARRAY_COUNT(type_u->types); ++u) {
|
||||
if (!errs[u]) {
|
||||
|
@ -306,12 +359,27 @@ union_find_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct
|
|||
continue;
|
||||
}
|
||||
|
||||
/* use an app-tag if all the types set it or set none */
|
||||
if (errs[u]->apptag) {
|
||||
if (!err_app_tag) {
|
||||
err_app_tag = strdup(errs[u]->apptag);
|
||||
LY_CHECK_ERR_GOTO(!err_app_tag, ret = LY_EMEM, cleanup);
|
||||
use_err_app_tag = 1;
|
||||
} else if (strcmp(errs[u]->apptag, err_app_tag)) {
|
||||
use_err_app_tag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
msg = ly_realloc(msg, msg_len + 4 + strlen(type_u->types[u]->plugin->id) + 2 + strlen(errs[u]->msg) + 2);
|
||||
LY_CHECK_ERR_GOTO(!msg, ret = LY_EMEM, cleanup);
|
||||
msg_len += sprintf(msg + msg_len, " %s: %s\n", type_u->types[u]->plugin->id, errs[u]->msg);
|
||||
}
|
||||
|
||||
ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "%s", msg);
|
||||
if (!use_err_app_tag) {
|
||||
free(err_app_tag);
|
||||
err_app_tag = NULL;
|
||||
}
|
||||
ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, err_app_tag, "%s", msg);
|
||||
} else if (type_idx) {
|
||||
*type_idx = u;
|
||||
}
|
||||
|
@ -496,26 +564,33 @@ lyplg_type_compare_union(const struct ly_ctx *ctx, const struct lyd_value *val1,
|
|||
LIBYANG_API_DEF int
|
||||
lyplg_type_sort_union(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
|
||||
{
|
||||
int rc = LY_SUCCESS;
|
||||
int rc;
|
||||
LY_ARRAY_COUNT_TYPE u;
|
||||
struct lysc_type **types;
|
||||
struct lysc_type **types, *type;
|
||||
|
||||
if (val1->subvalue->value.realtype == val2->subvalue->value.realtype) {
|
||||
return val1->subvalue->value.realtype->plugin->sort(ctx, &val1->subvalue->value, &val2->subvalue->value);
|
||||
}
|
||||
|
||||
/* compare according to the order of types */
|
||||
rc = 0;
|
||||
types = ((struct lysc_type_union *)val1->realtype)->types;
|
||||
LY_ARRAY_FOR(types, u) {
|
||||
if (types[u] == val1->subvalue->value.realtype) {
|
||||
if (types[u]->basetype == LY_TYPE_LEAFREF) {
|
||||
type = ((struct lysc_type_leafref *)types[u])->realtype;
|
||||
} else {
|
||||
type = types[u];
|
||||
}
|
||||
|
||||
if (type == val1->subvalue->value.realtype) {
|
||||
rc = 1;
|
||||
break;
|
||||
} else if (types[u] == val2->subvalue->value.realtype) {
|
||||
} else if (type == val2->subvalue->value.realtype) {
|
||||
rc = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(rc != 0);
|
||||
assert(rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -590,7 +590,7 @@ struct trt_fp_read {
|
|||
.module_name = tro_read_module_name, \
|
||||
.node = troc_read_node, \
|
||||
.if_sibling_exists = troc_read_if_sibling_exists, \
|
||||
.if_parent_exists = tro_read_if_sibling_exists \
|
||||
.if_parent_exists = tro_read_if_parent_exists \
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -601,7 +601,7 @@ struct trt_fp_read {
|
|||
.module_name = tro_read_module_name, \
|
||||
.node = trop_read_node, \
|
||||
.if_sibling_exists = trop_read_if_sibling_exists, \
|
||||
.if_parent_exists = tro_read_if_sibling_exists \
|
||||
.if_parent_exists = tro_read_if_parent_exists \
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
|
@ -781,6 +781,7 @@ typedef const char *(*trt_get_charptr_func)(const struct lysp_node *pn);
|
|||
*/
|
||||
struct tro_getters {
|
||||
uint16_t (*nodetype)(const void *); /**< Get nodetype. */
|
||||
uint16_t (*lysp_flags)(const void *); /**< Get flags from lysp_node. */
|
||||
const void *(*next)(const void *); /**< Get sibling. */
|
||||
const void *(*parent)(const void *); /**< Get parent. */
|
||||
const void *(*child)(const void *); /**< Get child. */
|
||||
|
@ -1947,6 +1948,16 @@ trop_nodetype(const void *node)
|
|||
return ((const struct lysp_node *)node)->nodetype;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get lysp_node flags.
|
||||
* @param[in] node is any lysp_node.
|
||||
*/
|
||||
static uint16_t
|
||||
trop_flags(const void *node)
|
||||
{
|
||||
return ((const struct lysp_node *)node)->flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sibling.
|
||||
* @param[in] node is any lysp_node.
|
||||
|
@ -2026,6 +2037,7 @@ trop_init_getters(void)
|
|||
{
|
||||
return (struct tro_getters) {
|
||||
.nodetype = trop_nodetype,
|
||||
.lysp_flags = trop_flags,
|
||||
.next = trop_next,
|
||||
.parent = trop_parent,
|
||||
.child = trop_child,
|
||||
|
@ -2046,6 +2058,23 @@ troc_nodetype(const void *node)
|
|||
return ((const struct lysc_node *)node)->nodetype;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get lysp_node flags.
|
||||
* @param[in] node is any lysc_node.
|
||||
*/
|
||||
static uint16_t
|
||||
troc_lysp_flags(const void *node)
|
||||
{
|
||||
const struct lysc_node *cn;
|
||||
|
||||
cn = (const struct lysc_node *)node;
|
||||
if (TRP_TREE_CTX_LYSP_NODE_PRESENT(cn)) {
|
||||
return TRP_TREE_CTX_GET_LYSP_NODE(cn)->flags;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sibling.
|
||||
* @param[in] node is any lysc_node.
|
||||
|
@ -2125,6 +2154,7 @@ troc_init_getters(void)
|
|||
{
|
||||
return (struct tro_getters) {
|
||||
.nodetype = troc_nodetype,
|
||||
.lysp_flags = troc_lysp_flags,
|
||||
.next = troc_next,
|
||||
.parent = troc_parent,
|
||||
.child = troc_child,
|
||||
|
@ -2272,6 +2302,8 @@ tro_next_sibling(const void *node, const struct trt_tree_ctx *tc)
|
|||
plugin_ctx = tc->plugin_ctx;
|
||||
if (sibl && tro_set_node_overr(tc->lysc_tree, sibl, 1, &plugin_ctx) && plugin_ctx.filtered) {
|
||||
return tro_next_sibling(sibl, tc);
|
||||
} else if (sibl && (get.lysp_flags(node) & LYS_INTERNAL)) {
|
||||
return tro_next_sibling(sibl, tc);
|
||||
}
|
||||
|
||||
return sibl;
|
||||
|
@ -2328,6 +2360,8 @@ tro_next_child(const void *node, const struct trt_tree_ctx *tc)
|
|||
plugin_ctx = tc->plugin_ctx;
|
||||
if (child && tro_set_node_overr(tc->lysc_tree, child, 1, &plugin_ctx) && plugin_ctx.filtered) {
|
||||
return tro_next_sibling(child, tc);
|
||||
} else if (child && (get.lysp_flags(node) & LYS_INTERNAL)) {
|
||||
return tro_next_sibling(child, tc);
|
||||
}
|
||||
|
||||
return child;
|
||||
|
@ -2605,7 +2639,7 @@ tro_read_module_name(const struct trt_tree_ctx *tc)
|
|||
}
|
||||
|
||||
static ly_bool
|
||||
tro_read_if_sibling_exists(const struct trt_tree_ctx *tc)
|
||||
tro_read_if_parent_exists(const struct trt_tree_ctx *tc)
|
||||
{
|
||||
const void *parent;
|
||||
|
||||
|
@ -3118,7 +3152,11 @@ trop_modi_first_sibling(struct trt_parent_cache ca, struct trt_tree_ctx *tc)
|
|||
default:
|
||||
assert(0);
|
||||
}
|
||||
node = trop_read_node(ca, tc);
|
||||
if (tc->pn && (trop_flags(tc->pn) & LYS_INTERNAL)) {
|
||||
node = trop_modi_next_sibling(ca, tc);
|
||||
} else {
|
||||
node = trop_read_node(ca, tc);
|
||||
}
|
||||
}
|
||||
|
||||
if (tc->plugin_ctx.filtered) {
|
||||
|
@ -3440,7 +3478,11 @@ troc_modi_first_sibling(struct trt_parent_cache ca, struct trt_tree_ctx *tc)
|
|||
default:
|
||||
assert(0);
|
||||
}
|
||||
node = troc_read_node(ca, tc);
|
||||
if (tc->cn && (troc_lysp_flags(tc->cn) & LYS_INTERNAL)) {
|
||||
node = troc_modi_next_sibling(ca, tc);
|
||||
} else {
|
||||
node = troc_read_node(ca, tc);
|
||||
}
|
||||
}
|
||||
|
||||
if (tc->plugin_ctx.filtered) {
|
||||
|
|
|
@ -463,6 +463,7 @@ no_content:
|
|||
pctx->options = prev_opts;
|
||||
break;
|
||||
case LYD_ANYDATA_STRING:
|
||||
case LYD_ANYDATA_JSON:
|
||||
/* escape XML-sensitive characters */
|
||||
if (!any->value.str[0]) {
|
||||
goto no_content;
|
||||
|
@ -478,9 +479,8 @@ no_content:
|
|||
}
|
||||
ly_print_(pctx->out, ">%s", any->value.str);
|
||||
break;
|
||||
case LYD_ANYDATA_JSON:
|
||||
case LYD_ANYDATA_LYB:
|
||||
/* JSON and LYB format is not supported */
|
||||
/* LYB format is not supported */
|
||||
LOGWRN(pctx->ctx, "Unable to print anydata content (type %d) as XML.", any->value_type);
|
||||
goto no_content;
|
||||
}
|
||||
|
|
|
@ -2269,6 +2269,10 @@ yang_print_parsed_body(struct lys_ypr_ctx *pctx, const struct lysp_module *modp)
|
|||
YPR_EXTRA_LINE(modp->groupings, pctx);
|
||||
|
||||
LY_LIST_FOR(modp->data, data) {
|
||||
if (data->flags & LYS_INTERNAL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
YPR_EXTRA_LINE_PRINT(pctx);
|
||||
yprp_node(pctx, data);
|
||||
}
|
||||
|
|
|
@ -1367,6 +1367,10 @@ yin_print_parsed_body(struct lys_ypr_ctx *pctx, const struct lysp_module *modp)
|
|||
}
|
||||
|
||||
LY_LIST_FOR(modp->data, data) {
|
||||
if (data->flags & LYS_INTERNAL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
yprp_node(pctx, data);
|
||||
}
|
||||
|
||||
|
|
|
@ -937,6 +937,7 @@ lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc
|
|||
{
|
||||
LY_ERR ret;
|
||||
uint32_t options;
|
||||
struct lyd_value *val;
|
||||
struct ly_err_item *err = NULL;
|
||||
|
||||
options = (ctx->ctx->flags & LY_CTX_REF_IMPLEMENTED) ? LYPLG_TYPE_STORE_IMPLEMENT : 0;
|
||||
|
@ -963,11 +964,16 @@ lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc
|
|||
}
|
||||
|
||||
LY_ATOMIC_INC_BARRIER(((struct lysc_type *)storage->realtype)->refcount);
|
||||
if (storage->realtype->basetype == LY_TYPE_INST) {
|
||||
if (storage->realtype->basetype == LY_TYPE_UNION) {
|
||||
val = &storage->subvalue->value;
|
||||
} else {
|
||||
val = storage;
|
||||
}
|
||||
if (val->realtype->basetype == LY_TYPE_INST) {
|
||||
/* ly_path includes references to other nodes, in case they are in foreign modules, the context would
|
||||
* need to be freed in specific order to avoid accessing freed memory, so just avoid storing it */
|
||||
ly_path_free(storage->target);
|
||||
storage->target = NULL;
|
||||
ly_path_free(val->target);
|
||||
val->target = NULL;
|
||||
}
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
@ -1537,11 +1543,13 @@ lys_compile_depset_r(struct ly_ctx *ctx, struct ly_set *dep_set, struct lys_glob
|
|||
LY_CHECK_GOTO(ret = lys_compile(mod, &unres->ds_unres), cleanup);
|
||||
}
|
||||
|
||||
resolve_unres:
|
||||
/* resolve dep set unres */
|
||||
ret = lys_compile_unres_depset(ctx, unres);
|
||||
lys_compile_unres_depset_erase(ctx, unres);
|
||||
|
||||
if (ret == LY_ERECOMPILE) {
|
||||
/* new module is implemented, discard current dep set unres and recompile the whole dep set */
|
||||
lys_compile_unres_depset_erase(ctx, unres);
|
||||
/* new module is implemented referencing previously compiled modules, recompile the whole dep set */
|
||||
return lys_compile_depset_r(ctx, dep_set, unres);
|
||||
} else if (ret) {
|
||||
/* error */
|
||||
|
@ -1551,6 +1559,13 @@ lys_compile_depset_r(struct ly_ctx *ctx, struct ly_set *dep_set, struct lys_glob
|
|||
/* success, unset the flags of all the modules in the dep set */
|
||||
for (i = 0; i < dep_set->count; ++i) {
|
||||
mod = dep_set->objs[i];
|
||||
|
||||
if (mod->to_compile && !mod->compiled) {
|
||||
/* new module is implemented but does not require recompilation of the whole dep set */
|
||||
LY_CHECK_GOTO(ret = lys_compile(mod, &unres->ds_unres), cleanup);
|
||||
goto resolve_unres;
|
||||
}
|
||||
|
||||
mod->to_compile = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -365,12 +365,12 @@ lysc_range_dup(struct lysc_ctx *ctx, const struct lysc_range *orig, struct ly_se
|
|||
dup = calloc(1, sizeof *dup);
|
||||
LY_CHECK_ERR_RET(!dup, LOGMEM(ctx->ctx), NULL);
|
||||
if (orig->parts) {
|
||||
LY_ARRAY_CREATE_GOTO(ctx->ctx, dup->parts, LY_ARRAY_COUNT(orig->parts), ret, cleanup);
|
||||
LY_ARRAY_CREATE_GOTO(ctx->ctx, dup->parts, LY_ARRAY_COUNT(orig->parts), ret, error);
|
||||
(*((LY_ARRAY_COUNT_TYPE *)(dup->parts) - 1)) = LY_ARRAY_COUNT(orig->parts);
|
||||
memcpy(dup->parts, orig->parts, LY_ARRAY_COUNT(dup->parts) * sizeof *dup->parts);
|
||||
}
|
||||
DUP_STRING_GOTO(ctx->ctx, orig->eapptag, dup->eapptag, ret, cleanup);
|
||||
DUP_STRING_GOTO(ctx->ctx, orig->emsg, dup->emsg, ret, cleanup);
|
||||
DUP_STRING_GOTO(ctx->ctx, orig->eapptag, dup->eapptag, ret, error);
|
||||
DUP_STRING_GOTO(ctx->ctx, orig->emsg, dup->emsg, ret, error);
|
||||
|
||||
/* collect all range extensions */
|
||||
if (tpdf_chain->count > tpdf_chain_last) {
|
||||
|
@ -381,15 +381,17 @@ lysc_range_dup(struct lysc_ctx *ctx, const struct lysc_range *orig, struct ly_se
|
|||
if (!tpdf_item->tpdf->type.range) {
|
||||
continue;
|
||||
}
|
||||
COMPILE_EXTS_GOTO(ctx, tpdf_item->tpdf->type.range->exts, dup->exts, dup, ret, cleanup);
|
||||
COMPILE_EXTS_GOTO(ctx, tpdf_item->tpdf->type.range->exts, dup->exts, dup, ret, error);
|
||||
} while (i > tpdf_chain_last);
|
||||
}
|
||||
|
||||
return dup;
|
||||
|
||||
cleanup:
|
||||
free(dup);
|
||||
(void) ret; /* set but not used due to the return type */
|
||||
error:
|
||||
if (dup) {
|
||||
lysc_range_free(&ctx->free_ctx, dup);
|
||||
free(dup);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1518,7 +1520,7 @@ lys_compile_type_enums(struct lysc_ctx *ctx, const struct lysp_type_enum *enums_
|
|||
}
|
||||
}
|
||||
|
||||
/* save highest value for auto assing */
|
||||
/* save highest value for auto assign */
|
||||
if (highest_value < cur_val) {
|
||||
highest_value = cur_val;
|
||||
}
|
||||
|
@ -1553,7 +1555,7 @@ lys_compile_type_enums(struct lysc_ctx *ctx, const struct lysp_type_enum *enums_
|
|||
}
|
||||
}
|
||||
|
||||
/* save highest position for auto assing */
|
||||
/* save highest position for auto assign */
|
||||
if (highest_position < cur_pos) {
|
||||
highest_position = cur_pos;
|
||||
}
|
||||
|
@ -1583,7 +1585,17 @@ lys_compile_type_enums(struct lysc_ctx *ctx, const struct lysp_type_enum *enums_
|
|||
DUP_STRING_GOTO(ctx->ctx, enums_p[u].name, e->name, ret, done);
|
||||
DUP_STRING_GOTO(ctx->ctx, enums_p[u].dsc, e->dsc, ret, done);
|
||||
DUP_STRING_GOTO(ctx->ctx, enums_p[u].ref, e->ref, ret, done);
|
||||
e->flags = (enums_p[u].flags & LYS_FLAGS_COMPILED_MASK) | (basetype == LY_TYPE_ENUM ? LYS_IS_ENUM : 0);
|
||||
|
||||
/* copy flags except for status */
|
||||
e->flags = (enums_p[u].flags & LYS_FLAGS_COMPILED_MASK) & ~LYS_STATUS_MASK;
|
||||
|
||||
/* compile status */
|
||||
LY_CHECK_RET(lys_compile_status(ctx, enums_p[u].flags, 0, 0, NULL, (basetype == LY_TYPE_ENUM) ? "enum" : "bit",
|
||||
&e->flags));
|
||||
|
||||
/* enum/bit flag */
|
||||
e->flags |= (basetype == LY_TYPE_ENUM) ? LYS_IS_ENUM : 0;
|
||||
|
||||
if (basetype == LY_TYPE_ENUM) {
|
||||
e->value = cur_val;
|
||||
} else {
|
||||
|
@ -4127,49 +4139,82 @@ cleanup:
|
|||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate path of a grouping for logging.
|
||||
*
|
||||
* @param[in] ctx Compile context.
|
||||
* @param[in] node Grouping node.
|
||||
* @param[out] path Generated path.
|
||||
* @return Length of the generated @p path;
|
||||
* @return -1 on error.
|
||||
*/
|
||||
static int
|
||||
lys_compile_grouping_pathlog(struct lysc_ctx *ctx, struct lysp_node *node, char **path)
|
||||
{
|
||||
struct lysp_node *iter;
|
||||
int len = 0;
|
||||
int len = 0, r;
|
||||
char *s, *id;
|
||||
|
||||
*path = NULL;
|
||||
for (iter = node; iter && len >= 0; iter = iter->parent) {
|
||||
char *s = *path;
|
||||
char *id;
|
||||
|
||||
for (iter = node; iter && (len >= 0); iter = iter->parent) {
|
||||
s = *path;
|
||||
|
||||
/* next node segment */
|
||||
switch (iter->nodetype) {
|
||||
case LYS_USES:
|
||||
LY_CHECK_RET(asprintf(&id, "{uses='%s'}", iter->name) == -1, -1);
|
||||
r = asprintf(&id, "{uses='%s'}", iter->name);
|
||||
break;
|
||||
case LYS_GROUPING:
|
||||
LY_CHECK_RET(asprintf(&id, "{grouping='%s'}", iter->name) == -1, -1);
|
||||
r = asprintf(&id, "{grouping='%s'}", iter->name);
|
||||
break;
|
||||
case LYS_AUGMENT:
|
||||
LY_CHECK_RET(asprintf(&id, "{augment='%s'}", iter->name) == -1, -1);
|
||||
r = asprintf(&id, "{augment='%s'}", iter->name);
|
||||
break;
|
||||
default:
|
||||
id = strdup(iter->name);
|
||||
r = id ? 1 : -1;
|
||||
break;
|
||||
}
|
||||
if (r == -1) {
|
||||
len = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* append the segment to the path */
|
||||
if (!iter->parent) {
|
||||
/* print prefix */
|
||||
len = asprintf(path, "/%s:%s%s", ctx->cur_mod->name, id, s ? s : "");
|
||||
r = asprintf(path, "/%s:%s%s", ctx->cur_mod->name, id, s ? s : "");
|
||||
} else {
|
||||
/* prefix is the same as in parent */
|
||||
len = asprintf(path, "/%s%s", id, s ? s : "");
|
||||
r = asprintf(path, "/%s%s", id, s ? s : "");
|
||||
}
|
||||
free(s);
|
||||
free(id);
|
||||
if (r == -1) {
|
||||
len = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* remember the length of the full path */
|
||||
len = r;
|
||||
}
|
||||
|
||||
if (!len) {
|
||||
/* root node path */
|
||||
*path = strdup("/");
|
||||
if (!*path) {
|
||||
len = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
len = 1;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (len < 0) {
|
||||
free(*path);
|
||||
*path = NULL;
|
||||
} else if (len == 0) {
|
||||
*path = strdup("/");
|
||||
len = 1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
|
315
src/tree_data.c
315
src/tree_data.c
|
@ -222,10 +222,14 @@ LIBYANG_API_DEF LY_ERR
|
|||
lyd_parse_data(const struct ly_ctx *ctx, struct lyd_node *parent, struct ly_in *in, LYD_FORMAT format,
|
||||
uint32_t parse_options, uint32_t validate_options, struct lyd_node **tree)
|
||||
{
|
||||
LY_CHECK_ARG_RET(ctx, ctx, in, parent || tree, LY_EINVAL);
|
||||
LY_CHECK_ARG_RET(ctx, ctx || parent, in, parent || tree, LY_EINVAL);
|
||||
LY_CHECK_ARG_RET(ctx, !(parse_options & ~LYD_PARSE_OPTS_MASK), LY_EINVAL);
|
||||
LY_CHECK_ARG_RET(ctx, !(validate_options & ~LYD_VALIDATE_OPTS_MASK), LY_EINVAL);
|
||||
|
||||
if (!ctx) {
|
||||
ctx = LYD_CTX(parent);
|
||||
}
|
||||
|
||||
return lyd_parse(ctx, NULL, parent, tree, in, format, parse_options, validate_options, NULL);
|
||||
}
|
||||
|
||||
|
@ -1035,7 +1039,7 @@ LIBYANG_API_DEF LY_ERR
|
|||
lyd_insert_child(struct lyd_node *parent, struct lyd_node *node)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, parent, node, !parent->schema || (parent->schema->nodetype & LYD_NODE_INNER), LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(LYD_CTX(parent), LYD_CTX(node), LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, LYD_CTX(parent), LYD_CTX(node), LY_EINVAL);
|
||||
|
||||
LY_CHECK_RET(lyd_insert_check_schema(parent->schema, NULL, node->schema));
|
||||
|
||||
|
@ -1101,7 +1105,7 @@ LIBYANG_API_DEF LY_ERR
|
|||
lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, sibling, node, sibling != node, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(LYD_CTX(sibling), LYD_CTX(node), LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, LYD_CTX(sibling), LYD_CTX(node), LY_EINVAL);
|
||||
|
||||
LY_CHECK_RET(lyd_insert_check_schema(NULL, sibling->schema, node->schema));
|
||||
|
||||
|
@ -1125,7 +1129,7 @@ LIBYANG_API_DEF LY_ERR
|
|||
lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, sibling, node, sibling != node, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(LYD_CTX(sibling), LYD_CTX(node), LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, LYD_CTX(sibling), LYD_CTX(node), LY_EINVAL);
|
||||
|
||||
LY_CHECK_RET(lyd_insert_check_schema(NULL, sibling->schema, node->schema));
|
||||
|
||||
|
@ -2002,6 +2006,121 @@ lyd_find_schema_ctx(const struct lysc_node *schema, const struct ly_ctx *trg_ctx
|
|||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the top-level context of a subtree of node. Handles extension data nodes.
|
||||
*
|
||||
* @param[in] node Node to use.
|
||||
* @return
|
||||
*/
|
||||
static const struct ly_ctx *
|
||||
lyd_dup_get_top_ctx(const struct lyd_node *node)
|
||||
{
|
||||
const struct lyd_node *par;
|
||||
|
||||
par = node;
|
||||
while (par && !(par->flags & LYD_EXT)) {
|
||||
par = lyd_parent(par);
|
||||
}
|
||||
|
||||
if (par && lyd_parent(par)) {
|
||||
/* context of the first non-extension parent */
|
||||
return LYD_CTX(lyd_parent(par));
|
||||
}
|
||||
|
||||
/* context of the node, all the parents have it */
|
||||
return LYD_CTX(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find (update) the target context for the next node, if needed.
|
||||
*
|
||||
* @param[in] orig_node First extension data node being processed from the original tree.
|
||||
* @param[in] dup_parent Duplicated parent of @p orig_node, set if @p dup_sparent is NULL.
|
||||
* @param[in] dup_sparent Schema node of the duplicated parent of @p orig_node, set if @p dup_parent is NULL.
|
||||
* @param[in,out] trg_ctx Target context, may be updated.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
static LY_ERR
|
||||
lyd_find_ext_ctx(const struct lyd_node *orig_node, const struct lyd_node *dup_parent,
|
||||
const struct lysc_node *dup_sparent, const struct ly_ctx **trg_ctx)
|
||||
{
|
||||
LY_ERR r;
|
||||
const struct lysc_node *snode;
|
||||
char *path;
|
||||
|
||||
assert(orig_node && (orig_node->flags & LYD_EXT) && *trg_ctx);
|
||||
|
||||
if (!lyd_parent(orig_node)) {
|
||||
/* treat as a non-extension node */
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
assert(dup_parent || dup_sparent);
|
||||
|
||||
if (LYD_CTX(lyd_parent(orig_node)) == *trg_ctx) {
|
||||
/* same contexts, just extension data */
|
||||
*trg_ctx = LYD_CTX(orig_node);
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
/* find the extension context to use from the target context */
|
||||
r = ly_nested_ext_schema(dup_parent, dup_sparent, orig_node->schema->module->name, strlen(orig_node->schema->module->name),
|
||||
LY_VALUE_JSON, NULL, LYD_NAME(orig_node), strlen(LYD_NAME(orig_node)), &snode, NULL);
|
||||
if (r == LY_ENOT) {
|
||||
path = lyd_path(orig_node, LYD_PATH_STD, NULL, 0);
|
||||
LOGERR(*trg_ctx, LY_ENOTFOUND, "Schema node of an extension node \"%s\" not found in the target context.", path);
|
||||
free(path);
|
||||
return LY_ENOTFOUND;
|
||||
} else if (r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* update the context */
|
||||
*trg_ctx = snode->module->ctx;
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find (update) the target context for the specific nested node, if needed.
|
||||
*
|
||||
* @param[in] orig_node Nested data node being processed from the original tree.
|
||||
* @param[in,out] trg_ctx Target context, may be updated.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
static LY_ERR
|
||||
lyd_find_ext_ctx_nested(const struct lyd_node *orig_node, const struct ly_ctx **trg_ctx)
|
||||
{
|
||||
const struct lyd_node *parent;
|
||||
const struct lysc_node *sparent;
|
||||
char *path;
|
||||
|
||||
if (lyd_dup_get_top_ctx(orig_node) == *trg_ctx) {
|
||||
/* it is the same context, use the same one for extension data nodes as well (if node is nested in such data) */
|
||||
*trg_ctx = LYD_CTX(orig_node);
|
||||
} else {
|
||||
/* not the same context, need to find the right one */
|
||||
parent = orig_node;
|
||||
while (parent && !(parent->flags & LYD_EXT)) {
|
||||
parent = lyd_parent(parent);
|
||||
}
|
||||
|
||||
if (parent && lyd_parent(parent)) {
|
||||
/* find the parent schema node in the target context */
|
||||
path = lysc_path(lyd_parent(parent)->schema, LYSC_PATH_DATA, NULL, 0);
|
||||
sparent = lys_find_path(*trg_ctx, NULL, path, 0);
|
||||
if (!sparent) {
|
||||
LOGERR(*trg_ctx, LY_ENOTFOUND, "Node \"%s\" was not found in the target context.", path);
|
||||
free(path);
|
||||
return LY_ENOTFOUND;
|
||||
}
|
||||
free(path);
|
||||
|
||||
LY_CHECK_RET(lyd_find_ext_ctx(parent, NULL, sparent, trg_ctx));
|
||||
}
|
||||
}
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Duplicate a single node and connect it into @p parent (if present) or last of @p first siblings.
|
||||
*
|
||||
|
@ -2020,7 +2139,7 @@ static LY_ERR
|
|||
lyd_dup_r(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_node *parent, uint32_t insert_order,
|
||||
struct lyd_node **first, uint32_t options, struct lyd_node **dup_p)
|
||||
{
|
||||
LY_ERR ret;
|
||||
LY_ERR rc = LY_SUCCESS;
|
||||
struct lyd_node *dup = NULL;
|
||||
struct lyd_meta *meta;
|
||||
struct lyd_attr *attr;
|
||||
|
@ -2036,8 +2155,10 @@ lyd_dup_r(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_
|
|||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
/* we need to use the same context */
|
||||
trg_ctx = LYD_CTX(node);
|
||||
if (parent) {
|
||||
/* update the context */
|
||||
LY_CHECK_GOTO(rc = lyd_find_ext_ctx(node, parent, NULL, &trg_ctx), cleanup);
|
||||
} /* else called from lyd_dup_get_local_parent() and the context is correct */
|
||||
}
|
||||
|
||||
if (!node->schema) {
|
||||
|
@ -2062,11 +2183,11 @@ lyd_dup_r(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_
|
|||
break;
|
||||
default:
|
||||
LOGINT(trg_ctx);
|
||||
ret = LY_EINT;
|
||||
goto error;
|
||||
rc = LY_EINT;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
LY_CHECK_ERR_GOTO(!dup, LOGMEM(trg_ctx); ret = LY_EMEM, error);
|
||||
LY_CHECK_ERR_GOTO(!dup, LOGMEM(trg_ctx); rc = LY_EMEM, cleanup);
|
||||
|
||||
if (options & LYD_DUP_WITH_FLAGS) {
|
||||
dup->flags = node->flags;
|
||||
|
@ -2076,15 +2197,17 @@ lyd_dup_r(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_
|
|||
if (options & LYD_DUP_WITH_PRIV) {
|
||||
dup->priv = node->priv;
|
||||
}
|
||||
|
||||
/* find schema node */
|
||||
if (trg_ctx == LYD_CTX(node)) {
|
||||
dup->schema = node->schema;
|
||||
} else {
|
||||
ret = lyd_find_schema_ctx(node->schema, trg_ctx, parent, 1, &dup->schema);
|
||||
if (ret) {
|
||||
rc = lyd_find_schema_ctx(node->schema, trg_ctx, parent, 1, &dup->schema);
|
||||
if (rc) {
|
||||
/* has no schema but is not an opaque node */
|
||||
free(dup);
|
||||
dup = NULL;
|
||||
goto error;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
dup->prev = dup;
|
||||
|
@ -2093,11 +2216,11 @@ lyd_dup_r(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_
|
|||
if (!(options & LYD_DUP_NO_META)) {
|
||||
if (!node->schema) {
|
||||
LY_LIST_FOR(((struct lyd_node_opaq *)node)->attr, attr) {
|
||||
LY_CHECK_GOTO(ret = lyd_dup_attr_single(attr, dup, NULL), error);
|
||||
LY_CHECK_GOTO(rc = lyd_dup_attr_single(attr, dup, NULL), cleanup);
|
||||
}
|
||||
} else {
|
||||
LY_LIST_FOR(node->meta, meta) {
|
||||
LY_CHECK_GOTO(ret = lyd_dup_meta_single_to_ctx(trg_ctx, meta, dup, NULL), error);
|
||||
LY_CHECK_GOTO(rc = lyd_dup_meta_single_to_ctx(trg_ctx, meta, dup, NULL), cleanup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2111,18 +2234,18 @@ lyd_dup_r(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_
|
|||
if (options & LYD_DUP_RECURSIVE) {
|
||||
/* duplicate all the children */
|
||||
LY_LIST_FOR(orig->child, child) {
|
||||
LY_CHECK_GOTO(ret = lyd_dup_r(child, trg_ctx, dup, LYD_INSERT_NODE_LAST, NULL, options, NULL), error);
|
||||
LY_CHECK_GOTO(rc = lyd_dup_r(child, trg_ctx, dup, LYD_INSERT_NODE_LAST, NULL, options, NULL), cleanup);
|
||||
}
|
||||
}
|
||||
LY_CHECK_GOTO(ret = lydict_insert(trg_ctx, orig->name.name, 0, &opaq->name.name), error);
|
||||
LY_CHECK_GOTO(ret = lydict_insert(trg_ctx, orig->name.prefix, 0, &opaq->name.prefix), error);
|
||||
LY_CHECK_GOTO(ret = lydict_insert(trg_ctx, orig->name.module_ns, 0, &opaq->name.module_ns), error);
|
||||
LY_CHECK_GOTO(ret = lydict_insert(trg_ctx, orig->value, 0, &opaq->value), error);
|
||||
LY_CHECK_GOTO(rc = lydict_insert(trg_ctx, orig->name.name, 0, &opaq->name.name), cleanup);
|
||||
LY_CHECK_GOTO(rc = lydict_insert(trg_ctx, orig->name.prefix, 0, &opaq->name.prefix), cleanup);
|
||||
LY_CHECK_GOTO(rc = lydict_insert(trg_ctx, orig->name.module_ns, 0, &opaq->name.module_ns), cleanup);
|
||||
LY_CHECK_GOTO(rc = lydict_insert(trg_ctx, orig->value, 0, &opaq->value), cleanup);
|
||||
opaq->hints = orig->hints;
|
||||
opaq->format = orig->format;
|
||||
if (orig->val_prefix_data) {
|
||||
ret = ly_dup_prefix_data(trg_ctx, opaq->format, orig->val_prefix_data, &opaq->val_prefix_data);
|
||||
LY_CHECK_GOTO(ret, error);
|
||||
rc = ly_dup_prefix_data(trg_ctx, opaq->format, orig->val_prefix_data, &opaq->val_prefix_data);
|
||||
LY_CHECK_GOTO(rc, cleanup);
|
||||
}
|
||||
} else if (dup->schema->nodetype & LYD_NODE_TERM) {
|
||||
struct lyd_node_term *term = (struct lyd_node_term *)dup;
|
||||
|
@ -2130,15 +2253,15 @@ lyd_dup_r(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_
|
|||
|
||||
term->hash = orig->hash;
|
||||
if (trg_ctx == LYD_CTX(node)) {
|
||||
ret = orig->value.realtype->plugin->duplicate(trg_ctx, &orig->value, &term->value);
|
||||
LY_CHECK_ERR_GOTO(ret, LOGERR(trg_ctx, ret, "Value duplication failed."), error);
|
||||
rc = orig->value.realtype->plugin->duplicate(trg_ctx, &orig->value, &term->value);
|
||||
LY_CHECK_ERR_GOTO(rc, LOGERR(trg_ctx, rc, "Value duplication failed."), cleanup);
|
||||
} else {
|
||||
/* store canonical value in the target context */
|
||||
val_can = lyd_get_value(node);
|
||||
type = ((struct lysc_node_leaf *)term->schema)->type;
|
||||
ret = lyd_value_store(trg_ctx, &term->value, type, val_can, strlen(val_can), 1, 1, NULL, LY_VALUE_CANON, NULL,
|
||||
rc = lyd_value_store(trg_ctx, &term->value, type, val_can, strlen(val_can), 1, 1, NULL, LY_VALUE_CANON, NULL,
|
||||
LYD_HINT_DATA, term->schema, NULL);
|
||||
LY_CHECK_GOTO(ret, error);
|
||||
LY_CHECK_GOTO(rc, cleanup);
|
||||
}
|
||||
} else if (dup->schema->nodetype & LYD_NODE_INNER) {
|
||||
struct lyd_node_inner *orig = (struct lyd_node_inner *)node;
|
||||
|
@ -2147,44 +2270,44 @@ lyd_dup_r(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_
|
|||
if (options & LYD_DUP_RECURSIVE) {
|
||||
/* create a hash table with the size of the previous hash table (duplicate) */
|
||||
if (orig->children_ht) {
|
||||
((struct lyd_node_inner *)dup)->children_ht = lyht_new(orig->children_ht->size, sizeof(struct lyd_node *), lyd_hash_table_val_equal, NULL, 1);
|
||||
((struct lyd_node_inner *)dup)->children_ht = lyht_new(orig->children_ht->size,
|
||||
sizeof(struct lyd_node *), lyd_hash_table_val_equal, NULL, 1);
|
||||
}
|
||||
|
||||
/* duplicate all the children */
|
||||
LY_LIST_FOR(orig->child, child) {
|
||||
LY_CHECK_GOTO(ret = lyd_dup_r(child, trg_ctx, dup, LYD_INSERT_NODE_LAST, NULL, options, NULL), error);
|
||||
LY_CHECK_GOTO(rc = lyd_dup_r(child, trg_ctx, dup, LYD_INSERT_NODE_LAST, NULL, options, NULL), cleanup);
|
||||
}
|
||||
} else if ((dup->schema->nodetype == LYS_LIST) && !(dup->schema->flags & LYS_KEYLESS)) {
|
||||
/* always duplicate keys of a list */
|
||||
for (child = orig->child; child && lysc_is_key(child->schema); child = child->next) {
|
||||
LY_CHECK_GOTO(ret = lyd_dup_r(child, trg_ctx, dup, LYD_INSERT_NODE_LAST, NULL, options, NULL), error);
|
||||
LY_CHECK_GOTO(rc = lyd_dup_r(child, trg_ctx, dup, LYD_INSERT_NODE_LAST, NULL, options, NULL), cleanup);
|
||||
}
|
||||
}
|
||||
lyd_hash(dup);
|
||||
} else if (dup->schema->nodetype & LYD_NODE_ANY) {
|
||||
dup->hash = node->hash;
|
||||
any = (struct lyd_node_any *)node;
|
||||
LY_CHECK_GOTO(ret = lyd_any_copy_value(dup, &any->value, any->value_type), error);
|
||||
LY_CHECK_GOTO(rc = lyd_any_copy_value(dup, &any->value, any->value_type), cleanup);
|
||||
}
|
||||
|
||||
/* insert */
|
||||
lyd_insert_node(parent, first, dup, insert_order);
|
||||
|
||||
if (dup_p) {
|
||||
cleanup:
|
||||
if (rc) {
|
||||
lyd_free_tree(dup);
|
||||
} else if (dup_p) {
|
||||
*dup_p = dup;
|
||||
}
|
||||
return LY_SUCCESS;
|
||||
|
||||
error:
|
||||
lyd_free_tree(dup);
|
||||
return ret;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a parent node to connect duplicated subtree to.
|
||||
*
|
||||
* @param[in] node Node (subtree) to duplicate.
|
||||
* @param[in] trg_ctx Target context for duplicated nodes.
|
||||
* @param[in,out] trg_ctx Target context for duplicated nodes, may be updated for @p node.
|
||||
* @param[in] parent Initial parent to connect to.
|
||||
* @param[in] options Bitmask of options flags, see @ref dupoptions.
|
||||
* @param[out] dup_parent First duplicated parent node, if any.
|
||||
|
@ -2192,24 +2315,30 @@ error:
|
|||
* @return LY_ERR value.
|
||||
*/
|
||||
static LY_ERR
|
||||
lyd_dup_get_local_parent(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_node *parent,
|
||||
lyd_dup_get_local_parent(const struct lyd_node *node, const struct ly_ctx **trg_ctx, struct lyd_node *parent,
|
||||
uint32_t options, struct lyd_node **dup_parent, struct lyd_node **local_parent)
|
||||
{
|
||||
const struct lyd_node *orig_parent;
|
||||
const struct ly_ctx *ctx, *top_ctx;
|
||||
struct lyd_node *iter = NULL;
|
||||
ly_bool repeat = 1, ext_parent = 0;
|
||||
ly_bool repeat = 1;
|
||||
|
||||
assert(node && *trg_ctx);
|
||||
|
||||
*dup_parent = NULL;
|
||||
*local_parent = NULL;
|
||||
|
||||
if (node->flags & LYD_EXT) {
|
||||
ext_parent = 1;
|
||||
if (!lyd_parent(node)) {
|
||||
/* no parents */
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
/* adjust the context for node parent correctly */
|
||||
top_ctx = *trg_ctx;
|
||||
LY_CHECK_RET(lyd_find_ext_ctx_nested(lyd_parent(node), trg_ctx));
|
||||
ctx = *trg_ctx;
|
||||
|
||||
for (orig_parent = lyd_parent(node); repeat && orig_parent; orig_parent = lyd_parent(orig_parent)) {
|
||||
if (ext_parent) {
|
||||
/* use the standard context */
|
||||
trg_ctx = LYD_CTX(orig_parent);
|
||||
}
|
||||
if (parent && (LYD_CTX(parent) == LYD_CTX(orig_parent)) && (parent->schema == orig_parent->schema)) {
|
||||
/* stop creating parents, connect what we have into the provided parent */
|
||||
iter = parent;
|
||||
|
@ -2221,7 +2350,7 @@ lyd_dup_get_local_parent(const struct lyd_node *node, const struct ly_ctx *trg_c
|
|||
repeat = 0;
|
||||
} else {
|
||||
iter = NULL;
|
||||
LY_CHECK_RET(lyd_dup_r(orig_parent, trg_ctx, NULL, LYD_INSERT_NODE_DEFAULT, &iter, options, &iter));
|
||||
LY_CHECK_RET(lyd_dup_r(orig_parent, ctx, NULL, LYD_INSERT_NODE_DEFAULT, &iter, options, &iter));
|
||||
|
||||
/* insert into the previous duplicated parent */
|
||||
if (*dup_parent) {
|
||||
|
@ -2238,13 +2367,14 @@ lyd_dup_get_local_parent(const struct lyd_node *node, const struct ly_ctx *trg_c
|
|||
}
|
||||
|
||||
if (orig_parent->flags & LYD_EXT) {
|
||||
ext_parent = 1;
|
||||
/* parents of the nested extension data, use the original context */
|
||||
ctx = top_ctx;
|
||||
}
|
||||
}
|
||||
|
||||
if (repeat && parent) {
|
||||
/* given parent and created parents chain actually do not interconnect */
|
||||
LOGERR(trg_ctx, LY_EINVAL, "None of the duplicated node \"%s\" schema parents match the provided parent \"%s\".",
|
||||
LOGERR(*trg_ctx, LY_EINVAL, "None of the duplicated node \"%s\" schema parents match the provided parent \"%s\".",
|
||||
LYD_NAME(node), LYD_NAME(parent));
|
||||
return LY_EINVAL;
|
||||
}
|
||||
|
@ -2272,11 +2402,13 @@ lyd_dup(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_no
|
|||
|
||||
assert(node && trg_ctx);
|
||||
|
||||
/* create/find parents, adjusts the context as well */
|
||||
if (options & LYD_DUP_WITH_PARENTS) {
|
||||
LY_CHECK_GOTO(rc = lyd_dup_get_local_parent(node, trg_ctx, parent, options & (LYD_DUP_WITH_FLAGS | LYD_DUP_NO_META),
|
||||
LY_CHECK_GOTO(rc = lyd_dup_get_local_parent(node, &trg_ctx, parent, options & (LYD_DUP_WITH_FLAGS | LYD_DUP_NO_META),
|
||||
&top, &local_parent), error);
|
||||
} else {
|
||||
local_parent = parent;
|
||||
LY_CHECK_GOTO(rc = lyd_find_ext_ctx_nested(node, &trg_ctx), error);
|
||||
}
|
||||
|
||||
LY_LIST_FOR(node, orig) {
|
||||
|
@ -2340,42 +2472,16 @@ error:
|
|||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check the context of node and parent when duplicating nodes.
|
||||
*
|
||||
* @param[in] node Node to duplicate.
|
||||
* @param[in] parent Parent of the duplicated node(s).
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
static LY_ERR
|
||||
lyd_dup_ctx_check(const struct lyd_node *node, const struct lyd_node_inner *parent)
|
||||
{
|
||||
const struct lyd_node *iter;
|
||||
|
||||
if (!node || !parent) {
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
if ((LYD_CTX(node) != LYD_CTX(parent))) {
|
||||
/* try to find top-level ext data parent */
|
||||
for (iter = node; iter && !(iter->flags & LYD_EXT); iter = lyd_parent(iter)) {}
|
||||
|
||||
if (!iter || !lyd_parent(iter) || (LYD_CTX(lyd_parent(iter)) != LYD_CTX(parent))) {
|
||||
LOGERR(LYD_CTX(node), LY_EINVAL, "Different contexts used in node duplication.");
|
||||
return LY_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
lyd_dup_single(const struct lyd_node *node, struct lyd_node_inner *parent, uint32_t options, struct lyd_node **dup)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
|
||||
LY_CHECK_RET(lyd_dup_ctx_check(node, parent));
|
||||
if (parent && (lyd_dup_get_top_ctx(node) != lyd_dup_get_top_ctx(&parent->node))) {
|
||||
LOGERR(LYD_CTX(node), LY_EINVAL, "Different \"node\" and \"parent\" contexts used in node duplication.");
|
||||
return LY_EINVAL;
|
||||
}
|
||||
|
||||
return lyd_dup(node, LYD_CTX(node), (struct lyd_node *)parent, options, 1, dup);
|
||||
return lyd_dup(node, lyd_dup_get_top_ctx(node), (struct lyd_node *)parent, options, 1, dup);
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
|
@ -2383,6 +2489,10 @@ lyd_dup_single_to_ctx(const struct lyd_node *node, const struct ly_ctx *trg_ctx,
|
|||
uint32_t options, struct lyd_node **dup)
|
||||
{
|
||||
LY_CHECK_ARG_RET(trg_ctx, node, trg_ctx, LY_EINVAL);
|
||||
if (parent && (trg_ctx != lyd_dup_get_top_ctx(&parent->node))) {
|
||||
LOGERR(LYD_CTX(node), LY_EINVAL, "Different \"trg_ctx\" and \"parent\" contexts used in node duplication.");
|
||||
return LY_EINVAL;
|
||||
}
|
||||
|
||||
return lyd_dup(node, trg_ctx, (struct lyd_node *)parent, options, 1, dup);
|
||||
}
|
||||
|
@ -2391,9 +2501,12 @@ LIBYANG_API_DEF LY_ERR
|
|||
lyd_dup_siblings(const struct lyd_node *node, struct lyd_node_inner *parent, uint32_t options, struct lyd_node **dup)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
|
||||
LY_CHECK_RET(lyd_dup_ctx_check(node, parent));
|
||||
if (parent && (lyd_dup_get_top_ctx(node) != lyd_dup_get_top_ctx(&parent->node))) {
|
||||
LOGERR(LYD_CTX(node), LY_EINVAL, "Different \"node\" and \"parent\" contexts used in node duplication.");
|
||||
return LY_EINVAL;
|
||||
}
|
||||
|
||||
return lyd_dup(node, LYD_CTX(node), (struct lyd_node *)parent, options, 0, dup);
|
||||
return lyd_dup(node, lyd_dup_get_top_ctx(node), (struct lyd_node *)parent, options, 0, dup);
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
|
@ -2401,6 +2514,10 @@ lyd_dup_siblings_to_ctx(const struct lyd_node *node, const struct ly_ctx *trg_ct
|
|||
uint32_t options, struct lyd_node **dup)
|
||||
{
|
||||
LY_CHECK_ARG_RET(trg_ctx, node, trg_ctx, LY_EINVAL);
|
||||
if (parent && (trg_ctx != lyd_dup_get_top_ctx(&parent->node))) {
|
||||
LOGERR(LYD_CTX(node), LY_EINVAL, "Different \"trg_ctx\" and \"parent\" contexts used in node duplication.");
|
||||
return LY_EINVAL;
|
||||
}
|
||||
|
||||
return lyd_dup(node, trg_ctx, (struct lyd_node *)parent, options, 0, dup);
|
||||
}
|
||||
|
@ -2635,8 +2752,8 @@ lyd_merge(struct lyd_node **target, const struct lyd_node *source, const struct
|
|||
struct lyds_pool lyds = {0};
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(*target ? LYD_CTX(*target) : NULL, source ? LYD_CTX(source) : NULL, mod ? mod->ctx : NULL,
|
||||
LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, *target ? LYD_CTX(*target) : NULL, source ? LYD_CTX(source) : NULL,
|
||||
mod ? mod->ctx : NULL, LY_EINVAL);
|
||||
|
||||
if (!source) {
|
||||
/* nothing to merge */
|
||||
|
@ -2993,7 +3110,7 @@ lyd_find_meta(const struct lyd_meta *first, const struct lys_module *module, con
|
|||
size_t pref_len, name_len;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, module || strchr(name, ':'), name, NULL);
|
||||
LY_CHECK_CTX_EQUAL_RET(first ? first->annotation->module->ctx : NULL, module ? module->ctx : NULL, NULL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, first ? first->annotation->module->ctx : NULL, module ? module->ctx : NULL, NULL);
|
||||
|
||||
if (!first) {
|
||||
return NULL;
|
||||
|
@ -3188,7 +3305,7 @@ lyd_find_sibling_dup_inst_set(const struct lyd_node *siblings, const struct lyd_
|
|||
uint32_t comp_opts;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, target, set, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(siblings ? LYD_CTX(siblings) : NULL, LYD_CTX(target), LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, siblings ? LYD_CTX(siblings) : NULL, LYD_CTX(target), LY_EINVAL);
|
||||
|
||||
LY_CHECK_RET(ly_set_new(set));
|
||||
|
||||
|
@ -3262,6 +3379,11 @@ lyd_find_sibling_opaq_next(const struct lyd_node *first, const char *name, struc
|
|||
LY_CHECK_ARG_RET(NULL, name, LY_EINVAL);
|
||||
|
||||
if (first && first->schema) {
|
||||
/* find the actual first node */
|
||||
while (first->prev->next) {
|
||||
first = first->prev;
|
||||
}
|
||||
|
||||
first = first->prev;
|
||||
if (first->schema) {
|
||||
/* no opaque nodes */
|
||||
|
@ -3573,8 +3695,8 @@ lyd_find_path(const struct lyd_node *ctx_node, const char *path, ly_bool output,
|
|||
LY_CHECK_ARG_RET(NULL, ctx_node, ctx_node->schema, path, LY_EINVAL);
|
||||
|
||||
/* parse the path */
|
||||
ret = ly_path_parse(LYD_CTX(ctx_node), ctx_node->schema, path, strlen(path), 0, LY_PATH_BEGIN_EITHER,
|
||||
LY_PATH_PREFIX_FIRST, LY_PATH_PRED_SIMPLE, &expr);
|
||||
ret = ly_path_parse(LYD_CTX(ctx_node), ctx_node->schema, path, 0, 0, LY_PATH_BEGIN_EITHER, LY_PATH_PREFIX_FIRST,
|
||||
LY_PATH_PRED_SIMPLE, &expr);
|
||||
LY_CHECK_GOTO(ret, cleanup);
|
||||
|
||||
/* compile the path */
|
||||
|
@ -3617,8 +3739,11 @@ LY_ERR
|
|||
lyd_get_or_create_leafref_links_record(const struct lyd_node_term *node, struct lyd_leafref_links_rec **record, ly_bool create)
|
||||
{
|
||||
struct ly_ht *ht;
|
||||
LY_ERR ret = LY_SUCCESS;
|
||||
uint32_t hash;
|
||||
struct lyd_leafref_links_rec rec = {0};
|
||||
struct lyd_leafref_links_rec *rec_p = &rec;
|
||||
struct lyd_leafref_links_rec **rec_p2;
|
||||
|
||||
assert(node);
|
||||
assert(record);
|
||||
|
@ -3633,15 +3758,23 @@ lyd_get_or_create_leafref_links_record(const struct lyd_node_term *node, struct
|
|||
ht = LYD_CTX(node)->leafref_links_ht;
|
||||
hash = lyht_hash((const char *)&node, sizeof node);
|
||||
|
||||
if (lyht_find(ht, &rec, hash, (void **)record) == LY_ENOTFOUND) {
|
||||
if (lyht_find(ht, &rec_p, hash, (void **)&rec_p2) == LY_ENOTFOUND) {
|
||||
if (create) {
|
||||
LY_CHECK_RET(lyht_insert_no_check(ht, &rec, hash, (void **)record));
|
||||
rec_p = calloc(1, sizeof rec);
|
||||
rec_p->node = node;
|
||||
LY_CHECK_ERR_RET(!rec_p, LOGMEM(LYD_CTX(node)), LY_EMEM);
|
||||
ret = lyht_insert_no_check(ht, &rec_p, hash, (void **)&rec_p2);
|
||||
LY_CHECK_ERR_GOTO(ret, free(rec_p), cleanup);
|
||||
} else {
|
||||
return LY_ENOTFOUND;
|
||||
}
|
||||
}
|
||||
|
||||
return LY_SUCCESS;
|
||||
cleanup:
|
||||
if (!ret) {
|
||||
*record = *rec_p2;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief libyang representation of YANG data trees.
|
||||
*
|
||||
* Copyright (c) 2015 - 2024 CESNET, z.s.p.o.
|
||||
* Copyright (c) 2015 - 2025 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.
|
||||
|
@ -556,15 +556,16 @@ typedef enum {
|
|||
* @brief List of possible value types stored in ::lyd_node_any.
|
||||
*/
|
||||
typedef enum {
|
||||
LYD_ANYDATA_DATATREE, /**< Value is a pointer to ::lyd_node structure (first sibling). When provided as input parameter, the pointer
|
||||
is directly connected into the anydata node without duplication, caller is supposed to not manipulate
|
||||
with the data after a successful call (including calling ::lyd_free_all() on the provided data) */
|
||||
LYD_ANYDATA_STRING, /**< Value is a generic string without any knowledge about its format (e.g. anyxml value in JSON encoded
|
||||
as string). XML sensitive characters (such as & or \>) are automatically escaped when the anydata
|
||||
is printed in XML format. */
|
||||
LYD_ANYDATA_XML, /**< Value is a string containing the serialized XML data. */
|
||||
LYD_ANYDATA_JSON, /**< Value is a string containing the data modeled by YANG and encoded as I-JSON. */
|
||||
LYD_ANYDATA_LYB /**< Value is a memory chunk with the serialized data tree in LYB format. */
|
||||
LYD_ANYDATA_DATATREE, /**< Value is a pointer to ::lyd_node structure (first sibling). When provided as input
|
||||
parameter, the pointer is directly connected into the anydata node without duplication,
|
||||
caller is supposed to not manipulate with the data after a successful call (including
|
||||
calling ::lyd_free_all() on the provided data) */
|
||||
LYD_ANYDATA_STRING, /**< Value is a generic string without any knowledge about its format (e.g. anyxml value in
|
||||
JSON encoded as string). XML sensitive characters (such as & or \>) are automatically
|
||||
escaped when the anydata is printed in XML format. */
|
||||
LYD_ANYDATA_XML, /**< Value is a string containing the serialized XML data. */
|
||||
LYD_ANYDATA_JSON, /**< Value is a string containing the data modeled by YANG and encoded as I-JSON. */
|
||||
LYD_ANYDATA_LYB /**< Value is a memory chunk with the serialized data tree in LYB format. */
|
||||
} LYD_ANYDATA_VALUETYPE;
|
||||
|
||||
/** @} */
|
||||
|
@ -944,6 +945,7 @@ struct lyd_node_any {
|
|||
#define LYD_VALHINT_NUM64 0x0010 /**< value is allowed to be an int64 or uint64 */
|
||||
#define LYD_VALHINT_BOOLEAN 0x0020 /**< value is allowed to be a boolean */
|
||||
#define LYD_VALHINT_EMPTY 0x0040 /**< value is allowed to be empty */
|
||||
#define LYD_VALHINT_STRING_DATATYPES 0x0080 /**< boolean and numeric fields are allowed to be quoted */
|
||||
/**
|
||||
* @} lydvalhints
|
||||
*/
|
||||
|
@ -1554,8 +1556,8 @@ LIBYANG_API_DECL LY_ERR lyd_new_attr2(struct lyd_node *parent, const char *modul
|
|||
* and @p value is set, the predicate is preferred.
|
||||
*
|
||||
* For key-less lists, positional predicates must be used (indices starting from 1). For non-configuration leaf-lists
|
||||
* either positional predicate can be used or leaf-list predicate, when an instance is always created at the end.
|
||||
* If no predicate is used for these nodes, they are always created.
|
||||
* (or lists) either positional predicate can be used or leaf-list (or key) predicate, when an instance is always
|
||||
* created at the end. If no predicate is used for these nodes, they are always created.
|
||||
*
|
||||
* @param[in] parent Data parent to add to/modify, can be NULL. Note that in case a first top-level sibling is used,
|
||||
* it may no longer be first if @p path is absolute and starts with a non-existing top-level node inserted
|
||||
|
@ -1591,7 +1593,7 @@ LIBYANG_API_DECL LY_ERR lyd_new_path(struct lyd_node *parent, const struct ly_ct
|
|||
* @param[in] value_type Anyxml/anydata node @p value type.
|
||||
* @param[in] options Bitmask of options, see @ref newvaloptions.
|
||||
* @param[out] new_parent Optional first parent node created. If only one node was created, equals to @p new_node.
|
||||
* @param[out] new_node Optional last node created.
|
||||
* @param[out] new_node Optional target node of @p path (the last created node, the list instance in case of a list).
|
||||
* @return LY_SUCCESS on success.
|
||||
* @return LY_EEXIST if the final node to create exists (unless ::LYD_NEW_PATH_UPDATE is used).
|
||||
* @return LY_EINVAL on invalid arguments including invalid @p path.
|
||||
|
@ -2005,7 +2007,8 @@ LIBYANG_API_DECL LY_ERR lyd_dup_single(const struct lyd_node *node, struct lyd_n
|
|||
* @brief Create a copy of the specified data tree @p node. Schema references are assigned from @p trg_ctx.
|
||||
*
|
||||
* @param[in] node Data tree node to be duplicated.
|
||||
* @param[in] trg_ctx Target context for duplicated nodes.
|
||||
* @param[in] trg_ctx Target context for duplicated nodes. In case of mixed contexts in @p node subtree or parents
|
||||
* (schema mount data), this is the context of top-level nodes.
|
||||
* @param[in] parent Optional parent node where to connect the duplicated node(s). If set in combination with
|
||||
* ::LYD_DUP_WITH_PARENTS, the missing parents' chain is duplicated and connected with @p parent.
|
||||
* @param[in] options Bitmask of options flags, see @ref dupoptions.
|
||||
|
@ -2035,7 +2038,8 @@ LIBYANG_API_DECL LY_ERR lyd_dup_siblings(const struct lyd_node *node, struct lyd
|
|||
* from @p trg_ctx.
|
||||
*
|
||||
* @param[in] node Data tree node to be duplicated.
|
||||
* @param[in] trg_ctx Target context for duplicated nodes.
|
||||
* @param[in] trg_ctx Target context for duplicated nodes. In case of mixed contexts in @p node subtree or parents
|
||||
* (schema mount data), this is the context of top-level nodes.
|
||||
* @param[in] parent Optional parent node where to connect the duplicated node(s). If set in combination with
|
||||
* ::LYD_DUP_WITH_PARENTS, the missing parents' chain is duplicated and connected with @p parent.
|
||||
* @param[in] options Bitmask of options flags, see @ref dupoptions.
|
||||
|
@ -2158,12 +2162,18 @@ LIBYANG_API_DECL LY_ERR lyd_merge_module(struct lyd_node **target, const struct
|
|||
*
|
||||
* Default behavior:
|
||||
* - any default nodes are treated as non-existent and ignored.
|
||||
* - nodes with 'none' operation can appear only in case a leaf node has not changed its value and only its
|
||||
* default flag.
|
||||
* - metadata differences are not included in the diff.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define LYD_DIFF_DEFAULTS 0x01 /**< Default nodes in the trees are not ignored but treated similarly to explicit
|
||||
nodes. Also, leaves and leaf-lists are added into diff even in case only their
|
||||
default flag (state) was changed. */
|
||||
#define LYD_DIFF_META 0x02 /**< All metadata are compared and the full difference reported in the diff always in
|
||||
the form of 'yang:meta-<operation>' metadata. Also, equal nodes with only changes
|
||||
in their metadata will be present in the diff with the 'none' operation. */
|
||||
|
||||
/** @} diffoptions */
|
||||
|
||||
|
@ -2661,7 +2671,7 @@ LIBYANG_API_DECL int ly_time_tz_offset_at(time_t time);
|
|||
/**
|
||||
* @brief Convert date-and-time from string to UNIX timestamp and fractions of a second.
|
||||
*
|
||||
* @param[in] value Valid string date-and-time value.
|
||||
* @param[in] value Valid string date-and-time value, the string may continue after the value (be longer).
|
||||
* @param[out] time UNIX timestamp.
|
||||
* @param[out] fractions_s Optional fractions of a second, set to NULL if none.
|
||||
* @return LY_ERR value.
|
||||
|
@ -2681,7 +2691,7 @@ LIBYANG_API_DECL LY_ERR ly_time_time2str(time_t time, const char *fractions_s, c
|
|||
/**
|
||||
* @brief Convert date-and-time from string to timespec.
|
||||
*
|
||||
* @param[in] value Valid string date-and-time value.
|
||||
* @param[in] value Valid string date-and-time value, the string may continue after the value (be longer).
|
||||
* @param[out] ts Timespec.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
|
|
|
@ -516,6 +516,7 @@ lyd_value_store(const struct ly_ctx *ctx, struct lyd_value *val, const struct ly
|
|||
|
||||
if (!value) {
|
||||
value = "";
|
||||
value_len = 0;
|
||||
}
|
||||
if (incomplete) {
|
||||
*incomplete = 0;
|
||||
|
@ -1626,9 +1627,6 @@ ly_time_tz_offset_at(time_t time)
|
|||
struct tm tm_local, tm_utc;
|
||||
int result = 0;
|
||||
|
||||
/* init timezone */
|
||||
tzset();
|
||||
|
||||
/* get local and UTC time */
|
||||
localtime_r(&time, &tm_local);
|
||||
gmtime_r(&time, &tm_utc);
|
||||
|
@ -1670,7 +1668,7 @@ ly_time_str2time(const char *value, time_t *time, char **fractions_s)
|
|||
int64_t shift, shift_m;
|
||||
time_t t;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, value, strlen(value) > 17, time, LY_EINVAL);
|
||||
LY_CHECK_ARG_RET(NULL, value, strnlen(value, 18) > 17, time, LY_EINVAL);
|
||||
|
||||
tm.tm_year = atoi(&value[0]) - 1900;
|
||||
tm.tm_mon = atoi(&value[5]) - 1;
|
||||
|
@ -1776,9 +1774,6 @@ ly_time_time2str(time_t time, const char *fractions_s, char **str)
|
|||
|
||||
LY_CHECK_ARG_RET(NULL, str, LY_EINVAL);
|
||||
|
||||
/* init timezone */
|
||||
tzset();
|
||||
|
||||
/* convert */
|
||||
if (!localtime_r(&time, &tm)) {
|
||||
return LY_ESYS;
|
||||
|
|
|
@ -191,7 +191,8 @@ lyd_free_leafref_nodes(const struct lyd_node_term *node)
|
|||
/* free entry itself from hash table */
|
||||
ht = LYD_CTX(node)->leafref_links_ht;
|
||||
hash = lyht_hash((const char *)&node, sizeof node);
|
||||
lyht_remove(ht, rec, hash);
|
||||
lyht_remove(ht, &rec, hash);
|
||||
free(rec);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -505,7 +505,7 @@ lyd_new_inner(struct lyd_node *parent, const struct lys_module *module, const ch
|
|||
const struct ly_ctx *ctx = parent ? LYD_CTX(parent) : (module ? module->ctx : NULL);
|
||||
|
||||
LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
|
||||
|
||||
if (!module) {
|
||||
module = parent->schema->module;
|
||||
|
@ -621,7 +621,7 @@ lyd_new_list(struct lyd_node *parent, const struct lys_module *module, const cha
|
|||
va_list ap;
|
||||
|
||||
LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
|
||||
LY_CHECK_RET(lyd_new_val_get_format(options, &format));
|
||||
LY_CHECK_ARG_RET(ctx, !(store_only && (format == LY_VALUE_CANON || format == LY_VALUE_LYB)), LY_EINVAL);
|
||||
|
||||
|
@ -726,7 +726,7 @@ lyd_new_list2(struct lyd_node *parent, const struct lys_module *module, const ch
|
|||
uint32_t getnext_opts = (options & LYD_NEW_VAL_OUTPUT) ? LYS_GETNEXT_OUTPUT : 0;
|
||||
|
||||
LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
|
||||
|
||||
if (!module) {
|
||||
module = parent->schema->module;
|
||||
|
@ -781,7 +781,7 @@ lyd_new_list3(struct lyd_node *parent, const struct lys_module *module, const ch
|
|||
|
||||
LY_CHECK_RET(lyd_new_val_get_format(options, &format));
|
||||
LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, (format != LY_VALUE_LYB) || value_lengths, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
|
||||
LY_CHECK_ARG_RET(ctx, !(store_only && (format == LY_VALUE_CANON || format == LY_VALUE_LYB)), LY_EINVAL);
|
||||
|
||||
/* create the list node */
|
||||
|
@ -845,7 +845,7 @@ _lyd_new_term(struct lyd_node *parent, const struct lys_module *module, const ch
|
|||
LY_VALUE_FORMAT format;
|
||||
|
||||
LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
|
||||
LY_CHECK_RET(lyd_new_val_get_format(options, &format));
|
||||
LY_CHECK_ARG_RET(ctx, !(store_only && (format == LY_VALUE_CANON || format == LY_VALUE_LYB)), LY_EINVAL);
|
||||
|
||||
|
@ -941,7 +941,7 @@ lyd_new_any(struct lyd_node *parent, const struct lys_module *module, const char
|
|||
|
||||
LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name,
|
||||
(value_type == LYD_ANYDATA_DATATREE) || (value_type == LYD_ANYDATA_STRING) || value, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
|
||||
|
||||
if (!module) {
|
||||
module = parent->schema->module;
|
||||
|
@ -1007,7 +1007,7 @@ lyd_new_meta(const struct ly_ctx *ctx, struct lyd_node *parent, const struct lys
|
|||
ly_bool store_only = options & LYD_NEW_VAL_STORE_ONLY;
|
||||
|
||||
LY_CHECK_ARG_RET(ctx, ctx || parent, name, module || strchr(name, ':'), parent || meta, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(ctx, parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, ctx, parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
|
||||
if (!ctx) {
|
||||
ctx = module ? module->ctx : LYD_CTX(parent);
|
||||
}
|
||||
|
@ -1050,7 +1050,7 @@ lyd_new_meta2(const struct ly_ctx *ctx, struct lyd_node *parent, uint32_t option
|
|||
ly_bool store_only = options & LYD_NEW_VAL_STORE_ONLY;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, ctx, attr, parent || meta, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(ctx, parent ? LYD_CTX(parent) : NULL, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, ctx, parent ? LYD_CTX(parent) : NULL, LY_EINVAL);
|
||||
|
||||
if (parent && !parent->schema) {
|
||||
LOGERR(ctx, LY_EINVAL, "Cannot add metadata to an opaque node \"%s\".",
|
||||
|
@ -1092,7 +1092,7 @@ lyd_new_opaq(struct lyd_node *parent, const struct ly_ctx *ctx, const char *name
|
|||
uint32_t hints = 0;
|
||||
|
||||
LY_CHECK_ARG_RET(ctx, parent || ctx, parent || node, name, module_name, !prefix || !strcmp(prefix, module_name), LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(ctx, parent ? LYD_CTX(parent) : NULL, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, ctx, parent ? LYD_CTX(parent) : NULL, LY_EINVAL);
|
||||
|
||||
if (!ctx) {
|
||||
ctx = LYD_CTX(parent);
|
||||
|
@ -1122,7 +1122,7 @@ lyd_new_opaq2(struct lyd_node *parent, const struct ly_ctx *ctx, const char *nam
|
|||
struct lyd_node *ret = NULL;
|
||||
|
||||
LY_CHECK_ARG_RET(ctx, parent || ctx, parent || node, name, module_ns, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(ctx, parent ? LYD_CTX(parent) : NULL, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, ctx, parent ? LYD_CTX(parent) : NULL, LY_EINVAL);
|
||||
|
||||
if (!ctx) {
|
||||
ctx = LYD_CTX(parent);
|
||||
|
@ -1479,13 +1479,14 @@ cleanup:
|
|||
* @param[in] value_len Length of @p value.
|
||||
* @param[in] value_type Type of @p value for anydata/anyxml node.
|
||||
* @param[in] format Format of @p value.
|
||||
* @param[in] any_use_value Whether to spend @p value when updating an anydata/anyxml node or not.
|
||||
* @param[out] new_parent Set to @p node if the value was updated, otherwise set to NULL.
|
||||
* @param[out] new_node Set to @p node if the value was updated, otherwise set to NULL.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
static LY_ERR
|
||||
lyd_new_path_update(struct lyd_node *node, const void *value, size_t value_len, LYD_ANYDATA_VALUETYPE value_type,
|
||||
LY_VALUE_FORMAT format, struct lyd_node **new_parent, struct lyd_node **new_node)
|
||||
LY_VALUE_FORMAT format, ly_bool any_use_value, struct lyd_node **new_parent, struct lyd_node **new_node)
|
||||
{
|
||||
LY_ERR ret = LY_SUCCESS;
|
||||
struct lyd_node *new_any;
|
||||
|
@ -1525,12 +1526,14 @@ lyd_new_path_update(struct lyd_node *node, const void *value, size_t value_len,
|
|||
case LYS_ANYDATA:
|
||||
case LYS_ANYXML:
|
||||
/* create a new any node */
|
||||
LY_CHECK_RET(lyd_create_any(node->schema, value, value_type, 0, &new_any));
|
||||
LY_CHECK_RET(lyd_create_any(node->schema, value, value_type, any_use_value, &new_any));
|
||||
|
||||
/* compare with the existing one */
|
||||
if (lyd_compare_single(node, new_any, 0)) {
|
||||
/* not equal, switch values (so that we can use generic node free) */
|
||||
((struct lyd_node_any *)new_any)->value = ((struct lyd_node_any *)node)->value;
|
||||
value = ((struct lyd_node_any *)new_any)->value.str;
|
||||
value_type = ((struct lyd_node_any *)new_any)->value_type;
|
||||
((struct lyd_node_any *)new_any)->value.str = ((struct lyd_node_any *)node)->value.str;
|
||||
((struct lyd_node_any *)new_any)->value_type = ((struct lyd_node_any *)node)->value_type;
|
||||
((struct lyd_node_any *)node)->value.str = value;
|
||||
((struct lyd_node_any *)node)->value_type = value_type;
|
||||
|
@ -1679,7 +1682,7 @@ lyd_new_path_(struct lyd_node *parent, const struct ly_ctx *ctx, const struct ly
|
|||
LY_CHECK_GOTO(ret = lyd_new_val_get_format(options, &format), cleanup);
|
||||
|
||||
/* parse path */
|
||||
LY_CHECK_GOTO(ret = ly_path_parse(ctx, NULL, path, strlen(path), 0, LY_PATH_BEGIN_EITHER, LY_PATH_PREFIX_FIRST,
|
||||
LY_CHECK_GOTO(ret = ly_path_parse(ctx, NULL, path, 0, 0, LY_PATH_BEGIN_EITHER, LY_PATH_PREFIX_FIRST,
|
||||
LY_PATH_PRED_SIMPLE, &exp), cleanup);
|
||||
|
||||
/* compile path */
|
||||
|
@ -1708,7 +1711,7 @@ lyd_new_path_(struct lyd_node *parent, const struct ly_ctx *ctx, const struct ly
|
|||
}
|
||||
|
||||
/* update the existing node */
|
||||
ret = lyd_new_path_update(node, value, value_len, value_type, format, &nparent, &nnode);
|
||||
ret = lyd_new_path_update(node, value, value_len, value_type, format, any_use_value, &nparent, &nnode);
|
||||
goto cleanup;
|
||||
} /* else we were not searching for the whole path */
|
||||
} else if (r == LY_EINCOMPLETE) {
|
||||
|
@ -1811,7 +1814,8 @@ lyd_new_path_(struct lyd_node *parent, const struct ly_ctx *ctx, const struct ly
|
|||
if (val) {
|
||||
LY_CHECK_GOTO(ret = lyd_create_term2(schema, val, &node), cleanup);
|
||||
} else {
|
||||
LY_CHECK_GOTO(ret = lyd_create_term(schema, value, value_len, 0, store_only, NULL, format, NULL, LYD_HINT_DATA, NULL, &node), cleanup);
|
||||
LY_CHECK_GOTO(ret = lyd_create_term(schema, value, value_len, 0, store_only, NULL, format, NULL,
|
||||
LYD_HINT_DATA, NULL, &node), cleanup);
|
||||
}
|
||||
break;
|
||||
case LYS_LEAF:
|
||||
|
@ -1836,15 +1840,16 @@ lyd_new_path_(struct lyd_node *parent, const struct ly_ctx *ctx, const struct ly
|
|||
if (value && (format == LY_VALUE_JSON) && !ly_strncmp("[null]", value, value_len)) {
|
||||
hints |= LYD_VALHINT_EMPTY;
|
||||
}
|
||||
LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0,
|
||||
schema->module->name, strlen(schema->module->name), value, value_len, NULL, format, NULL, hints, &node),
|
||||
cleanup);
|
||||
ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, schema->module->name,
|
||||
strlen(schema->module->name), value, value_len, NULL, format, NULL, hints, &node);
|
||||
LY_CHECK_GOTO(ret, cleanup);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* create a leaf instance */
|
||||
LY_CHECK_GOTO(ret = lyd_create_term(schema, value, value_len, 0, store_only, NULL, format, NULL, LYD_HINT_DATA, NULL, &node), cleanup);
|
||||
LY_CHECK_GOTO(ret = lyd_create_term(schema, value, value_len, 0, store_only, NULL, format, NULL,
|
||||
LYD_HINT_DATA, NULL, &node), cleanup);
|
||||
break;
|
||||
case LYS_ANYDATA:
|
||||
case LYS_ANYXML:
|
||||
|
@ -1903,7 +1908,7 @@ lyd_new_path(struct lyd_node *parent, const struct ly_ctx *ctx, const char *path
|
|||
{
|
||||
LY_CHECK_ARG_RET(ctx, parent || ctx, path, (path[0] == '/') || parent,
|
||||
!(options & LYD_NEW_VAL_BIN) || !(options & LYD_NEW_VAL_CANON), LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, ctx, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, parent ? LYD_CTX(parent) : NULL, ctx, LY_EINVAL);
|
||||
|
||||
return lyd_new_path_(parent, ctx, NULL, path, value, 0, LYD_ANYDATA_STRING, options, node, NULL);
|
||||
}
|
||||
|
@ -1915,7 +1920,7 @@ lyd_new_path2(struct lyd_node *parent, const struct ly_ctx *ctx, const char *pat
|
|||
{
|
||||
LY_CHECK_ARG_RET(ctx, parent || ctx, path, (path[0] == '/') || parent,
|
||||
!(options & LYD_NEW_VAL_BIN) || !(options & LYD_NEW_VAL_CANON), LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, ctx, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, parent ? LYD_CTX(parent) : NULL, ctx, LY_EINVAL);
|
||||
|
||||
return lyd_new_path_(parent, ctx, NULL, path, value, value_len, value_type, options, new_parent, new_node);
|
||||
}
|
||||
|
@ -1928,7 +1933,7 @@ lyd_new_ext_path(struct lyd_node *parent, const struct lysc_ext_instance *ext, c
|
|||
|
||||
LY_CHECK_ARG_RET(ctx, ext, path, (path[0] == '/') || parent,
|
||||
!(options & LYD_NEW_VAL_BIN) || !(options & LYD_NEW_VAL_CANON), LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, ctx, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, parent ? LYD_CTX(parent) : NULL, ctx, LY_EINVAL);
|
||||
|
||||
return lyd_new_path_(parent, ctx, ext, path, value, 0, LYD_ANYDATA_STRING, options, node, NULL);
|
||||
}
|
||||
|
@ -2150,7 +2155,7 @@ lyd_new_implicit_all(struct lyd_node **tree, const struct ly_ctx *ctx, uint32_t
|
|||
LY_ERR rc = LY_SUCCESS;
|
||||
|
||||
LY_CHECK_ARG_RET(ctx, tree, *tree || ctx, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(*tree ? LYD_CTX(*tree) : NULL, ctx, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, *tree ? LYD_CTX(*tree) : NULL, ctx, LY_EINVAL);
|
||||
if (diff) {
|
||||
*diff = NULL;
|
||||
}
|
||||
|
@ -2191,7 +2196,7 @@ lyd_new_implicit_module(struct lyd_node **tree, const struct lys_module *module,
|
|||
struct ly_ht *getnext_ht = NULL;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, tree, module, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(*tree ? LYD_CTX(*tree) : NULL, module ? module->ctx : NULL, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, *tree ? LYD_CTX(*tree) : NULL, module ? module->ctx : NULL, LY_EINVAL);
|
||||
if (diff) {
|
||||
*diff = NULL;
|
||||
}
|
||||
|
|
|
@ -148,7 +148,7 @@ void *ly_realloc(void *ptr, size_t size);
|
|||
} \
|
||||
p__ = (char *)((LY_ARRAY_COUNT_TYPE*)(p__) + 1); \
|
||||
memcpy(&(ARRAY), &p__, sizeof p__); \
|
||||
if (ARRAY) { \
|
||||
if ((ARRAY) && (SIZE > 0)) { \
|
||||
memset(&(ARRAY)[*((LY_ARRAY_COUNT_TYPE*)(p__) - 1)], 0, (SIZE) * sizeof *(ARRAY)); \
|
||||
} \
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
/**
|
||||
* @file tree_schema.c
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief Schema tree implementation
|
||||
*
|
||||
* Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
|
||||
* Copyright (c) 2015 - 2025 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.
|
||||
|
@ -410,7 +411,7 @@ lys_find_child(const struct lysc_node *parent, const struct lys_module *module,
|
|||
const struct lysc_node *node = NULL;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, module, name, NULL);
|
||||
LY_CHECK_CTX_EQUAL_RET(parent ? parent->module->ctx : NULL, module->ctx, NULL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, parent ? parent->module->ctx : NULL, module->ctx, NULL);
|
||||
if (!nodetype) {
|
||||
nodetype = LYS_NODETYPE_MASK;
|
||||
}
|
||||
|
@ -447,7 +448,7 @@ lys_find_xpath_atoms(const struct ly_ctx *ctx, const struct lysc_node *ctx_node,
|
|||
uint32_t i;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, ctx || ctx_node, xpath, set, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(ctx, ctx_node ? ctx_node->module->ctx : NULL, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, ctx, ctx_node ? ctx_node->module->ctx : NULL, LY_EINVAL);
|
||||
if (!(options & LYXP_SCNODE_ALL)) {
|
||||
options |= LYXP_SCNODE;
|
||||
}
|
||||
|
@ -494,7 +495,7 @@ lys_find_expr_atoms(const struct lysc_node *ctx_node, const struct lys_module *c
|
|||
uint32_t i;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, cur_mod, expr, prefixes, set, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(ctx_node ? ctx_node->module->ctx : NULL, cur_mod->ctx, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, ctx_node ? ctx_node->module->ctx : NULL, cur_mod->ctx, LY_EINVAL);
|
||||
if (!(options & LYXP_SCNODE_ALL)) {
|
||||
options = LYXP_SCNODE;
|
||||
}
|
||||
|
@ -542,9 +543,9 @@ lys_find_xpath(const struct ly_ctx *ctx, const struct lysc_node *ctx_node, const
|
|||
uint32_t i;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, ctx || ctx_node, xpath, set, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(ctx, ctx_node ? ctx_node->module->ctx : NULL, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, ctx, ctx_node ? ctx_node->module->ctx : NULL, LY_EINVAL);
|
||||
if (!(options & LYXP_SCNODE_ALL)) {
|
||||
options = LYXP_SCNODE;
|
||||
options |= LYXP_SCNODE;
|
||||
}
|
||||
if (!ctx) {
|
||||
ctx = ctx_node->module->ctx;
|
||||
|
@ -624,14 +625,14 @@ lys_find_path_atoms(const struct ly_ctx *ctx, const struct lysc_node *ctx_node,
|
|||
struct ly_path *p = NULL;
|
||||
|
||||
LY_CHECK_ARG_RET(ctx, ctx || ctx_node, path, set, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(ctx, ctx_node ? ctx_node->module->ctx : NULL, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, ctx, ctx_node ? ctx_node->module->ctx : NULL, LY_EINVAL);
|
||||
|
||||
if (!ctx) {
|
||||
ctx = ctx_node->module->ctx;
|
||||
}
|
||||
|
||||
/* parse */
|
||||
ret = ly_path_parse(ctx, ctx_node, path, strlen(path), 0, LY_PATH_BEGIN_EITHER, LY_PATH_PREFIX_FIRST,
|
||||
ret = ly_path_parse(ctx, ctx_node, path, 0, 0, LY_PATH_BEGIN_EITHER, LY_PATH_PREFIX_FIRST,
|
||||
LY_PATH_PRED_SIMPLE, &expr);
|
||||
LY_CHECK_GOTO(ret, cleanup);
|
||||
|
||||
|
@ -658,15 +659,15 @@ lys_find_path(const struct ly_ctx *ctx, const struct lysc_node *ctx_node, const
|
|||
LY_ERR ret;
|
||||
uint8_t oper;
|
||||
|
||||
LY_CHECK_ARG_RET(ctx, ctx || ctx_node, NULL);
|
||||
LY_CHECK_CTX_EQUAL_RET(ctx, ctx_node ? ctx_node->module->ctx : NULL, NULL);
|
||||
LY_CHECK_ARG_RET(ctx, ctx || ctx_node, path, NULL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, ctx, ctx_node ? ctx_node->module->ctx : NULL, NULL);
|
||||
|
||||
if (!ctx) {
|
||||
ctx = ctx_node->module->ctx;
|
||||
}
|
||||
|
||||
/* parse */
|
||||
ret = ly_path_parse(ctx, ctx_node, path, strlen(path), 0, LY_PATH_BEGIN_EITHER, LY_PATH_PREFIX_FIRST,
|
||||
ret = ly_path_parse(ctx, ctx_node, path, 0, 0, LY_PATH_BEGIN_EITHER, LY_PATH_PREFIX_FIRST,
|
||||
LY_PATH_PRED_SIMPLE, &expr);
|
||||
LY_CHECK_GOTO(ret, cleanup);
|
||||
|
||||
|
@ -787,6 +788,7 @@ lysc_path_until(const struct lysc_node *node, const struct lysc_node *parent, LY
|
|||
if (buffer) {
|
||||
strcpy(buffer, "/");
|
||||
} else {
|
||||
free(path);
|
||||
path = strdup("/");
|
||||
}
|
||||
}
|
||||
|
@ -1420,35 +1422,147 @@ next_iter:
|
|||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate a warning if the filename does not match the expected module name and version.
|
||||
*
|
||||
* @param[in] ctx Context for logging
|
||||
* @param[in] name Expected module name
|
||||
* @param[in] revision Expected module revision, or NULL if not to be checked
|
||||
* @param[in] filename File path to be checked
|
||||
*/
|
||||
static void
|
||||
ly_check_module_filename(const struct ly_ctx *ctx, const char *name, const char *revision, const char *filename)
|
||||
{
|
||||
const char *basename, *rev, *dot;
|
||||
size_t len;
|
||||
|
||||
/* check that name and revision match filename */
|
||||
basename = strrchr(filename, '/');
|
||||
#ifdef _WIN32
|
||||
const char *backslash = strrchr(filename, '\\');
|
||||
|
||||
if (!basename || (basename && backslash && (backslash > basename))) {
|
||||
basename = backslash;
|
||||
}
|
||||
#endif
|
||||
if (!basename) {
|
||||
basename = filename;
|
||||
} else {
|
||||
basename++; /* leading slash */
|
||||
}
|
||||
rev = strchr(basename, '@');
|
||||
dot = strrchr(basename, '.');
|
||||
|
||||
/* name */
|
||||
len = strlen(name);
|
||||
if (strncmp(basename, name, len) ||
|
||||
((rev && (rev != &basename[len])) || (!rev && (dot != &basename[len])))) {
|
||||
LOGWRN(ctx, "File name \"%s\" does not match module name \"%s\".", basename, name);
|
||||
}
|
||||
if (rev) {
|
||||
len = dot - ++rev;
|
||||
if (!revision || (len != LY_REV_SIZE - 1) || strncmp(revision, rev, len)) {
|
||||
LOGWRN(ctx, "File name \"%s\" does not match module revision \"%s\".", basename,
|
||||
revision ? revision : "none");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check created (sub)module that it matches the expected module.
|
||||
*
|
||||
* @param[in] ctx Context to use.
|
||||
* @param[in] mod Parsed module.
|
||||
* @param[in] submod Parsed submodule.
|
||||
* @param[in] mod_data Expected module data.
|
||||
* @return LY_SUCCESS on success;
|
||||
* @return LY_EEXIST if the same module already exists;
|
||||
* @return LY_ERR on error.
|
||||
*/
|
||||
static LY_ERR
|
||||
lysp_load_module_data_check(const struct ly_ctx *ctx, struct lysp_module *mod, struct lysp_submodule *submod,
|
||||
const struct lysp_load_module_data *mod_data)
|
||||
{
|
||||
const char *name;
|
||||
uint8_t latest_revision;
|
||||
struct lysp_revision *revs;
|
||||
|
||||
name = mod ? mod->mod->name : submod->name;
|
||||
revs = mod ? mod->revs : submod->revs;
|
||||
latest_revision = mod ? mod->mod->latest_revision : submod->latest_revision;
|
||||
|
||||
if (mod_data->name) {
|
||||
/* check name of the parsed model */
|
||||
if (strcmp(mod_data->name, name)) {
|
||||
LOGERR(ctx, LY_EINVAL, "Unexpected module \"%s\" parsed instead of \"%s\".", name, mod_data->name);
|
||||
return LY_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (mod_data->revision) {
|
||||
/* check revision of the parsed model */
|
||||
if (!revs || strcmp(mod_data->revision, revs[0].date)) {
|
||||
LOGERR(ctx, LY_EINVAL, "Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").", name,
|
||||
revs ? revs[0].date : "none", mod_data->revision);
|
||||
return LY_EINVAL;
|
||||
}
|
||||
} else if (!latest_revision) {
|
||||
/* do not log, we just need to drop the schema and use the latest revision from the context */
|
||||
return LY_EEXIST;
|
||||
}
|
||||
|
||||
if (submod) {
|
||||
assert(mod_data->submoduleof);
|
||||
|
||||
/* check that the submodule belongs-to our module */
|
||||
if (strcmp(mod_data->submoduleof, submod->mod->name)) {
|
||||
LOGVAL(ctx, LYVE_REFERENCE, "Included \"%s\" submodule from \"%s\" belongs-to a different module \"%s\".",
|
||||
submod->name, mod_data->submoduleof, submod->mod->name);
|
||||
return LY_EVALID;
|
||||
}
|
||||
/* check circular dependency */
|
||||
if (submod->parsing) {
|
||||
LOGVAL(ctx, LYVE_REFERENCE, "A circular dependency (include) for module \"%s\".", submod->name);
|
||||
return LY_EVALID;
|
||||
}
|
||||
}
|
||||
|
||||
if (mod_data->path) {
|
||||
ly_check_module_filename(ctx, name, revs ? revs[0].date : NULL, mod_data->path);
|
||||
}
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
lys_parse_submodule(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, struct lysp_ctx *main_ctx,
|
||||
LY_ERR (*custom_check)(const struct ly_ctx *, struct lysp_module *, struct lysp_submodule *, void *),
|
||||
void *check_data, struct ly_set *new_mods, struct lysp_submodule **submodule)
|
||||
const struct lysp_load_module_data *mod_data, struct ly_set *new_mods, struct lysp_submodule **submodule)
|
||||
{
|
||||
LY_ERR ret;
|
||||
LY_ERR rc = LY_SUCCESS, r;
|
||||
struct lysp_submodule *submod = NULL, *latest_sp;
|
||||
struct lysp_yang_ctx *yangctx = NULL;
|
||||
struct lysp_yin_ctx *yinctx = NULL;
|
||||
struct lysp_ctx *pctx;
|
||||
struct lysp_ctx *pctx = NULL;
|
||||
struct lysf_ctx fctx = {.ctx = ctx};
|
||||
const char *submod_name;
|
||||
|
||||
LY_CHECK_ARG_RET(ctx, ctx, in, LY_EINVAL);
|
||||
|
||||
switch (format) {
|
||||
case LYS_IN_YIN:
|
||||
ret = yin_parse_submodule(&yinctx, ctx, main_ctx, in, &submod);
|
||||
rc = yin_parse_submodule(&yinctx, ctx, main_ctx, in, &submod);
|
||||
pctx = (struct lysp_ctx *)yinctx;
|
||||
break;
|
||||
case LYS_IN_YANG:
|
||||
ret = yang_parse_submodule(&yangctx, ctx, main_ctx, in, &submod);
|
||||
rc = yang_parse_submodule(&yangctx, ctx, main_ctx, in, &submod);
|
||||
pctx = (struct lysp_ctx *)yangctx;
|
||||
break;
|
||||
default:
|
||||
LOGERR(ctx, LY_EINVAL, "Invalid schema input format.");
|
||||
ret = LY_EINVAL;
|
||||
rc = LY_EINVAL;
|
||||
break;
|
||||
}
|
||||
LY_CHECK_GOTO(ret, error);
|
||||
LY_CHECK_GOTO(rc, cleanup);
|
||||
assert(submod);
|
||||
|
||||
/* make sure that the newest revision is at position 0 */
|
||||
|
@ -1475,8 +1589,21 @@ lys_parse_submodule(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, s
|
|||
submod->latest_revision = 1;
|
||||
}
|
||||
|
||||
if (custom_check) {
|
||||
LY_CHECK_GOTO(ret = custom_check(ctx, NULL, submod, check_data), error);
|
||||
if (mod_data) {
|
||||
/* check the parsed submodule it is as expected */
|
||||
r = lysp_load_module_data_check(ctx, NULL, submod, mod_data);
|
||||
if (r == LY_EEXIST) {
|
||||
/* not an error, the submodule already exists so free this one */
|
||||
ly_set_erase(&pctx->tpdfs_nodes, NULL);
|
||||
ly_set_erase(&pctx->grps_nodes, NULL);
|
||||
ly_set_erase(&pctx->ext_inst, NULL);
|
||||
lysp_module_free(&fctx, (struct lysp_module *)submod);
|
||||
submod = NULL;
|
||||
goto cleanup;
|
||||
} else if (r) {
|
||||
rc = r;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (latest_sp) {
|
||||
|
@ -1486,29 +1613,47 @@ lys_parse_submodule(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, s
|
|||
lys_parser_fill_filepath(ctx, in, &submod->filepath);
|
||||
|
||||
/* resolve imports and includes */
|
||||
LY_CHECK_GOTO(ret = lysp_resolve_import_include(pctx, (struct lysp_module *)submod, new_mods), error);
|
||||
LY_CHECK_GOTO(rc = lysp_resolve_import_include(pctx, (struct lysp_module *)submod, new_mods), cleanup);
|
||||
|
||||
cleanup:
|
||||
if (rc) {
|
||||
if (submod && submod->name) {
|
||||
submod_name = submod->name;
|
||||
} else if (mod_data) {
|
||||
submod_name = mod_data->name;
|
||||
} else {
|
||||
submod_name = NULL;
|
||||
}
|
||||
if (submod_name) {
|
||||
LOGERR(ctx, rc, "Parsing submodule \"%s\" failed.", submod_name);
|
||||
} else {
|
||||
LOGERR(ctx, rc, "Parsing submodule failed.");
|
||||
}
|
||||
|
||||
if (pctx) {
|
||||
ly_set_erase(&pctx->tpdfs_nodes, NULL);
|
||||
ly_set_erase(&pctx->grps_nodes, NULL);
|
||||
ly_set_erase(&pctx->ext_inst, NULL);
|
||||
}
|
||||
lysp_module_free(&fctx, (struct lysp_module *)submod);
|
||||
} else if (submod) {
|
||||
*submodule = submod;
|
||||
|
||||
/* merge submod unres into main_ctx unres */
|
||||
ly_set_merge(&pctx->main_ctx->tpdfs_nodes, &pctx->tpdfs_nodes, 1, NULL);
|
||||
ly_set_erase(&pctx->tpdfs_nodes, NULL);
|
||||
ly_set_merge(&pctx->main_ctx->grps_nodes, &pctx->grps_nodes, 1, NULL);
|
||||
ly_set_erase(&pctx->grps_nodes, NULL);
|
||||
ly_set_merge(&pctx->main_ctx->ext_inst, &pctx->ext_inst, 1, NULL);
|
||||
ly_set_erase(&pctx->ext_inst, NULL);
|
||||
}
|
||||
|
||||
if (format == LYS_IN_YANG) {
|
||||
lysp_yang_ctx_free(yangctx);
|
||||
} else {
|
||||
lysp_yin_ctx_free(yinctx);
|
||||
}
|
||||
*submodule = submod;
|
||||
return LY_SUCCESS;
|
||||
|
||||
error:
|
||||
if (!submod || !submod->name) {
|
||||
LOGERR(ctx, ret, "Parsing submodule failed.");
|
||||
} else {
|
||||
LOGERR(ctx, ret, "Parsing submodule \"%s\" failed.", submod->name);
|
||||
}
|
||||
lysp_module_free(&fctx, (struct lysp_module *)submod);
|
||||
if (format == LYS_IN_YANG) {
|
||||
lysp_yang_ctx_free(yangctx);
|
||||
} else {
|
||||
lysp_yin_ctx_free(yinctx);
|
||||
}
|
||||
return ret;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1524,6 +1669,9 @@ lysp_add_internal_ietf_netconf(struct lysp_ctx *pctx, struct lysp_module *mod)
|
|||
{
|
||||
struct lysp_ext_instance *extp, *prev_exts = mod->exts;
|
||||
struct lysp_stmt *stmt;
|
||||
struct lysp_node_leaf *leaf;
|
||||
struct lysp_node_container *cont;
|
||||
struct lysp_type_enum *enm;
|
||||
struct lysp_import *imp;
|
||||
uint32_t idx;
|
||||
|
||||
|
@ -1677,6 +1825,107 @@ lysp_add_internal_ietf_netconf(struct lysp_ctx *pctx, struct lysp_module *mod)
|
|||
pctx->ext_inst.objs[idx] = mod->exts;
|
||||
}
|
||||
|
||||
/*
|
||||
* 4) rpc-error
|
||||
*/
|
||||
LY_LIST_NEW_RET(mod->mod->ctx, &mod->data, cont, next, LY_EMEM);
|
||||
cont->nodetype = LYS_CONTAINER;
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "rpc-error", 0, &cont->name));
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "presence", 0, &cont->presence));
|
||||
cont->flags = LYS_INTERNAL;
|
||||
|
||||
LY_LIST_NEW_RET(mod->mod->ctx, &cont->child, leaf, next, LY_EMEM);
|
||||
leaf->nodetype = LYS_LEAF;
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "error-type", 0, &leaf->name));
|
||||
leaf->flags = LYS_INTERNAL;
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "enumeration", 0, &leaf->type.name));
|
||||
leaf->type.pmod = mod;
|
||||
leaf->type.flags = LYS_SET_ENUM;
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "transport", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "rpc", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "protocol", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "application", 0, &enm->name));
|
||||
|
||||
LY_LIST_NEW_RET(mod->mod->ctx, &cont->child, leaf, next, LY_EMEM);
|
||||
leaf->nodetype = LYS_LEAF;
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "error-tag", 0, &leaf->name));
|
||||
leaf->flags = LYS_INTERNAL;
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "enumeration", 0, &leaf->type.name));
|
||||
leaf->type.pmod = mod;
|
||||
leaf->type.flags = LYS_SET_ENUM;
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "in-use", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "invalid-value", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "too-big", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "missing-attribute", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "bad-attribute", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "unknown-attribute", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "missing-element", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "bad-element", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "unknown-element", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "unknown-namespace", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "access-denied", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "lock-denied", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "resource-denied", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "rollback-failed", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "data-exists", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "data-missing", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "operation-not-supported", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "operation-failed", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "partial-operation", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "malformed-message", 0, &enm->name));
|
||||
|
||||
LY_LIST_NEW_RET(mod->mod->ctx, &cont->child, leaf, next, LY_EMEM);
|
||||
leaf->nodetype = LYS_LEAF;
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "error-severity", 0, &leaf->name));
|
||||
leaf->flags = LYS_INTERNAL;
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "enumeration", 0, &leaf->type.name));
|
||||
leaf->type.pmod = mod;
|
||||
leaf->type.flags = LYS_SET_ENUM;
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "error", 0, &enm->name));
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "warning", 0, &enm->name));
|
||||
|
||||
LY_LIST_NEW_RET(mod->mod->ctx, &cont->child, leaf, next, LY_EMEM);
|
||||
leaf->nodetype = LYS_LEAF;
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "error-app-tag", 0, &leaf->name));
|
||||
leaf->flags = LYS_INTERNAL;
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "string", 0, &leaf->type.name));
|
||||
leaf->type.pmod = mod;
|
||||
|
||||
LY_LIST_NEW_RET(mod->mod->ctx, &cont->child, leaf, next, LY_EMEM);
|
||||
leaf->nodetype = LYS_LEAF;
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "error-path", 0, &leaf->name));
|
||||
leaf->flags = LYS_INTERNAL;
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "yang_:xpath1.0", 0, &leaf->type.name));
|
||||
leaf->type.pmod = mod;
|
||||
|
||||
/* the rest are opaque nodes, error-message (because of 'xml:lang' attribute) and error-info (because can be any nodes) */
|
||||
|
||||
/* create new imports for the used prefixes */
|
||||
LY_ARRAY_NEW_RET(mod->mod->ctx, mod->imports, imp, LY_EMEM);
|
||||
LY_CHECK_RET(lydict_insert(mod->mod->ctx, "ietf-yang-metadata", 0, &imp->name));
|
||||
|
@ -1810,17 +2059,16 @@ lysp_add_internal_yang(struct lysp_ctx *pctx, struct lysp_module *mod)
|
|||
}
|
||||
|
||||
LY_ERR
|
||||
lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format,
|
||||
LY_ERR (*custom_check)(const struct ly_ctx *ctx, struct lysp_module *mod, struct lysp_submodule *submod, void *data),
|
||||
void *check_data, struct ly_set *new_mods, struct lys_module **module)
|
||||
lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, const struct lysp_load_module_data *mod_data,
|
||||
struct ly_set *new_mods, struct lys_module **module)
|
||||
{
|
||||
LY_ERR rc = LY_SUCCESS, r;
|
||||
struct lys_module *mod = NULL, *latest, *mod_dup = NULL;
|
||||
LY_ERR ret;
|
||||
struct lysp_yang_ctx *yangctx = NULL;
|
||||
struct lysp_yin_ctx *yinctx = NULL;
|
||||
struct lysp_ctx *pctx = NULL;
|
||||
struct lysf_ctx fctx = {.ctx = ctx};
|
||||
ly_bool module_created = 0;
|
||||
ly_bool mod_created = 0, mod_exists = 0;
|
||||
|
||||
assert(ctx && in && new_mods);
|
||||
|
||||
|
@ -1835,24 +2083,24 @@ lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format,
|
|||
/* parse */
|
||||
switch (format) {
|
||||
case LYS_IN_YIN:
|
||||
ret = yin_parse_module(&yinctx, in, mod);
|
||||
rc = yin_parse_module(&yinctx, in, mod);
|
||||
pctx = (struct lysp_ctx *)yinctx;
|
||||
break;
|
||||
case LYS_IN_YANG:
|
||||
ret = yang_parse_module(&yangctx, in, mod);
|
||||
rc = yang_parse_module(&yangctx, in, mod);
|
||||
pctx = (struct lysp_ctx *)yangctx;
|
||||
break;
|
||||
default:
|
||||
LOGERR(ctx, LY_EINVAL, "Invalid schema input format.");
|
||||
ret = LY_EINVAL;
|
||||
rc = LY_EINVAL;
|
||||
break;
|
||||
}
|
||||
LY_CHECK_GOTO(ret, cleanup);
|
||||
LY_CHECK_GOTO(rc, cleanup);
|
||||
|
||||
/* make sure that the newest revision is at position 0 */
|
||||
lysp_sort_revisions(mod->parsed->revs);
|
||||
if (mod->parsed->revs) {
|
||||
LY_CHECK_GOTO(ret = lydict_insert(ctx, mod->parsed->revs[0].date, 0, &mod->revision), cleanup);
|
||||
LY_CHECK_GOTO(rc = lydict_insert(ctx, mod->parsed->revs[0].date, 0, &mod->revision), cleanup);
|
||||
}
|
||||
|
||||
/* decide the latest revision */
|
||||
|
@ -1876,8 +2124,16 @@ lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format,
|
|||
mod->latest_revision = LYS_MOD_LATEST_REV;
|
||||
}
|
||||
|
||||
if (custom_check) {
|
||||
LY_CHECK_GOTO(ret = custom_check(ctx, mod->parsed, NULL, check_data), cleanup);
|
||||
if (mod_data) {
|
||||
/* check the parsed module it is as expected */
|
||||
r = lysp_load_module_data_check(ctx, mod->parsed, NULL, mod_data);
|
||||
if (r == LY_EEXIST) {
|
||||
mod_exists = 1;
|
||||
goto cleanup;
|
||||
} else if (r) {
|
||||
rc = r;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* check whether it is not already in the context in the same revision */
|
||||
|
@ -1894,7 +2150,7 @@ lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format,
|
|||
if (mod_dup && (mod_dup->revision == mod->revision)) {
|
||||
LOGERR(ctx, LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\".",
|
||||
mod_dup->name, mod->name, mod->ns);
|
||||
ret = LY_EINVAL;
|
||||
rc = LY_EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
@ -1909,7 +2165,7 @@ lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format,
|
|||
break;
|
||||
case LY_IN_ERROR:
|
||||
LOGINT(ctx);
|
||||
ret = LY_EINT;
|
||||
rc = LY_EINT;
|
||||
goto cleanup;
|
||||
}
|
||||
lys_parser_fill_filepath(ctx, in, &mod->filepath);
|
||||
|
@ -1920,53 +2176,51 @@ lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format,
|
|||
|
||||
/* add internal data in case specific modules were parsed */
|
||||
if (!strcmp(mod->name, "ietf-netconf")) {
|
||||
LY_CHECK_GOTO(ret = lysp_add_internal_ietf_netconf(pctx, mod->parsed), cleanup);
|
||||
LY_CHECK_GOTO(rc = lysp_add_internal_ietf_netconf(pctx, mod->parsed), cleanup);
|
||||
} else if (!strcmp(mod->name, "ietf-netconf-with-defaults")) {
|
||||
LY_CHECK_GOTO(ret = lysp_add_internal_ietf_netconf_with_defaults(pctx, mod->parsed), cleanup);
|
||||
LY_CHECK_GOTO(rc = lysp_add_internal_ietf_netconf_with_defaults(pctx, mod->parsed), cleanup);
|
||||
} else if (!strcmp(mod->name, "yang")) {
|
||||
LY_CHECK_GOTO(ret = lysp_add_internal_yang(pctx, mod->parsed), cleanup);
|
||||
LY_CHECK_GOTO(rc = lysp_add_internal_yang(pctx, mod->parsed), cleanup);
|
||||
}
|
||||
|
||||
/* add the module into newly created module set, will also be freed from there on any error */
|
||||
LY_CHECK_GOTO(ret = ly_set_add(new_mods, mod, 1, NULL), cleanup);
|
||||
module_created = 1;
|
||||
LY_CHECK_GOTO(rc = ly_set_add(new_mods, mod, 1, NULL), cleanup);
|
||||
mod_created = 1;
|
||||
|
||||
/* add into context */
|
||||
ret = ly_set_add(&ctx->list, mod, 1, NULL);
|
||||
LY_CHECK_GOTO(ret, cleanup);
|
||||
rc = ly_set_add(&ctx->list, mod, 1, NULL);
|
||||
LY_CHECK_GOTO(rc, cleanup);
|
||||
ctx->change_count++;
|
||||
|
||||
/* resolve includes and all imports */
|
||||
LY_CHECK_GOTO(ret = lysp_resolve_import_include(pctx, mod->parsed, new_mods), cleanup);
|
||||
LY_CHECK_GOTO(rc = lysp_resolve_import_include(pctx, mod->parsed, new_mods), cleanup);
|
||||
|
||||
/* resolve extension instance plugin records */
|
||||
LY_CHECK_GOTO(ret = lysp_resolve_ext_instance_records(pctx), cleanup);
|
||||
LY_CHECK_GOTO(rc = lysp_resolve_ext_instance_records(pctx), cleanup);
|
||||
|
||||
/* check name collisions */
|
||||
LY_CHECK_GOTO(ret = lysp_check_dup_typedefs(pctx, mod->parsed), cleanup);
|
||||
LY_CHECK_GOTO(ret = lysp_check_dup_groupings(pctx, mod->parsed), cleanup);
|
||||
LY_CHECK_GOTO(ret = lysp_check_dup_features(pctx, mod->parsed), cleanup);
|
||||
LY_CHECK_GOTO(ret = lysp_check_dup_identities(pctx, mod->parsed), cleanup);
|
||||
LY_CHECK_GOTO(rc = lysp_check_dup_typedefs(pctx, mod->parsed), cleanup);
|
||||
LY_CHECK_GOTO(rc = lysp_check_dup_groupings(pctx, mod->parsed), cleanup);
|
||||
LY_CHECK_GOTO(rc = lysp_check_dup_features(pctx, mod->parsed), cleanup);
|
||||
LY_CHECK_GOTO(rc = lysp_check_dup_identities(pctx, mod->parsed), cleanup);
|
||||
|
||||
/* compile features */
|
||||
LY_CHECK_GOTO(ret = lys_compile_feature_iffeatures(mod->parsed), cleanup);
|
||||
LY_CHECK_GOTO(rc = lys_compile_feature_iffeatures(mod->parsed), cleanup);
|
||||
|
||||
/* compile identities */
|
||||
LY_CHECK_GOTO(ret = lys_compile_identities(mod), cleanup);
|
||||
LY_CHECK_GOTO(rc = lys_compile_identities(mod), cleanup);
|
||||
|
||||
cleanup:
|
||||
if (ret && (ret != LY_EEXIST)) {
|
||||
if (mod && mod->name) {
|
||||
/* there are cases when path is not available for parsing error, so this additional
|
||||
* message tries to add information about the module where the error occurred */
|
||||
const struct ly_err_item *e = ly_err_last(ctx);
|
||||
if (rc && mod && mod->name) {
|
||||
/* there are cases when path is not available for parsing error, so this additional
|
||||
* message tries to add information about the module where the error occurred */
|
||||
const struct ly_err_item *e = ly_err_last(ctx);
|
||||
|
||||
if (e && (!e->schema_path || e->line)) {
|
||||
LOGERR(ctx, LY_EOTHER, "Parsing module \"%s\" failed.", mod->name);
|
||||
}
|
||||
if (e && (!e->schema_path || e->line)) {
|
||||
LOGERR(ctx, LY_EOTHER, "Parsing module \"%s\" failed.", mod->name);
|
||||
}
|
||||
}
|
||||
if (!module_created) {
|
||||
if (!mod_created) {
|
||||
fctx.mod = mod;
|
||||
lys_module_free(&fctx, mod, 0);
|
||||
lysf_ctx_erase(&fctx);
|
||||
|
@ -1980,10 +2234,10 @@ cleanup:
|
|||
lysp_yin_ctx_free(yinctx);
|
||||
}
|
||||
|
||||
if (!ret && module) {
|
||||
if (!rc && !mod_exists && module) {
|
||||
*module = mod;
|
||||
}
|
||||
return ret;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static LYS_INFORMAT
|
||||
|
@ -2027,7 +2281,7 @@ lys_parse(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, const char
|
|||
in->func_start = in->current;
|
||||
|
||||
/* parse */
|
||||
ret = lys_parse_in(ctx, in, format, NULL, NULL, &ctx->unres.creating, &mod);
|
||||
ret = lys_parse_in(ctx, in, format, NULL, &ctx->unres.creating, &mod);
|
||||
LY_CHECK_GOTO(ret, cleanup);
|
||||
|
||||
/* implement */
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief libyang representation of YANG schema trees.
|
||||
*
|
||||
* Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
|
||||
* Copyright (c) 2015 - 2025 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.
|
||||
|
@ -1908,13 +1908,39 @@ LIBYANG_API_DECL struct lysc_must *lysc_node_musts(const struct lysc_node *node)
|
|||
LIBYANG_API_DECL struct lysc_when **lysc_node_when(const struct lysc_node *node);
|
||||
|
||||
/**
|
||||
* @brief Get the target node of a leafref node.
|
||||
* @brief Get the target node of a leafref node. Function ::lysc_node_lref_targets() should be used instead
|
||||
* to get all the leafref targets even for a union node.
|
||||
*
|
||||
* @param[in] node Leafref node.
|
||||
* @return Leafref target, NULL on any error.
|
||||
*/
|
||||
LIBYANG_API_DECL const struct lysc_node *lysc_node_lref_target(const struct lysc_node *node);
|
||||
|
||||
/**
|
||||
* @brief Get the target node(s) of a leafref node or union node with leafrefs.
|
||||
*
|
||||
* @param[in] node Term node to use.
|
||||
* @param[out] set Set with all the leafref targets, may be empty if the node is a different type or the targets
|
||||
* are not found.
|
||||
* @return LY_SUCCESS on success.
|
||||
* @return LY_ERR value on error.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR lysc_node_lref_targets(const struct lysc_node *node, struct ly_set **set);
|
||||
|
||||
/**
|
||||
* @brief Get all the leafref (or union with leafrefs) nodes that target a specific node.
|
||||
*
|
||||
* @param[in] ctx Context to use, may not be set if @p node is.
|
||||
* @param[in] node Leafref target node to use for matching. If not set, all the leafref nodes are just collected.
|
||||
* @param[in] match_ancestors If set, @p node is considered a match not only when a leafref targets it directly but
|
||||
* even when an ancestor (parent) node of @p node is a target of the leafref.
|
||||
* @param[out] set Set of matching leafref nodes.
|
||||
* @return LY_SUCCESS on success.
|
||||
* @return LY_ERR value on error.
|
||||
*/
|
||||
LIBYANG_API_DECL LY_ERR lysc_node_lref_backlinks(const struct ly_ctx *ctx, const struct lysc_node *node,
|
||||
ly_bool match_ancestors, struct ly_set **set);
|
||||
|
||||
/**
|
||||
* @brief Callback to be called for every schema node in a DFS traversal.
|
||||
*
|
||||
|
|
|
@ -686,64 +686,6 @@ cleanup:
|
|||
return ret;
|
||||
}
|
||||
|
||||
struct lysp_load_module_check_data {
|
||||
const char *name;
|
||||
const char *revision;
|
||||
const char *path;
|
||||
const char *submoduleof;
|
||||
};
|
||||
|
||||
static LY_ERR
|
||||
lysp_load_module_check(const struct ly_ctx *ctx, struct lysp_module *mod, struct lysp_submodule *submod, void *data)
|
||||
{
|
||||
struct lysp_load_module_check_data *info = data;
|
||||
const char *name;
|
||||
uint8_t latest_revision;
|
||||
struct lysp_revision *revs;
|
||||
|
||||
name = mod ? mod->mod->name : submod->name;
|
||||
revs = mod ? mod->revs : submod->revs;
|
||||
latest_revision = mod ? mod->mod->latest_revision : submod->latest_revision;
|
||||
|
||||
if (info->name) {
|
||||
/* check name of the parsed model */
|
||||
if (strcmp(info->name, name)) {
|
||||
LOGERR(ctx, LY_EINVAL, "Unexpected module \"%s\" parsed instead of \"%s\").", name, info->name);
|
||||
return LY_EINVAL;
|
||||
}
|
||||
}
|
||||
if (info->revision) {
|
||||
/* check revision of the parsed model */
|
||||
if (!revs || strcmp(info->revision, revs[0].date)) {
|
||||
LOGERR(ctx, LY_EINVAL, "Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").", name,
|
||||
revs ? revs[0].date : "none", info->revision);
|
||||
return LY_EINVAL;
|
||||
}
|
||||
} else if (!latest_revision) {
|
||||
/* do not log, we just need to drop the schema and use the latest revision from the context */
|
||||
return LY_EEXIST;
|
||||
}
|
||||
if (submod) {
|
||||
assert(info->submoduleof);
|
||||
|
||||
/* check that the submodule belongs-to our module */
|
||||
if (strcmp(info->submoduleof, submod->mod->name)) {
|
||||
LOGVAL(ctx, LYVE_REFERENCE, "Included \"%s\" submodule from \"%s\" belongs-to a different module \"%s\".",
|
||||
submod->name, info->submoduleof, submod->mod->name);
|
||||
return LY_EVALID;
|
||||
}
|
||||
/* check circular dependency */
|
||||
if (submod->parsing) {
|
||||
LOGVAL(ctx, LYVE_REFERENCE, "A circular dependency (include) for module \"%s\".", submod->name);
|
||||
return LY_EVALID;
|
||||
}
|
||||
}
|
||||
if (info->path) {
|
||||
ly_check_module_filename(ctx, name, revs ? revs[0].date : NULL, info->path);
|
||||
}
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse a (sub)module from a local file and add into the context.
|
||||
*
|
||||
|
@ -771,7 +713,7 @@ lys_parse_localfile(struct ly_ctx *ctx, const char *name, const char *revision,
|
|||
LYS_INFORMAT format = 0;
|
||||
void *mod = NULL;
|
||||
LY_ERR ret = LY_SUCCESS;
|
||||
struct lysp_load_module_check_data check_data = {0};
|
||||
struct lysp_load_module_data mod_data = {0};
|
||||
|
||||
LY_CHECK_RET(lys_search_localfile(ly_ctx_get_searchdirs(ctx), !(ctx->flags & LY_CTX_DISABLE_SEARCHDIR_CWD), name,
|
||||
revision, &filepath, &format));
|
||||
|
@ -779,8 +721,9 @@ lys_parse_localfile(struct ly_ctx *ctx, const char *name, const char *revision,
|
|||
if (required) {
|
||||
LOGERR(ctx, LY_ENOTFOUND, "Data model \"%s%s%s\" not found in local searchdirs.", name, revision ? "@" : "",
|
||||
revision ? revision : "");
|
||||
ret = LY_ENOTFOUND;
|
||||
}
|
||||
return LY_ENOTFOUND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
LOGVRB("Loading schema from \"%s\" file.", filepath);
|
||||
|
@ -788,15 +731,14 @@ lys_parse_localfile(struct ly_ctx *ctx, const char *name, const char *revision,
|
|||
/* get the (sub)module */
|
||||
LY_CHECK_ERR_GOTO(ret = ly_in_new_filepath(filepath, 0, &in),
|
||||
LOGERR(ctx, ret, "Unable to create input handler for filepath %s.", filepath), cleanup);
|
||||
check_data.name = name;
|
||||
check_data.revision = revision;
|
||||
check_data.path = filepath;
|
||||
check_data.submoduleof = main_name;
|
||||
mod_data.name = name;
|
||||
mod_data.revision = revision;
|
||||
mod_data.path = filepath;
|
||||
mod_data.submoduleof = main_name;
|
||||
if (main_ctx) {
|
||||
ret = lys_parse_submodule(ctx, in, format, main_ctx, lysp_load_module_check, &check_data, new_mods,
|
||||
(struct lysp_submodule **)&mod);
|
||||
ret = lys_parse_submodule(ctx, in, format, main_ctx, &mod_data, new_mods, (struct lysp_submodule **)&mod);
|
||||
} else {
|
||||
ret = lys_parse_in(ctx, in, format, lysp_load_module_check, &check_data, new_mods, (struct lys_module **)&mod);
|
||||
ret = lys_parse_in(ctx, in, format, &mod_data, new_mods, (struct lys_module **)&mod);
|
||||
|
||||
}
|
||||
ly_in_free(in, 1);
|
||||
|
@ -804,8 +746,6 @@ lys_parse_localfile(struct ly_ctx *ctx, const char *name, const char *revision,
|
|||
|
||||
*result = mod;
|
||||
|
||||
/* success */
|
||||
|
||||
cleanup:
|
||||
free(filepath);
|
||||
return ret;
|
||||
|
@ -827,11 +767,12 @@ static LY_ERR
|
|||
lys_parse_load_from_clb_or_file(struct ly_ctx *ctx, const char *name, const char *revision,
|
||||
struct lys_module *mod_latest, struct ly_set *new_mods, struct lys_module **mod)
|
||||
{
|
||||
LY_ERR r;
|
||||
const char *module_data = NULL;
|
||||
LYS_INFORMAT format = LYS_IN_UNKNOWN;
|
||||
|
||||
void (*module_data_free)(void *module_data, void *user_data) = NULL;
|
||||
struct lysp_load_module_check_data check_data = {0};
|
||||
struct lysp_load_module_data mod_data = {0};
|
||||
struct ly_in *in;
|
||||
|
||||
*mod = NULL;
|
||||
|
@ -848,13 +789,14 @@ search_clb:
|
|||
if (ctx->imp_clb && (!mod_latest || !(mod_latest->latest_revision & LYS_MOD_LATEST_IMPCLB))) {
|
||||
if (!ctx->imp_clb(name, revision, NULL, NULL, ctx->imp_clb_data, &format, &module_data, &module_data_free)) {
|
||||
LY_CHECK_RET(ly_in_new_memory(module_data, &in));
|
||||
check_data.name = name;
|
||||
check_data.revision = revision;
|
||||
lys_parse_in(ctx, in, format, lysp_load_module_check, &check_data, new_mods, mod);
|
||||
mod_data.name = name;
|
||||
mod_data.revision = revision;
|
||||
r = lys_parse_in(ctx, in, format, &mod_data, new_mods, mod);
|
||||
ly_in_free(in, 0);
|
||||
if (module_data_free) {
|
||||
module_data_free((void *)module_data, ctx->imp_clb_data);
|
||||
}
|
||||
LY_CHECK_RET(r);
|
||||
}
|
||||
}
|
||||
if (*mod && !revision) {
|
||||
|
@ -868,7 +810,7 @@ search_file:
|
|||
/* check we can use searchdirs and that we should */
|
||||
if (!(ctx->flags & LY_CTX_DISABLE_SEARCHDIRS) &&
|
||||
(!mod_latest || !(mod_latest->latest_revision & LYS_MOD_LATEST_SEARCHDIRS))) {
|
||||
lys_parse_localfile(ctx, name, revision, NULL, NULL, mod_latest ? 0 : 1, new_mods, (void **)mod);
|
||||
LY_CHECK_RET(lys_parse_localfile(ctx, name, revision, NULL, NULL, mod_latest ? 0 : 1, new_mods, (void **)mod));
|
||||
}
|
||||
if (*mod && !revision) {
|
||||
/* we got the latest revision module in the searchdirs */
|
||||
|
@ -878,6 +820,11 @@ search_file:
|
|||
}
|
||||
}
|
||||
|
||||
if (!*mod && !mod_latest) {
|
||||
LOGVAL(ctx, LYVE_REFERENCE, "Loading \"%s\" module failed, not found.", name);
|
||||
return LY_ENOTFOUND;
|
||||
}
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -972,10 +919,6 @@ lys_parse_load(struct ly_ctx *ctx, const char *name, const char *revision, struc
|
|||
if (!*mod) {
|
||||
/* No suitable module in the context, try to load it. */
|
||||
LY_CHECK_RET(lys_parse_load_from_clb_or_file(ctx, name, revision, mod_latest, new_mods, mod));
|
||||
if (!*mod && !mod_latest) {
|
||||
LOGVAL(ctx, LYVE_REFERENCE, "Loading \"%s\" module failed.", name);
|
||||
return LY_EVALID;
|
||||
}
|
||||
|
||||
/* Update the latest_revision flag - here we have selected the latest available schema,
|
||||
* consider that even the callback provides correct latest revision.
|
||||
|
@ -1171,22 +1114,29 @@ lysp_inject_submodule(struct lysp_ctx *pctx, struct lysp_include *inc)
|
|||
LY_ERR
|
||||
lysp_load_submodules(struct lysp_ctx *pctx, struct lysp_module *pmod, struct ly_set *new_mods)
|
||||
{
|
||||
LY_ARRAY_COUNT_TYPE u;
|
||||
LY_ERR r;
|
||||
struct ly_ctx *ctx = PARSER_CTX(pctx);
|
||||
struct lysp_submodule *submod;
|
||||
struct lysp_include *inc;
|
||||
LY_ARRAY_COUNT_TYPE u;
|
||||
ly_bool submod_included;
|
||||
|
||||
LY_ARRAY_FOR(pmod->includes, u) {
|
||||
LY_ERR ret = LY_SUCCESS, r;
|
||||
struct lysp_submodule *submod = NULL;
|
||||
struct lysp_include *inc = &pmod->includes[u];
|
||||
|
||||
inc = &pmod->includes[u];
|
||||
if (inc->submodule) {
|
||||
continue;
|
||||
}
|
||||
|
||||
submod = NULL;
|
||||
submod_included = 1;
|
||||
if (pmod->is_submod) {
|
||||
/* try to find the submodule in the main module or its submodules */
|
||||
ret = lysp_main_pmod_get_submodule(pctx, inc);
|
||||
LY_CHECK_RET(ret != LY_ENOT, ret);
|
||||
r = lysp_main_pmod_get_submodule(pctx, inc);
|
||||
if (r == LY_ENOT) {
|
||||
submod_included = 0;
|
||||
} else if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* try to use currently parsed submodule */
|
||||
|
@ -1201,27 +1151,25 @@ search_clb:
|
|||
LYS_INFORMAT format = LYS_IN_UNKNOWN;
|
||||
|
||||
void (*submodule_data_free)(void *module_data, void *user_data) = NULL;
|
||||
struct lysp_load_module_check_data check_data = {0};
|
||||
struct lysp_load_module_data mod_data = {0};
|
||||
struct ly_in *in;
|
||||
|
||||
if (ctx->imp_clb(PARSER_CUR_PMOD(pctx)->mod->name, NULL, inc->name,
|
||||
inc->rev[0] ? inc->rev : NULL, ctx->imp_clb_data,
|
||||
&format, &submodule_data, &submodule_data_free) == LY_SUCCESS) {
|
||||
if (ctx->imp_clb(PARSER_CUR_PMOD(pctx)->mod->name, NULL, inc->name, inc->rev[0] ? inc->rev : NULL,
|
||||
ctx->imp_clb_data, &format, &submodule_data, &submodule_data_free) == LY_SUCCESS) {
|
||||
LY_CHECK_RET(ly_in_new_memory(submodule_data, &in));
|
||||
check_data.name = inc->name;
|
||||
check_data.revision = inc->rev[0] ? inc->rev : NULL;
|
||||
check_data.submoduleof = PARSER_CUR_PMOD(pctx)->mod->name;
|
||||
lys_parse_submodule(ctx, in, format, pctx->main_ctx, lysp_load_module_check, &check_data, new_mods,
|
||||
&submod);
|
||||
|
||||
/* update inc pointer - parsing another (YANG 1.0) submodule can cause injecting
|
||||
* submodule's include into main module, where it is missing */
|
||||
inc = &pmod->includes[u];
|
||||
|
||||
mod_data.name = inc->name;
|
||||
mod_data.revision = inc->rev[0] ? inc->rev : NULL;
|
||||
mod_data.submoduleof = PARSER_CUR_PMOD(pctx)->mod->name;
|
||||
r = lys_parse_submodule(ctx, in, format, pctx->main_ctx, &mod_data, new_mods, &submod);
|
||||
ly_in_free(in, 0);
|
||||
if (submodule_data_free) {
|
||||
submodule_data_free((void *)submodule_data, ctx->imp_clb_data);
|
||||
}
|
||||
LY_CHECK_RET(r);
|
||||
|
||||
/* update inc pointer - parsing another (YANG 1.0) submodule can cause injecting
|
||||
* submodule's include into main module, where it is missing */
|
||||
inc = &pmod->includes[u];
|
||||
}
|
||||
}
|
||||
if (!submod && !(ctx->flags & LY_CTX_PREFER_SEARCHDIRS)) {
|
||||
|
@ -1250,7 +1198,7 @@ search_file:
|
|||
}
|
||||
|
||||
inc->submodule = submod;
|
||||
if (ret == LY_ENOT) {
|
||||
if (!submod_included) {
|
||||
/* the submodule include is not present in YANG 1.0 main module - add it there */
|
||||
LY_CHECK_RET(lysp_inject_submodule(pctx, &pmod->includes[u]));
|
||||
}
|
||||
|
@ -1380,6 +1328,10 @@ lys_datatype2str(LY_DATA_TYPE basetype)
|
|||
LIBYANG_API_DEF const struct lysp_tpdf *
|
||||
lysp_node_typedefs(const struct lysp_node *node)
|
||||
{
|
||||
if (!node) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (node->nodetype) {
|
||||
case LYS_CONTAINER:
|
||||
return ((struct lysp_node_container *)node)->typedefs;
|
||||
|
@ -1403,6 +1355,10 @@ lysp_node_typedefs(const struct lysp_node *node)
|
|||
LIBYANG_API_DEF const struct lysp_node_grp *
|
||||
lysp_node_groupings(const struct lysp_node *node)
|
||||
{
|
||||
if (!node) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (node->nodetype) {
|
||||
case LYS_CONTAINER:
|
||||
return ((struct lysp_node_container *)node)->groupings;
|
||||
|
@ -1447,6 +1403,10 @@ lysp_node_actions(const struct lysp_node *node)
|
|||
{
|
||||
struct lysp_node_action **actions;
|
||||
|
||||
if (!node) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
actions = lysp_node_actions_p((struct lysp_node *)node);
|
||||
if (actions) {
|
||||
return *actions;
|
||||
|
@ -1478,6 +1438,10 @@ lysp_node_notifs(const struct lysp_node *node)
|
|||
{
|
||||
struct lysp_node_notif **notifs;
|
||||
|
||||
if (!node) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
notifs = lysp_node_notifs_p((struct lysp_node *)node);
|
||||
if (notifs) {
|
||||
return *notifs;
|
||||
|
@ -1621,6 +1585,7 @@ struct lysc_node_action **
|
|||
lysc_node_actions_p(struct lysc_node *node)
|
||||
{
|
||||
assert(node);
|
||||
|
||||
switch (node->nodetype) {
|
||||
case LYS_CONTAINER:
|
||||
return &((struct lysc_node_container *)node)->actions;
|
||||
|
@ -1636,6 +1601,10 @@ lysc_node_actions(const struct lysc_node *node)
|
|||
{
|
||||
struct lysc_node_action **actions;
|
||||
|
||||
if (!node) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
actions = lysc_node_actions_p((struct lysc_node *)node);
|
||||
if (actions) {
|
||||
return *actions;
|
||||
|
@ -1648,6 +1617,7 @@ struct lysc_node_notif **
|
|||
lysc_node_notifs_p(struct lysc_node *node)
|
||||
{
|
||||
assert(node);
|
||||
|
||||
switch (node->nodetype) {
|
||||
case LYS_CONTAINER:
|
||||
return &((struct lysc_node_container *)node)->notifs;
|
||||
|
@ -1663,6 +1633,10 @@ lysc_node_notifs(const struct lysc_node *node)
|
|||
{
|
||||
struct lysc_node_notif **notifs;
|
||||
|
||||
if (!node) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
notifs = lysc_node_notifs_p((struct lysc_node *)node);
|
||||
if (notifs) {
|
||||
return *notifs;
|
||||
|
@ -1750,6 +1724,10 @@ lysc_node_musts(const struct lysc_node *node)
|
|||
{
|
||||
struct lysc_must **must_p;
|
||||
|
||||
if (!node) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
must_p = lysc_node_musts_p(node);
|
||||
if (must_p) {
|
||||
return *must_p;
|
||||
|
@ -1796,6 +1774,10 @@ lysc_node_when(const struct lysc_node *node)
|
|||
{
|
||||
struct lysc_when ***when_p;
|
||||
|
||||
if (!node) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
when_p = lysc_node_when_p(node);
|
||||
if (when_p) {
|
||||
return *when_p;
|
||||
|
@ -1804,21 +1786,24 @@ lysc_node_when(const struct lysc_node *node)
|
|||
}
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF const struct lysc_node *
|
||||
lysc_node_lref_target(const struct lysc_node *node)
|
||||
/**
|
||||
* @brief Get the target node of a leafref.
|
||||
*
|
||||
* @param[in] node Context node for the leafref.
|
||||
* @param[in] type Leafref type to resolve.
|
||||
* @return Target schema node;
|
||||
* @return NULL if the tearget is not found.
|
||||
*/
|
||||
static const struct lysc_node *
|
||||
lysc_type_lref_target(const struct lysc_node *node, const struct lysc_type *type)
|
||||
{
|
||||
struct lysc_type_leafref *lref;
|
||||
struct ly_path *p;
|
||||
const struct lysc_node *target;
|
||||
|
||||
if (!node || !(node->nodetype & LYD_NODE_TERM)) {
|
||||
return NULL;
|
||||
}
|
||||
assert(type->basetype == LY_TYPE_LEAFREF);
|
||||
|
||||
lref = (struct lysc_type_leafref *)((struct lysc_node_leaf *)node)->type;
|
||||
if (lref->basetype != LY_TYPE_LEAFREF) {
|
||||
return NULL;
|
||||
}
|
||||
lref = (struct lysc_type_leafref *)type;
|
||||
|
||||
/* compile the path */
|
||||
if (ly_path_compile_leafref(node->module->ctx, node, NULL, lref->path,
|
||||
|
@ -1834,6 +1819,164 @@ lysc_node_lref_target(const struct lysc_node *node)
|
|||
return target;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF const struct lysc_node *
|
||||
lysc_node_lref_target(const struct lysc_node *node)
|
||||
{
|
||||
if (!node || !(node->nodetype & LYD_NODE_TERM) || (((struct lysc_node_leaf *)node)->type->basetype != LY_TYPE_LEAFREF)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return lysc_type_lref_target(node, ((struct lysc_node_leaf *)node)->type);
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
lysc_node_lref_targets(const struct lysc_node *node, struct ly_set **set)
|
||||
{
|
||||
LY_ERR rc = LY_SUCCESS;
|
||||
struct lysc_type *type;
|
||||
struct lysc_type_union *type_un;
|
||||
const struct lysc_node *target;
|
||||
LY_ARRAY_COUNT_TYPE u;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, node, (node->nodetype & LYD_NODE_TERM), LY_EINVAL);
|
||||
|
||||
/* allocate return set */
|
||||
LY_CHECK_RET(ly_set_new(set));
|
||||
|
||||
type = ((struct lysc_node_leaf *)node)->type;
|
||||
if (type->basetype == LY_TYPE_UNION) {
|
||||
/* union with possible leafrefs */
|
||||
type_un = (struct lysc_type_union *)type;
|
||||
|
||||
LY_ARRAY_FOR(type_un->types, u) {
|
||||
if (type_un->types[u]->basetype != LY_TYPE_LEAFREF) {
|
||||
continue;
|
||||
}
|
||||
|
||||
target = lysc_type_lref_target(node, type_un->types[u]);
|
||||
if (target) {
|
||||
LY_CHECK_GOTO(rc = ly_set_add(*set, target, 1, NULL), cleanup);
|
||||
}
|
||||
}
|
||||
} else if (type->basetype == LY_TYPE_LEAFREF) {
|
||||
/* leafref */
|
||||
target = lysc_type_lref_target(node, type);
|
||||
if (target) {
|
||||
LY_CHECK_GOTO(rc = ly_set_add(*set, target, 1, NULL), cleanup);
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (rc) {
|
||||
ly_set_free(*set, NULL);
|
||||
*set = NULL;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct lysc_node_lref_backlings_arg {
|
||||
const struct lysc_node *node;
|
||||
ly_bool match_ancestors;
|
||||
struct ly_set *set;
|
||||
};
|
||||
|
||||
static LY_ERR
|
||||
lysc_node_lref_backlinks_clb(struct lysc_node *node, void *data, ly_bool *dfs_continue)
|
||||
{
|
||||
LY_ERR rc = LY_SUCCESS;
|
||||
struct lysc_node_lref_backlings_arg *arg = data;
|
||||
struct ly_set *set = NULL;
|
||||
const struct lysc_node *par;
|
||||
uint32_t i;
|
||||
|
||||
(void)dfs_continue;
|
||||
|
||||
if (!(node->nodetype & LYD_NODE_TERM)) {
|
||||
/* skip */
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* get all the leafref targets */
|
||||
LY_CHECK_GOTO(rc = lysc_node_lref_targets(node, &set), cleanup);
|
||||
|
||||
/* ignore node if has no leafref targets */
|
||||
if (!set->count) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* if just collecting leafrefs, we are done */
|
||||
if (!arg->node) {
|
||||
rc = ly_set_add(arg->set, node, 1, NULL);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* check that the node (or the ancestor of) is the target of this leafref */
|
||||
for (i = 0; i < set->count; ++i) {
|
||||
for (par = set->snodes[i]; par; par = par->parent) {
|
||||
if (par == arg->node) {
|
||||
/* match */
|
||||
break;
|
||||
}
|
||||
|
||||
if (!arg->match_ancestors) {
|
||||
/* not a match */
|
||||
par = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (par) {
|
||||
/* add into the set, matches */
|
||||
LY_CHECK_GOTO(rc = ly_set_add(arg->set, node, 1, NULL), cleanup);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
ly_set_free(set, NULL);
|
||||
return rc;
|
||||
}
|
||||
|
||||
LIBYANG_API_DEF LY_ERR
|
||||
lysc_node_lref_backlinks(const struct ly_ctx *ctx, const struct lysc_node *node, ly_bool match_ancestors,
|
||||
struct ly_set **set)
|
||||
{
|
||||
LY_ERR rc = LY_SUCCESS;
|
||||
struct lysc_node_lref_backlings_arg arg = {0};
|
||||
uint32_t idx = 0;
|
||||
const struct lys_module *mod;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, ctx || node, set, LY_EINVAL);
|
||||
|
||||
if (!ctx) {
|
||||
ctx = node->module->ctx;
|
||||
}
|
||||
|
||||
/* allocate return set */
|
||||
LY_CHECK_RET(ly_set_new(set));
|
||||
|
||||
/* prepare the arg */
|
||||
arg.node = node;
|
||||
arg.match_ancestors = match_ancestors;
|
||||
arg.set = *set;
|
||||
|
||||
/* iterate across all loaded modules */
|
||||
while ((mod = ly_ctx_get_module_iter(ctx, &idx))) {
|
||||
if (!mod->compiled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LY_CHECK_GOTO(rc = lysc_module_dfs_full(mod, lysc_node_lref_backlinks_clb, &arg), cleanup);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (rc) {
|
||||
ly_set_free(*set, NULL);
|
||||
*set = NULL;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
enum ly_stmt
|
||||
lysp_match_kw(struct ly_in *in, uint64_t *indent)
|
||||
{
|
||||
|
@ -2619,41 +2762,3 @@ lys_stmt_flags(enum ly_stmt stmt)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ly_check_module_filename(const struct ly_ctx *ctx, const char *name, const char *revision, const char *filename)
|
||||
{
|
||||
const char *basename, *rev, *dot;
|
||||
size_t len;
|
||||
|
||||
/* check that name and revision match filename */
|
||||
basename = strrchr(filename, '/');
|
||||
#ifdef _WIN32
|
||||
const char *backslash = strrchr(filename, '\\');
|
||||
|
||||
if (!basename || (basename && backslash && (backslash > basename))) {
|
||||
basename = backslash;
|
||||
}
|
||||
#endif
|
||||
if (!basename) {
|
||||
basename = filename;
|
||||
} else {
|
||||
basename++; /* leading slash */
|
||||
}
|
||||
rev = strchr(basename, '@');
|
||||
dot = strrchr(basename, '.');
|
||||
|
||||
/* name */
|
||||
len = strlen(name);
|
||||
if (strncmp(basename, name, len) ||
|
||||
((rev && (rev != &basename[len])) || (!rev && (dot != &basename[len])))) {
|
||||
LOGWRN(ctx, "File name \"%s\" does not match module name \"%s\".", basename, name);
|
||||
}
|
||||
if (rev) {
|
||||
len = dot - ++rev;
|
||||
if (!revision || (len != LY_REV_SIZE - 1) || strncmp(revision, rev, len)) {
|
||||
LOGWRN(ctx, "File name \"%s\" does not match module revision \"%s\".", basename,
|
||||
revision ? revision : "none");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -825,14 +825,7 @@ lysc_ident_free(struct lysf_ctx *ctx, struct lysc_ident *ident)
|
|||
FREE_ARRAY(ctx, ident->exts, lysc_ext_instance_free);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the compiled range structure.
|
||||
*
|
||||
* @param[in] ctx Free context.
|
||||
* @param[in,out] range Compiled range structure to be freed.
|
||||
* Since the structure is typically part of the sized array, the structure itself is not freed.
|
||||
*/
|
||||
static void
|
||||
void
|
||||
lysc_range_free(struct lysf_ctx *ctx, struct lysc_range *range)
|
||||
{
|
||||
LY_ARRAY_FREE(range->parts);
|
||||
|
|
|
@ -134,6 +134,15 @@ void lysc_ext_instance_free(struct lysf_ctx *ctx, struct lysc_ext_instance *ext)
|
|||
*/
|
||||
void lysc_iffeature_free(struct lysf_ctx *ctx, struct lysc_iffeature *iff);
|
||||
|
||||
/**
|
||||
* @brief Free the compiled range structure.
|
||||
*
|
||||
* @param[in] ctx Free context.
|
||||
* @param[in,out] range Compiled range structure to be freed.
|
||||
* Since the structure is typically part of the sized array, the structure itself is not freed.
|
||||
*/
|
||||
void lysc_range_free(struct lysf_ctx *ctx, struct lysc_range *range);
|
||||
|
||||
/**
|
||||
* @brief Free a compiled pattern.
|
||||
*
|
||||
|
|
|
@ -130,11 +130,12 @@ enum yang_arg {
|
|||
|
||||
struct lysp_ctx {
|
||||
LYS_INFORMAT format; /**< parser format */
|
||||
struct ly_set tpdfs_nodes; /**< Set of nodes that contain typedef(s). Invalid in case of
|
||||
submodule, use ::lysp_ctx.main_ctx instead. */
|
||||
struct ly_set grps_nodes; /**< Set of nodes that contain grouping(s). Invalid in case of
|
||||
submodule, use ::lysp_ctx.main_ctx instead. */
|
||||
struct ly_set ext_inst; /**< parsed extension instances to finish parsing */
|
||||
struct ly_set tpdfs_nodes; /**< Set of nodes that contain typedef(s). Used only temporarily in case of
|
||||
submodule, ::lysp_ctx.main_ctx used instead. */
|
||||
struct ly_set grps_nodes; /**< Set of nodes that contain grouping(s). Used only temporarily in case of
|
||||
submodule, ::lysp_ctx.main_ctx used instead. */
|
||||
struct ly_set ext_inst; /**< Set of parsed extension instances to finish parsing. Used only temporarily
|
||||
in case of submodule, ::lysp_ctx.main_ctx used instead. */
|
||||
|
||||
struct ly_set *parsed_mods; /**< (sub)modules being parsed, the last one is the current */
|
||||
struct lysp_ctx *main_ctx; /**< This pointer must not be NULL. If this context deals with the submodule,
|
||||
|
@ -528,8 +529,12 @@ void lys_unres_glob_revert(struct ly_ctx *ctx, struct lys_glob_unres *unres);
|
|||
*/
|
||||
void lys_unres_glob_erase(struct lys_glob_unres *unres);
|
||||
|
||||
typedef LY_ERR (*lys_custom_check)(const struct ly_ctx *ctx, struct lysp_module *mod, struct lysp_submodule *submod,
|
||||
void *check_data);
|
||||
struct lysp_load_module_data {
|
||||
const char *name; /**< expected module name */
|
||||
const char *revision; /**< expected module revision */
|
||||
const char *path; /**< module file name to check */
|
||||
const char *submoduleof; /**< expected submodule main module */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Parse a module and add it into the context.
|
||||
|
@ -537,15 +542,14 @@ typedef LY_ERR (*lys_custom_check)(const struct ly_ctx *ctx, struct lysp_module
|
|||
* @param[in] ctx libyang context where to process the data model.
|
||||
* @param[in] in Input structure.
|
||||
* @param[in] format Format of the input data (YANG or YIN).
|
||||
* @param[in] custom_check Callback to check the parsed schema before it is accepted.
|
||||
* @param[in] check_data Caller's data to pass to the custom_check callback.
|
||||
* @param[in] mod_data Optional expected module data to check.
|
||||
* @param[in,out] new_mods Set of all the new mods added to the context. Includes this module and all of its imports.
|
||||
* @param[out] module Created module.
|
||||
* @return LY_SUCCESS on success.
|
||||
* @return LY_ERR on error, @p new_mods may be modified.
|
||||
*/
|
||||
LY_ERR lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, lys_custom_check custom_check,
|
||||
void *check_data, struct ly_set *new_mods, struct lys_module **module);
|
||||
LY_ERR lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format,
|
||||
const struct lysp_load_module_data *mod_data, struct ly_set *new_mods, struct lys_module **module);
|
||||
|
||||
/**
|
||||
* @brief Parse submodule.
|
||||
|
@ -556,14 +560,13 @@ LY_ERR lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, l
|
|||
* @param[in] in Input structure.
|
||||
* @param[in] format Format of the input data (YANG or YIN).
|
||||
* @param[in] main_ctx Parser context of the main module.
|
||||
* @param[in] custom_check Callback to check the parsed schema before it is accepted.
|
||||
* @param[in] check_data Caller's data to pass to the custom_check callback.
|
||||
* @param[in] mod_data Optional expected module data to check.
|
||||
* @param[in] new_mods Set of all the new mods added to the context. Includes this module and all of its imports.
|
||||
* @param[out] submodule Parsed submodule.
|
||||
* @return LY_ERR value.
|
||||
*/
|
||||
LY_ERR lys_parse_submodule(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, struct lysp_ctx *main_ctx,
|
||||
lys_custom_check custom_check, void *check_data, struct ly_set *new_mods, struct lysp_submodule **submodule);
|
||||
const struct lysp_load_module_data *mod_data, struct ly_set *new_mods, struct lysp_submodule **submodule);
|
||||
|
||||
/**
|
||||
* @brief Fill filepath value if available in input handler @p in
|
||||
|
@ -732,14 +735,4 @@ uint8_t lys_stmt_flags(enum ly_stmt stmt);
|
|||
*/
|
||||
LY_ERR lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, void ***storage_pp);
|
||||
|
||||
/**
|
||||
* @brief Warning if the filename does not match the expected module name and version
|
||||
*
|
||||
* @param[in] ctx Context for logging
|
||||
* @param[in] name Expected module name
|
||||
* @param[in] revision Expected module revision, or NULL if not to be checked
|
||||
* @param[in] filename File path to be checked
|
||||
*/
|
||||
void ly_check_module_filename(const struct ly_ctx *ctx, const char *name, const char *revision, const char *filename);
|
||||
|
||||
#endif /* LY_TREE_SCHEMA_INTERNAL_H_ */
|
||||
|
|
|
@ -216,7 +216,7 @@ lyd_val_diff_add(const struct lyd_node *node, enum lyd_diff_op op, struct lyd_no
|
|||
}
|
||||
|
||||
/* create new diff tree */
|
||||
LY_CHECK_GOTO(ret = lyd_diff_add(node, op, NULL, NULL, key, value, position, NULL, NULL, &new_diff), cleanup);
|
||||
LY_CHECK_GOTO(ret = lyd_diff_add(node, op, NULL, NULL, key, value, position, NULL, NULL, &new_diff, NULL), cleanup);
|
||||
|
||||
/* merge into existing diff */
|
||||
ret = lyd_diff_merge_all(diff, new_diff, 0);
|
||||
|
@ -336,7 +336,8 @@ lyd_validate_autodel_node_del(struct lyd_node **first, struct lyd_node *del, con
|
|||
/* remove nested from node_when set */
|
||||
LYD_TREE_DFS_BEGIN(del, iter) {
|
||||
if ((del != iter) && ly_set_contains(node_when, iter, &idx)) {
|
||||
ly_set_rm_index(node_when, idx, NULL);
|
||||
assert(0 && "Please contact libyang support with the use-case that triggered this assert.");
|
||||
// ly_set_rm_index(node_when, idx, NULL);
|
||||
}
|
||||
LYD_TREE_DFS_END(del, iter);
|
||||
}
|
||||
|
@ -345,7 +346,9 @@ lyd_validate_autodel_node_del(struct lyd_node **first, struct lyd_node *del, con
|
|||
if (node_types && node_types->count) {
|
||||
/* remove from node_types set */
|
||||
LYD_TREE_DFS_BEGIN(del, iter) {
|
||||
if (ly_set_contains(node_types, iter, &idx)) {
|
||||
if ((iter->schema->nodetype & LYD_NODE_TERM) &&
|
||||
((struct lysc_node_leaf *)iter->schema)->type->plugin->validate &&
|
||||
ly_set_contains(node_types, iter, &idx)) {
|
||||
ly_set_rm_index(node_types, idx, NULL);
|
||||
}
|
||||
LYD_TREE_DFS_END(del, iter);
|
||||
|
@ -490,8 +493,14 @@ lyd_validate_unres(struct lyd_node **tree, const struct lys_module *mod, enum ly
|
|||
/* there must have been some when conditions resolved */
|
||||
} while (prev_count > node_when->count);
|
||||
|
||||
/* there could have been no cyclic when dependencies, checked during compilation */
|
||||
assert(!node_when->count || ((rc == LY_EVALID) && (val_opts & LYD_VALIDATE_MULTI_ERROR)));
|
||||
if (node_when->count) {
|
||||
/* there could have been no cyclic when dependencies, checked during compilation */
|
||||
assert((rc == LY_EVALID) && (val_opts & LYD_VALIDATE_MULTI_ERROR));
|
||||
|
||||
/* when condition was validated and it is not satisfied, error printed, if kept in the set the following
|
||||
* unres (for the next module) can fail this assert */
|
||||
ly_set_erase(node_when, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (node_types && node_types->count) {
|
||||
|
@ -1140,13 +1149,17 @@ static LY_ERR
|
|||
lyd_validate_minmax(const struct lyd_node *first, const struct lyd_node *parent, const struct lysc_node *snode,
|
||||
uint32_t min, uint32_t max, uint32_t val_opts)
|
||||
{
|
||||
LY_ERR rc = LY_SUCCESS;
|
||||
uint32_t count = 0;
|
||||
struct lyd_node *iter;
|
||||
struct lyd_node *iter, *last_iter = NULL;
|
||||
const struct lysc_when *disabled;
|
||||
char *log_path;
|
||||
int r;
|
||||
|
||||
assert(min || max);
|
||||
|
||||
LYD_LIST_FOR_INST(first, snode, iter) {
|
||||
last_iter = iter;
|
||||
++count;
|
||||
|
||||
if (min && (count == min)) {
|
||||
|
@ -1182,32 +1195,52 @@ lyd_validate_minmax(const struct lyd_node *first, const struct lyd_node *parent,
|
|||
max = 0;
|
||||
}
|
||||
|
||||
if (min) {
|
||||
if (val_opts & LYD_VALIDATE_OPERATIONAL) {
|
||||
/* only a warning */
|
||||
LOG_LOCSET(snode, NULL);
|
||||
LOGWRN(snode->module->ctx, "Too few \"%s\" instances.", snode->name);
|
||||
LOG_LOCBACK(1, 0);
|
||||
if (min || max) {
|
||||
/* set log path */
|
||||
if (last_iter) {
|
||||
/* standard data path */
|
||||
LOG_LOCSET(NULL, last_iter);
|
||||
} else {
|
||||
LOG_LOCSET(snode, NULL);
|
||||
LOGVAL_APPTAG(snode->module->ctx, "too-few-elements", LY_VCODE_NOMIN, snode->name);
|
||||
LOG_LOCBACK(1, 0);
|
||||
return LY_EVALID;
|
||||
/* data path with last schema node name or only the schema node if !parent */
|
||||
if (lyd_node_module(parent) != snode->module) {
|
||||
r = asprintf(&log_path, "/%s:%s", snode->module->name, snode->name);
|
||||
} else {
|
||||
r = asprintf(&log_path, "/%s", snode->name);
|
||||
}
|
||||
if (r == -1) {
|
||||
LOGMEM_RET(snode->module->ctx);
|
||||
}
|
||||
ly_log_location(NULL, parent, log_path, NULL);
|
||||
free(log_path);
|
||||
}
|
||||
} else if (max) {
|
||||
if (val_opts & LYD_VALIDATE_OPERATIONAL) {
|
||||
/* only a warning */
|
||||
LOG_LOCSET(NULL, iter);
|
||||
LOGWRN(snode->module->ctx, "Too many \"%s\" instances.", snode->name);
|
||||
|
||||
if (min) {
|
||||
if (val_opts & LYD_VALIDATE_OPERATIONAL) {
|
||||
/* only a warning */
|
||||
LOGWRN(snode->module->ctx, "Too few \"%s\" instances.", snode->name);
|
||||
} else {
|
||||
LOGVAL_APPTAG(snode->module->ctx, "too-few-elements", LY_VCODE_NOMIN, snode->name);
|
||||
rc = LY_EVALID;
|
||||
}
|
||||
} else if (max) {
|
||||
if (val_opts & LYD_VALIDATE_OPERATIONAL) {
|
||||
/* only a warning */
|
||||
LOGWRN(snode->module->ctx, "Too many \"%s\" instances.", snode->name);
|
||||
} else {
|
||||
LOGVAL_APPTAG(snode->module->ctx, "too-many-elements", LY_VCODE_NOMAX, snode->name);
|
||||
rc = LY_EVALID;
|
||||
}
|
||||
}
|
||||
|
||||
/* revert log path */
|
||||
if (last_iter) {
|
||||
LOG_LOCBACK(0, 1);
|
||||
} else {
|
||||
LOG_LOCSET(NULL, iter);
|
||||
LOGVAL_APPTAG(snode->module->ctx, "too-many-elements", LY_VCODE_NOMAX, snode->name);
|
||||
LOG_LOCBACK(0, 1);
|
||||
return LY_EVALID;
|
||||
ly_log_location_revert(0, parent ? 1 : 0, 1, 0);
|
||||
}
|
||||
}
|
||||
return LY_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1588,7 +1621,8 @@ lyd_validate_obsolete(const struct lyd_node *node)
|
|||
|
||||
snode = node->schema;
|
||||
do {
|
||||
if (snode->flags & LYS_STATUS_OBSLT) {
|
||||
if (snode->flags & LYS_STATUS_OBSLT &&
|
||||
(!(snode->nodetype & LYD_NODE_INNER) || lyd_child(node))) {
|
||||
LOG_LOCSET(NULL, node);
|
||||
LOGWRN(snode->module->ctx, "Obsolete schema node \"%s\" instantiated in data.", snode->name);
|
||||
LOG_LOCBACK(0, 1);
|
||||
|
@ -2126,7 +2160,7 @@ LIBYANG_API_DEF LY_ERR
|
|||
lyd_validate_all(struct lyd_node **tree, const struct ly_ctx *ctx, uint32_t val_opts, struct lyd_node **diff)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, tree, *tree || ctx, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(*tree ? LYD_CTX(*tree) : NULL, ctx, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, *tree ? LYD_CTX(*tree) : NULL, ctx, LY_EINVAL);
|
||||
if (!ctx) {
|
||||
ctx = LYD_CTX(*tree);
|
||||
}
|
||||
|
@ -2141,7 +2175,7 @@ LIBYANG_API_DEF LY_ERR
|
|||
lyd_validate_module(struct lyd_node **tree, const struct lys_module *module, uint32_t val_opts, struct lyd_node **diff)
|
||||
{
|
||||
LY_CHECK_ARG_RET(NULL, tree, module, !(val_opts & LYD_VALIDATE_PRESENT), LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(*tree ? LYD_CTX(*tree) : NULL, module->ctx, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, *tree ? LYD_CTX(*tree) : NULL, module->ctx, LY_EINVAL);
|
||||
if (diff) {
|
||||
*diff = NULL;
|
||||
}
|
||||
|
@ -2159,7 +2193,7 @@ lyd_validate_module_final(struct lyd_node *tree, const struct lys_module *module
|
|||
struct ly_ht *getnext_ht = NULL;
|
||||
|
||||
LY_CHECK_ARG_RET(NULL, module, !(val_opts & (LYD_VALIDATE_PRESENT | LYD_VALIDATE_NOT_FINAL)), LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(tree ? LYD_CTX(tree) : NULL, module->ctx, LY_EINVAL);
|
||||
LY_CHECK_CTX_EQUAL_RET(__func__, tree ? LYD_CTX(tree) : NULL, module->ctx, LY_EINVAL);
|
||||
|
||||
/* module is unchanged but we need to get the first module data node */
|
||||
mod = lyd_mod_next_module(tree, module, module->ctx, &i, &first);
|
||||
|
|
47
src/xpath.c
47
src/xpath.c
|
@ -3690,6 +3690,7 @@ xpath_bit_is_set(struct lyxp_set **args, uint32_t UNUSED(arg_count), struct lyxp
|
|||
struct lyd_node_term *leaf;
|
||||
struct lysc_node_leaf *sleaf;
|
||||
struct lyd_value_bits *bits;
|
||||
struct lyd_value *val;
|
||||
LY_ERR rc = LY_SUCCESS;
|
||||
LY_ARRAY_COUNT_TYPE u;
|
||||
|
||||
|
@ -3725,10 +3726,14 @@ xpath_bit_is_set(struct lyxp_set **args, uint32_t UNUSED(arg_count), struct lyxp
|
|||
LY_CHECK_RET(rc);
|
||||
|
||||
set_fill_boolean(set, 0);
|
||||
if (args[0]->used) {
|
||||
if (args[0]->used && (args[0]->val.nodes[0].node->schema->nodetype & LYD_NODE_TERM)) {
|
||||
leaf = (struct lyd_node_term *)args[0]->val.nodes[0].node;
|
||||
if ((leaf->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && (leaf->value.realtype->basetype == LY_TYPE_BITS)) {
|
||||
LYD_VALUE_GET(&leaf->value, bits);
|
||||
val = &leaf->value;
|
||||
if (val->realtype->basetype == LY_TYPE_UNION) {
|
||||
val = &val->subvalue->value;
|
||||
}
|
||||
if (val->realtype->basetype == LY_TYPE_BITS) {
|
||||
LYD_VALUE_GET(val, bits);
|
||||
LY_ARRAY_FOR(bits->items, u) {
|
||||
if (!strcmp(bits->items[u]->name, args[1]->val.str)) {
|
||||
set_fill_boolean(set, 1);
|
||||
|
@ -4200,17 +4205,21 @@ xpath_derived_(struct lyxp_set **args, struct lyxp_set *set, uint32_t options, l
|
|||
leaf = (struct lyd_node_term *)args[0]->val.nodes[i].node;
|
||||
sleaf = (struct lysc_node_leaf *)leaf->schema;
|
||||
val = &leaf->value;
|
||||
if (!sleaf || !(sleaf->nodetype & LYD_NODE_TERM) || (leaf->value.realtype->basetype != LY_TYPE_IDENT)) {
|
||||
if (!sleaf || !(sleaf->nodetype & LYD_NODE_TERM)) {
|
||||
/* uninteresting */
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
meta = args[0]->val.meta[i].meta;
|
||||
val = &meta->value;
|
||||
if (val->realtype->basetype != LY_TYPE_IDENT) {
|
||||
/* uninteresting */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (val->realtype->basetype == LY_TYPE_UNION) {
|
||||
val = &val->subvalue->value;
|
||||
}
|
||||
if (val->realtype->basetype != LY_TYPE_IDENT) {
|
||||
/* uninteresting */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check the identity itself */
|
||||
|
@ -4972,6 +4981,7 @@ xpath_re_match(struct lyxp_set **args, uint32_t UNUSED(arg_count), struct lyxp_s
|
|||
LOG_LOCBACK(0, 1);
|
||||
}
|
||||
if (rc != LY_SUCCESS) {
|
||||
free(*pattern);
|
||||
LY_ARRAY_FREE(patterns);
|
||||
return rc;
|
||||
}
|
||||
|
@ -6801,7 +6811,8 @@ moveto_scnode(struct lyxp_set *set, const struct lys_module *moveto_mod, const c
|
|||
}
|
||||
}
|
||||
|
||||
if (moveto_mod && ncname && ((axis == LYXP_AXIS_DESCENDANT) || (axis == LYXP_AXIS_CHILD)) &&
|
||||
/* only consider extension nodes after no local ones were found */
|
||||
if ((orig_used == set->used) && moveto_mod && ncname && ((axis == LYXP_AXIS_DESCENDANT) || (axis == LYXP_AXIS_CHILD)) &&
|
||||
(set->val.scnodes[i].type == LYXP_NODE_ELEM) && !ly_nested_ext_schema(NULL, set->val.scnodes[i].scnode,
|
||||
moveto_mod->name, strlen(moveto_mod->name), LY_VALUE_JSON, NULL, ncname, strlen(ncname), &iter, NULL)) {
|
||||
/* there is a matching node from an extension, use it */
|
||||
|
@ -8236,14 +8247,16 @@ moveto:
|
|||
}
|
||||
LY_CHECK_GOTO(rc, cleanup);
|
||||
|
||||
i = set->used;
|
||||
do {
|
||||
--i;
|
||||
if (set->val.scnodes[i].in_ctx > LYXP_SET_SCNODE_ATOM_NODE) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
} while (i);
|
||||
if (set->used) {
|
||||
i = set->used;
|
||||
do {
|
||||
--i;
|
||||
if (set->val.scnodes[i].in_ctx > LYXP_SET_SCNODE_ATOM_NODE) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
} while (i);
|
||||
}
|
||||
if (!found) {
|
||||
/* generate message */
|
||||
eval_name_test_scnode_no_match_msg(set, scparent, ncname, ncname_len, exp->expr, options);
|
||||
|
|
|
@ -30,6 +30,9 @@ function(ly_add_utest)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if (XXHASH_FOUND)
|
||||
target_link_libraries(${TEST_NAME} ${XXHASH_LIBRARY})
|
||||
endif()
|
||||
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME})
|
||||
set_property(TEST ${TEST_NAME} APPEND PROPERTY ENVIRONMENT "MALLOC_CHECK_=3")
|
||||
|
||||
|
|
|
@ -6,7 +6,11 @@ set(format_sources
|
|||
add_executable(ly_perf ${CMAKE_CURRENT_SOURCE_DIR}/perf.c $<TARGET_OBJECTS:yangobj>)
|
||||
set_target_properties(ly_perf PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests")
|
||||
target_link_libraries(ly_perf ${CMAKE_THREAD_LIBS_INIT} ${PCRE2_LIBRARIES} ${CMAKE_DL_LIBS})
|
||||
if (NOT WIN32)
|
||||
if(XXHASH_FOUND)
|
||||
target_link_libraries(ly_perf ${XXHASH_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
target_link_libraries(ly_perf m)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
add_test(NAME headers
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/compat/check_includes.sh ${CMAKE_SOURCE_DIR}/src/ ${CMAKE_SOURCE_DIR}/tools/lint/ ${CMAKE_SOURCE_DIR}/tools/re/)
|
||||
|
||||
if (${SOURCE_FORMAT_ENABLED})
|
||||
if(${SOURCE_FORMAT_ENABLED})
|
||||
add_test(NAME format WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMAND cmake --build ${CMAKE_BINARY_DIR} --target format-check)
|
||||
endif()
|
||||
|
||||
|
@ -9,4 +9,8 @@ endif()
|
|||
add_executable(cpp_compat cpp_compat.c $<TARGET_OBJECTS:yangobj>)
|
||||
target_include_directories(cpp_compat BEFORE PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(cpp_compat ${CMAKE_THREAD_LIBS_INIT} ${PCRE2_LIBRARIES} ${CMAKE_DL_LIBS} m)
|
||||
if(XXHASH_FOUND)
|
||||
target_link_libraries(cpp_compat ${XXHASH_LIBRARY})
|
||||
endif()
|
||||
|
||||
target_compile_options(cpp_compat PUBLIC "-Werror=c++-compat")
|
||||
|
|
|
@ -276,10 +276,32 @@ test_options(void **state)
|
|||
}
|
||||
|
||||
static LY_ERR
|
||||
test_imp_clb(const char *UNUSED(mod_name), const char *UNUSED(mod_rev), const char *UNUSED(submod_name),
|
||||
const char *UNUSED(sub_rev), void *user_data, LYS_INFORMAT *format,
|
||||
const char **module_data, void (**free_module_data)(void *model_data, void *user_data))
|
||||
test_imp_clb(const char *mod_name, const char *UNUSED(mod_rev), const char *submod_name, const char *UNUSED(sub_rev),
|
||||
void *user_data, LYS_INFORMAT *format, const char **module_data, void (**free_module_data)(void *model_data,
|
||||
void *user_data))
|
||||
{
|
||||
const char *name;
|
||||
|
||||
if (submod_name) {
|
||||
if (strncmp(user_data, "submodule", 9)) {
|
||||
return LY_ENOTFOUND;
|
||||
}
|
||||
|
||||
name = ((char *)user_data) + 10;
|
||||
if (strncmp(name, submod_name, strlen(submod_name)) || (name[strlen(submod_name)] != ' ')) {
|
||||
return LY_ENOTFOUND;
|
||||
}
|
||||
} else {
|
||||
if (strncmp(user_data, "module", 6)) {
|
||||
return LY_ENOTFOUND;
|
||||
}
|
||||
|
||||
name = ((char *)user_data) + 7;
|
||||
if (strncmp(name, mod_name, strlen(mod_name)) || (name[strlen(mod_name)] != ' ')) {
|
||||
return LY_ENOTFOUND;
|
||||
}
|
||||
}
|
||||
|
||||
*module_data = user_data;
|
||||
*format = LYS_IN_YANG;
|
||||
*free_module_data = NULL;
|
||||
|
@ -305,7 +327,7 @@ test_models(void **state)
|
|||
assert_int_equal(UTEST_LYCTX->change_count, ly_ctx_get_change_count(UTEST_LYCTX));
|
||||
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory("module x {namespace urn:x;prefix x;}", &in));
|
||||
assert_int_equal(LY_EINVAL, lys_parse_in(UTEST_LYCTX, in, 4, NULL, NULL, &unres.creating, &mod1));
|
||||
assert_int_equal(LY_EINVAL, lys_parse_in(UTEST_LYCTX, in, 4, NULL, &unres.creating, &mod1));
|
||||
lys_unres_glob_erase(&unres);
|
||||
ly_in_free(in, 0);
|
||||
CHECK_LOG_CTX("Invalid schema input format.", NULL, 0);
|
||||
|
@ -324,17 +346,17 @@ test_models(void **state)
|
|||
/* name collision of module and submodule */
|
||||
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule y {belongs-to a {prefix a;} revision 2018-10-30;}");
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory("module y {namespace urn:y;prefix y;include y;}", &in));
|
||||
assert_int_equal(LY_EVALID, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod1));
|
||||
assert_int_equal(LY_EVALID, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, &unres.creating, &mod1));
|
||||
lys_unres_glob_erase(&unres);
|
||||
ly_in_free(in, 0);
|
||||
CHECK_LOG_CTX("Parsing module \"y\" failed.", NULL, 0);
|
||||
CHECK_LOG_CTX("Name collision between module and submodule of name \"y\".", NULL, 1);
|
||||
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory("module a {namespace urn:a;prefix a;include y;revision 2018-10-30; }", &in));
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod1));
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, &unres.creating, &mod1));
|
||||
ly_in_free(in, 0);
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory("module y {namespace urn:y;prefix y;}", &in));
|
||||
assert_int_equal(LY_EVALID, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod1));
|
||||
assert_int_equal(LY_EVALID, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, &unres.creating, &mod1));
|
||||
lys_unres_glob_erase(&unres);
|
||||
ly_in_free(in, 0);
|
||||
CHECK_LOG_CTX("Parsing module \"y\" failed.", NULL, 0);
|
||||
|
@ -342,19 +364,18 @@ test_models(void **state)
|
|||
|
||||
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule y {belongs-to b {prefix b;}}");
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory("module b {namespace urn:b;prefix b;include y;}", &in));
|
||||
assert_int_equal(LY_EVALID, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod1));
|
||||
assert_int_equal(LY_EVALID, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, &unres.creating, &mod1));
|
||||
lys_unres_glob_revert(UTEST_LYCTX, &unres);
|
||||
lys_unres_glob_erase(&unres);
|
||||
ly_in_free(in, 0);
|
||||
CHECK_LOG_CTX("Parsing module \"b\" failed.", NULL, 0);
|
||||
CHECK_LOG_CTX("Including \"y\" submodule into \"b\" failed.", NULL, 0);
|
||||
CHECK_LOG_CTX("Parsing submodule failed.", NULL, 0);
|
||||
CHECK_LOG_CTX("Parsing submodule \"y\" failed.", NULL, 0);
|
||||
CHECK_LOG_CTX("Name collision between submodules of name \"y\".", NULL, 1);
|
||||
|
||||
/* selecting correct revision of the submodules */
|
||||
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule y {belongs-to a {prefix a;} revision 2018-10-31;}");
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory("module a {namespace urn:a;prefix a;include y; revision 2018-10-31;}", &in));
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod2));
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, &unres.creating, &mod2));
|
||||
lys_unres_glob_erase(&unres);
|
||||
ly_in_free(in, 0);
|
||||
assert_string_equal("2018-10-31", mod2->parsed->includes[0].submodule->revs[0].date);
|
||||
|
@ -490,17 +511,17 @@ test_get_models(void **state)
|
|||
/* select module by revision */
|
||||
assert_int_equal(LY_SUCCESS, lys_parse(UTEST_LYCTX, in1, LYS_IN_YANG, NULL, &mod));
|
||||
/* invalid attempts - implementing module of the same name and inserting the same module */
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in2, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod2));
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in2, LYS_IN_YANG, NULL, &unres.creating, &mod2));
|
||||
assert_int_equal(LY_EDENIED, lys_implement(mod2, NULL, &unres));
|
||||
CHECK_LOG_CTX("Module \"a@2018-10-24\" is already implemented in revision \"2018-10-23\".", NULL, 0);
|
||||
lys_unres_glob_erase(&unres);
|
||||
ly_in_reset(in1);
|
||||
/* it is already there, fine */
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in1, LYS_IN_YANG, NULL, NULL, &unres.creating, NULL));
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in1, LYS_IN_YANG, NULL, &unres.creating, NULL));
|
||||
/* insert the second module only as imported, not implemented */
|
||||
lys_unres_glob_erase(&unres);
|
||||
ly_in_reset(in2);
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in2, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod2));
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in2, LYS_IN_YANG, NULL, &unres.creating, &mod2));
|
||||
lys_unres_glob_erase(&unres);
|
||||
assert_non_null(mod2);
|
||||
assert_ptr_not_equal(mod, mod2);
|
||||
|
@ -509,7 +530,7 @@ test_get_models(void **state)
|
|||
mod2 = ly_ctx_get_module_latest_ns(UTEST_LYCTX, mod->ns);
|
||||
assert_ptr_equal(mod, mod2);
|
||||
/* work with module with no revision */
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in0, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod));
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in0, LYS_IN_YANG, NULL, &unres.creating, &mod));
|
||||
lys_unres_glob_erase(&unres);
|
||||
assert_ptr_equal(mod, ly_ctx_get_module(UTEST_LYCTX, "a", NULL));
|
||||
assert_ptr_not_equal(mod, ly_ctx_get_module_latest(UTEST_LYCTX, "a"));
|
||||
|
@ -517,7 +538,7 @@ test_get_models(void **state)
|
|||
str1 = "submodule b {belongs-to a {prefix a;}}";
|
||||
ly_in_free(in1, 0);
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str1, &in1));
|
||||
assert_int_equal(LY_EINVAL, lys_parse_in(UTEST_LYCTX, in1, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod));
|
||||
assert_int_equal(LY_EINVAL, lys_parse_in(UTEST_LYCTX, in1, LYS_IN_YANG, NULL, &unres.creating, &mod));
|
||||
CHECK_LOG_CTX("Input data contains submodule which cannot be parsed directly without its main module.", NULL, 0);
|
||||
lys_unres_glob_erase(&unres);
|
||||
|
||||
|
@ -540,7 +561,7 @@ test_ylmem(void **state)
|
|||
" <name>complete</name>\n"\
|
||||
" <module>\n"\
|
||||
" <name>yang</name>\n"\
|
||||
" <revision>2022-06-16</revision>\n"\
|
||||
" <revision>2025-01-29</revision>\n"\
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:1</namespace>\n"\
|
||||
" </module>\n"\
|
||||
" <module>\n"\
|
||||
|
@ -587,7 +608,7 @@ test_ylmem(void **state)
|
|||
" </module>\n"\
|
||||
" <module>\n"\
|
||||
" <name>yang</name>\n"\
|
||||
" <revision>2022-06-16</revision>\n"\
|
||||
" <revision>2025-01-29</revision>\n"\
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:1</namespace>\n"\
|
||||
" <conformance-type>implement</conformance-type>\n"\
|
||||
" </module>\n"\
|
||||
|
@ -740,7 +761,7 @@ test_ylmem(void **state)
|
|||
" <name>complete</name>\n"
|
||||
" <module>\n"
|
||||
" <name>yang</name>\n"
|
||||
" <revision>2022-06-16</revision>\n"
|
||||
" <revision>2025-01-29</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:1</namespace>\n"
|
||||
" </module>\n"
|
||||
DATA_YANG_BASE_IMPORTS
|
||||
|
@ -978,7 +999,7 @@ test_set_priv_parsed(void **state)
|
|||
ly_ctx_destroy(UTEST_LYCTX);
|
||||
const char *feats[] = {"f1", NULL};
|
||||
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_SET_PRIV_PARSED, &UTEST_LYCTX));
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIR_CWD | LY_CTX_SET_PRIV_PARSED, &UTEST_LYCTX));
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_DIR_MODULES_YANG));
|
||||
assert_non_null(ly_ctx_load_module(UTEST_LYCTX, "ietf-restconf", "2017-01-26", NULL));
|
||||
UTEST_ADD_MODULE(schema_a, LYS_IN_YANG, feats, NULL);
|
||||
|
@ -1054,7 +1075,7 @@ test_explicit_compile(void **state)
|
|||
ly_ctx_destroy(UTEST_LYCTX);
|
||||
const char *feats[] = {"f1", NULL};
|
||||
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_EXPLICIT_COMPILE, &UTEST_LYCTX));
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIR_CWD | LY_CTX_EXPLICIT_COMPILE, &UTEST_LYCTX));
|
||||
UTEST_ADD_MODULE(schema_a, LYS_IN_YANG, NULL, &mod);
|
||||
UTEST_ADD_MODULE(schema_b, LYS_IN_YANG, NULL, NULL);
|
||||
UTEST_ADD_MODULE(schema_c, LYS_IN_YANG, NULL, NULL);
|
||||
|
|
|
@ -23,11 +23,11 @@
|
|||
#define CHECK_LYD_STRING(INPUT, TEXT) \
|
||||
CHECK_LYD_STRING_PARAM(INPUT, TEXT, LYD_XML, LYD_PRINT_WITHSIBLINGS)
|
||||
|
||||
#define CHECK_PARSE_LYD_DIFF(INPUT_1, INPUT_2, OUT_DIFF) \
|
||||
assert_int_equal(LY_SUCCESS, lyd_diff_siblings(INPUT_1, INPUT_2, 0, &OUT_DIFF));\
|
||||
#define CHECK_PARSE_LYD_DIFF(INPUT_1, INPUT_2, OPTS, OUT_DIFF) \
|
||||
assert_int_equal(LY_SUCCESS, lyd_diff_siblings(INPUT_1, INPUT_2, OPTS, &OUT_DIFF));\
|
||||
assert_non_null(OUT_DIFF)
|
||||
|
||||
#define TEST_DIFF_3(XML1, XML2, XML3, DIFF1, DIFF2, MERGE) \
|
||||
#define TEST_DIFF_3(XML1, XML2, XML3, OPTS, DIFF1, DIFF2, MERGE) \
|
||||
{ \
|
||||
struct lyd_node *data1;\
|
||||
struct lyd_node *data2;\
|
||||
|
@ -38,13 +38,13 @@
|
|||
CHECK_PARSE_LYD(XML3, data3);\
|
||||
/* diff1 */ \
|
||||
struct lyd_node *diff1;\
|
||||
CHECK_PARSE_LYD_DIFF(data1, data2, diff1); \
|
||||
CHECK_PARSE_LYD_DIFF(data1, data2, OPTS, diff1); \
|
||||
CHECK_LYD_STRING(diff1, DIFF1); \
|
||||
assert_int_equal(lyd_diff_apply_all(&data1, diff1), LY_SUCCESS); \
|
||||
CHECK_LYD(data1, data2); \
|
||||
/* diff2 */ \
|
||||
struct lyd_node *diff2;\
|
||||
CHECK_PARSE_LYD_DIFF(data2, data3, diff2); \
|
||||
CHECK_PARSE_LYD_DIFF(data2, data3, OPTS, diff2); \
|
||||
CHECK_LYD_STRING(diff2, DIFF2); \
|
||||
assert_int_equal(lyd_diff_apply_all(&data2, diff2), LY_SUCCESS);\
|
||||
CHECK_LYD(data2, data3);\
|
||||
|
@ -59,248 +59,104 @@
|
|||
lyd_free_all(diff2);\
|
||||
}
|
||||
|
||||
const char *schema1 =
|
||||
"module defaults {\n"
|
||||
" yang-version 1.1;\n"
|
||||
" namespace \"urn:libyang:tests:defaults\";\n"
|
||||
" prefix df;\n"
|
||||
const char *schema =
|
||||
"module defaults {"
|
||||
"yang-version 1.1;"
|
||||
"namespace \"urn:libyang:tests:defaults\";"
|
||||
"prefix df;"
|
||||
""
|
||||
" feature unhide;\n"
|
||||
"import ietf-yang-metadata {prefix md;}"
|
||||
""
|
||||
" typedef defint32 {\n"
|
||||
" type int32;\n"
|
||||
" default \"42\";\n"
|
||||
" }\n"
|
||||
"feature unhide;"
|
||||
""
|
||||
" leaf hiddenleaf {\n"
|
||||
" if-feature \"unhide\";\n"
|
||||
" type int32;\n"
|
||||
" default \"42\";\n"
|
||||
" }\n"
|
||||
"md:annotation my-meta {type string;}"
|
||||
"md:annotation my-meta2 {type string;}"
|
||||
""
|
||||
" container df {\n"
|
||||
" leaf foo {\n"
|
||||
" type defint32;\n"
|
||||
" }\n"
|
||||
"typedef defint32 {type int32; default \"42\";}"
|
||||
""
|
||||
" leaf hiddenleaf {\n"
|
||||
" if-feature \"unhide\";\n"
|
||||
" type int32;\n"
|
||||
" default \"42\";\n"
|
||||
" }\n"
|
||||
""
|
||||
" container bar {\n"
|
||||
" presence \"\";\n"
|
||||
" leaf hi {\n"
|
||||
" type int32;\n"
|
||||
" default \"42\";\n"
|
||||
" }\n"
|
||||
""
|
||||
" leaf ho {\n"
|
||||
" type int32;\n"
|
||||
" mandatory true;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
""
|
||||
" leaf-list llist {\n"
|
||||
" type defint32;\n"
|
||||
" ordered-by user;\n"
|
||||
" }\n"
|
||||
""
|
||||
" list ul {\n"
|
||||
" key \"l1\";\n"
|
||||
" ordered-by user;\n"
|
||||
" leaf l1 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
""
|
||||
" leaf l2 {\n"
|
||||
" type int32;\n"
|
||||
" }\n"
|
||||
""
|
||||
" container cont {\n"
|
||||
" leaf l3 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
""
|
||||
" leaf-list dllist {\n"
|
||||
" type uint8;\n"
|
||||
" default \"1\";\n"
|
||||
" default \"2\";\n"
|
||||
" default \"3\";\n"
|
||||
" }\n"
|
||||
""
|
||||
" list list {\n"
|
||||
" key \"name\";\n"
|
||||
" leaf name {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
""
|
||||
" leaf value {\n"
|
||||
" type int32;\n"
|
||||
" default \"42\";\n"
|
||||
" }\n"
|
||||
" list list2 {\n"
|
||||
" key \"name2\";\n"
|
||||
" leaf name2 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf value2 {\n"
|
||||
" type int32;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n";
|
||||
const char *schema2 =
|
||||
" choice select {\n"
|
||||
" default \"a\";\n"
|
||||
" case a {\n"
|
||||
" choice a {\n"
|
||||
" leaf a1 {\n"
|
||||
" type int32;\n"
|
||||
" default \"42\";\n"
|
||||
" }\n"
|
||||
""
|
||||
" leaf a2 {\n"
|
||||
" type int32;\n"
|
||||
" default \"24\";\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
""
|
||||
" leaf b {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
""
|
||||
" container c {\n"
|
||||
" presence \"\";\n"
|
||||
" leaf x {\n"
|
||||
" type int32;\n"
|
||||
" default \"42\";\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
""
|
||||
" choice select2 {\n"
|
||||
" default \"s2b\";\n"
|
||||
" leaf s2a {\n"
|
||||
" type int32;\n"
|
||||
" default \"42\";\n"
|
||||
" }\n"
|
||||
""
|
||||
" case s2b {\n"
|
||||
" choice s2b {\n"
|
||||
" default \"b1\";\n"
|
||||
" case b1 {\n"
|
||||
" leaf b1_1 {\n"
|
||||
" type int32;\n"
|
||||
" default \"42\";\n"
|
||||
" }\n"
|
||||
""
|
||||
" leaf b1_2 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
""
|
||||
" leaf b1_status {\n"
|
||||
" type int32;\n"
|
||||
" default \"42\";\n"
|
||||
" config false;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
""
|
||||
" leaf b2 {\n"
|
||||
" type int32;\n"
|
||||
" default \"42\";\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" list kl {\n"
|
||||
" config \"false\";\n"
|
||||
" leaf l1 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
""
|
||||
" leaf l2 {\n"
|
||||
" type int32;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
""
|
||||
" leaf-list kll {\n"
|
||||
" config \"false\";\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
""
|
||||
" container hidden {\n"
|
||||
" leaf foo {\n"
|
||||
" type int32;\n"
|
||||
" default \"42\";\n"
|
||||
" }\n"
|
||||
""
|
||||
" leaf baz {\n"
|
||||
" type int32;\n"
|
||||
" default \"42\";\n"
|
||||
" }\n"
|
||||
""
|
||||
" leaf papa {\n"
|
||||
" type int32;\n"
|
||||
" default \"42\";\n"
|
||||
" config false;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
""
|
||||
" rpc rpc1 {\n"
|
||||
" input {\n"
|
||||
" leaf inleaf1 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
""
|
||||
" leaf inleaf2 {\n"
|
||||
" type string;\n"
|
||||
" default \"def1\";\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
""
|
||||
" output {\n"
|
||||
" leaf outleaf1 {\n"
|
||||
" type string;\n"
|
||||
" default \"def2\";\n"
|
||||
" }\n"
|
||||
""
|
||||
" leaf outleaf2 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
""
|
||||
" notification notif {\n"
|
||||
" leaf ntfleaf1 {\n"
|
||||
" type string;\n"
|
||||
" default \"def3\";\n"
|
||||
" }\n"
|
||||
""
|
||||
" leaf ntfleaf2 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
"leaf hiddenleaf {if-feature \"unhide\"; type int32; default \"42\";}"
|
||||
"container df {"
|
||||
" leaf foo {type defint32; }"
|
||||
" leaf hiddenleaf {if-feature \"unhide\"; type int32; default \"42\";}"
|
||||
" container bar { presence \"\";"
|
||||
" leaf hi {type int32; default \"42\";}"
|
||||
" leaf ho {type int32; mandatory true;}"
|
||||
" }"
|
||||
" leaf-list llist {type defint32; ordered-by user;}"
|
||||
" list ul {key \"l1\"; ordered-by user;"
|
||||
" leaf l1 {type string;}"
|
||||
" leaf l2 {type int32;}"
|
||||
" container cont {"
|
||||
" leaf l3 {type string;}"
|
||||
" }"
|
||||
" }"
|
||||
" leaf-list dllist {type uint8; default \"1\"; default \"2\"; default \"3\";}"
|
||||
" list list {key \"name\";"
|
||||
" leaf name {type string;}"
|
||||
" leaf value {type int32; default \"42\";}"
|
||||
" list list2 {key \"name2\";"
|
||||
" leaf name2 {type string;}"
|
||||
" leaf value2 {type int32;}"
|
||||
" }"
|
||||
" }"
|
||||
" choice select {default \"a\";"
|
||||
" case a {"
|
||||
" choice a {"
|
||||
" leaf a1 {type int32; default \"42\";}"
|
||||
" leaf a2 {type int32; default \"24\";}"
|
||||
" }"
|
||||
" }"
|
||||
" leaf b {type string;}"
|
||||
" container c {presence \"\";"
|
||||
" leaf x {type int32; default \"42\";}"
|
||||
" }"
|
||||
" }"
|
||||
" choice select2 {default \"s2b\";"
|
||||
" leaf s2a {type int32; default \"42\";}"
|
||||
" case s2b {"
|
||||
" choice s2b {default \"b1\";"
|
||||
" case b1 {"
|
||||
" leaf b1_1 {type int32; default \"42\";}"
|
||||
" leaf b1_2 {type string;}"
|
||||
" leaf b1_status {type int32; default \"42\"; config false;}"
|
||||
" }"
|
||||
" leaf b2 {type int32; default \"42\";}"
|
||||
" }"
|
||||
" }"
|
||||
" }"
|
||||
" list kl {config \"false\";"
|
||||
" leaf l1 {type string;}"
|
||||
" leaf l2 {type int32;}"
|
||||
" }"
|
||||
" leaf-list kll {config \"false\"; type string;}"
|
||||
"}"
|
||||
"container hidden {"
|
||||
" leaf foo {type int32; default \"42\";}"
|
||||
" leaf baz {type int32; default \"42\";}"
|
||||
" leaf papa {type int32; default \"42\"; config false;}"
|
||||
"}"
|
||||
"rpc rpc1 {"
|
||||
" input {"
|
||||
" leaf inleaf1 {type string;}"
|
||||
" leaf inleaf2 {type string; default \"def1\";}"
|
||||
" }"
|
||||
" output {"
|
||||
" leaf outleaf1 {type string; default \"def2\";}"
|
||||
" leaf outleaf2 {type string;}"
|
||||
" }"
|
||||
"}"
|
||||
"notification notif {"
|
||||
" leaf ntfleaf1 {type string; default \"def3\";}"
|
||||
" leaf ntfleaf2 {type string;}"
|
||||
"}"
|
||||
"}";
|
||||
|
||||
static int
|
||||
setup(void **state)
|
||||
{
|
||||
char *schema;
|
||||
|
||||
UTEST_SETUP;
|
||||
|
||||
/* create one schema, longer than 4095 chars */
|
||||
schema = malloc(strlen(schema1) + strlen(schema2) + 1);
|
||||
strcpy(schema, schema1);
|
||||
strcat(schema, schema2);
|
||||
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
free(schema);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -384,7 +240,7 @@ test_empty1(void **state)
|
|||
|
||||
struct lyd_node *diff;
|
||||
|
||||
CHECK_PARSE_LYD_DIFF(model_1, model_2, diff);
|
||||
CHECK_PARSE_LYD_DIFF(model_1, model_2, 0, diff);
|
||||
CHECK_LYD_STRING(diff,
|
||||
"<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">\n"
|
||||
" <foo>42</foo>\n"
|
||||
|
@ -420,7 +276,7 @@ test_empty2(void **state)
|
|||
|
||||
struct lyd_node *diff;
|
||||
|
||||
CHECK_PARSE_LYD_DIFF(model_1, NULL, diff);
|
||||
CHECK_PARSE_LYD_DIFF(model_1, NULL, 0, diff);
|
||||
CHECK_LYD_STRING(diff,
|
||||
"<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"delete\">\n"
|
||||
" <foo>42</foo>\n"
|
||||
|
@ -455,7 +311,7 @@ test_empty_nested(void **state)
|
|||
|
||||
struct lyd_node *diff1;
|
||||
|
||||
CHECK_PARSE_LYD_DIFF(NULL, lyd_child(model_1), diff1);
|
||||
CHECK_PARSE_LYD_DIFF(NULL, lyd_child(model_1), 0, diff1);
|
||||
CHECK_LYD_STRING(diff1,
|
||||
"<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">\n"
|
||||
" <foo yang:operation=\"create\">42</foo>\n"
|
||||
|
@ -463,7 +319,7 @@ test_empty_nested(void **state)
|
|||
|
||||
struct lyd_node *diff2;
|
||||
|
||||
CHECK_PARSE_LYD_DIFF(lyd_child(model_1), NULL, diff2);
|
||||
CHECK_PARSE_LYD_DIFF(lyd_child(model_1), NULL, 0, diff2);
|
||||
CHECK_LYD_STRING(diff2,
|
||||
"<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">\n"
|
||||
" <foo yang:operation=\"delete\">42</foo>\n"
|
||||
|
@ -565,7 +421,7 @@ test_leaf(void **state)
|
|||
" <baz yang:operation=\"delete\">42</baz>\n"
|
||||
"</hidden>\n";
|
||||
|
||||
TEST_DIFF_3(xml1, xml2, xml3, out_diff_1, out_diff_2, out_merge);
|
||||
TEST_DIFF_3(xml1, xml2, xml3, 0, out_diff_1, out_diff_2, out_merge);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -641,7 +497,7 @@ test_list(void **state)
|
|||
" </list>\n"
|
||||
"</df>\n";
|
||||
|
||||
TEST_DIFF_3(xml1, xml2, xml3, out_diff_1, out_diff_2, out_merge);
|
||||
TEST_DIFF_3(xml1, xml2, xml3, 0, out_diff_1, out_diff_2, out_merge);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -713,7 +569,7 @@ test_nested_list(void **state)
|
|||
|
||||
CHECK_PARSE_LYD(xml1, data1);
|
||||
CHECK_PARSE_LYD(xml2, data2);
|
||||
CHECK_PARSE_LYD_DIFF(data1, data2, diff);
|
||||
CHECK_PARSE_LYD_DIFF(data1, data2, 0, diff);
|
||||
|
||||
CHECK_LYD_STRING(diff,
|
||||
"<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">\n"
|
||||
|
@ -810,7 +666,7 @@ test_userord_llist(void **state)
|
|||
" <llist yang:orig-default=\"false\" yang:orig-value=\"2\" yang:value=\"\" yang:operation=\"replace\">5</llist>\n"
|
||||
"</df>\n";
|
||||
|
||||
TEST_DIFF_3(xml1, xml2, xml3, out_diff_1, out_diff_2, out_merge);
|
||||
TEST_DIFF_3(xml1, xml2, xml3, 0, out_diff_1, out_diff_2, out_merge);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -856,7 +712,7 @@ test_userord_llist2(void **state)
|
|||
" <llist yang:orig-value=\"1\" yang:operation=\"delete\">2</llist>\n"
|
||||
"</df>\n";
|
||||
|
||||
TEST_DIFF_3(xml1, xml2, xml3, out_diff_1, out_diff_2, out_merge);
|
||||
TEST_DIFF_3(xml1, xml2, xml3, 0, out_diff_1, out_diff_2, out_merge);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -899,7 +755,7 @@ test_userord_mix(void **state)
|
|||
" <llist yang:value=\"1\" yang:operation=\"create\">4</llist>\n"
|
||||
"</df>\n";
|
||||
|
||||
TEST_DIFF_3(xml1, xml2, xml3, out_diff_1, out_diff_2, out_merge);
|
||||
TEST_DIFF_3(xml1, xml2, xml3, 0, out_diff_1, out_diff_2, out_merge);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -985,7 +841,7 @@ test_userord_list(void **state)
|
|||
" </ul>\n"
|
||||
"</df>\n";
|
||||
|
||||
TEST_DIFF_3(xml1, xml2, xml3, out_diff_1, out_diff_2, out_merge);
|
||||
TEST_DIFF_3(xml1, xml2, xml3, 0, out_diff_1, out_diff_2, out_merge);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1064,7 +920,7 @@ test_userord_list2(void **state)
|
|||
" </ul>\n"
|
||||
"</df>\n";
|
||||
|
||||
TEST_DIFF_3(xml1, xml2, xml3, out_diff_1, out_diff_2, out_merge);
|
||||
TEST_DIFF_3(xml1, xml2, xml3, 0, out_diff_1, out_diff_2, out_merge);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1176,7 +1032,7 @@ test_userord_list3(void **state)
|
|||
" </ul>\n"
|
||||
"</df>\n";
|
||||
|
||||
TEST_DIFF_3(xml1, xml2, xml3, out_diff_1, out_diff_2, out_merge);
|
||||
TEST_DIFF_3(xml1, xml2, xml3, 0, out_diff_1, out_diff_2, out_merge);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1302,7 +1158,7 @@ test_keyless_list(void **state)
|
|||
" </kl>\n"
|
||||
"</df>\n";
|
||||
|
||||
TEST_DIFF_3(xml1, xml2, xml3, out_diff_1, out_diff_2, out_merge);
|
||||
TEST_DIFF_3(xml1, xml2, xml3, 0, out_diff_1, out_diff_2, out_merge);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1349,7 +1205,7 @@ test_state_llist(void **state)
|
|||
" <kll yang:position=\"1\" yang:operation=\"create\">d</kll>\n"
|
||||
"</df>\n";
|
||||
|
||||
TEST_DIFF_3(xml1, xml2, xml3, out_diff_1, out_diff_2, out_merge);
|
||||
TEST_DIFF_3(xml1, xml2, xml3, 0, out_diff_1, out_diff_2, out_merge);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1435,6 +1291,89 @@ test_wd(void **state)
|
|||
lyd_free_all(diff2);
|
||||
}
|
||||
|
||||
static void
|
||||
test_metadata(void **state)
|
||||
{
|
||||
(void) state;
|
||||
const char *xml1 = "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:df=\"urn:libyang:tests:defaults\">\n"
|
||||
" <list df:my-meta=\"val1\">\n"
|
||||
" <name>a</name>\n"
|
||||
" <value df:my-meta2=\"val2\">1</value>\n"
|
||||
" </list>\n"
|
||||
" <list>\n"
|
||||
" <name df:my-meta=\"val10\">b</name>\n"
|
||||
" <value df:my-meta=\"repeated\" df:my-meta=\"repeated\">2</value>\n"
|
||||
" </list>\n"
|
||||
"</df>\n";
|
||||
const char *xml2 = "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:df=\"urn:libyang:tests:defaults\">\n"
|
||||
" <list>\n"
|
||||
" <name>b</name>\n"
|
||||
" <value df:my-meta=\"repeated\">2</value>\n"
|
||||
" </list>\n"
|
||||
" <list>\n"
|
||||
" <name df:my-meta2=\"val22\">c</name>\n"
|
||||
" <value df:my-meta2=\"val23\">3</value>\n"
|
||||
" </list>\n"
|
||||
"</df>\n";
|
||||
const char *xml3 = "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:df=\"urn:libyang:tests:defaults\" df:my-meta=\"top\">\n"
|
||||
" <list>\n"
|
||||
" <name>b</name>\n"
|
||||
" <value df:my-meta=\"repeated\" df:my-meta=\"new\">2</value>\n"
|
||||
" </list>\n"
|
||||
" <list>\n"
|
||||
" <name df:my-meta=\"val22\">c</name>\n"
|
||||
" <value df:my-meta2=\"val23\">3</value>\n"
|
||||
" </list>\n"
|
||||
"</df>\n";
|
||||
|
||||
const char *out_diff_1 =
|
||||
"<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">\n"
|
||||
" <list yang:operation=\"delete\" yang:meta-delete=\"defaults:my-meta=val1\">\n"
|
||||
" <name>a</name>\n"
|
||||
" <value yang:meta-delete=\"defaults:my-meta2=val2\">1</value>\n"
|
||||
" </list>\n"
|
||||
" <list>\n"
|
||||
" <name yang:meta-delete=\"defaults:my-meta=val10\">b</name>\n"
|
||||
" <value yang:orig-default=\"false\" yang:meta-delete=\"defaults:my-meta=repeated\">2</value>\n"
|
||||
" </list>\n"
|
||||
" <list yang:operation=\"create\">\n"
|
||||
" <name yang:meta-create=\"defaults:my-meta2=val22\">c</name>\n"
|
||||
" <value yang:meta-create=\"defaults:my-meta2=val23\">3</value>\n"
|
||||
" </list>\n"
|
||||
"</df>\n";
|
||||
const char *out_diff_2 =
|
||||
"<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\" "
|
||||
"yang:meta-create=\"defaults:my-meta=top\">\n"
|
||||
" <list>\n"
|
||||
" <name>b</name>\n"
|
||||
" <value yang:orig-default=\"false\" yang:meta-create=\"defaults:my-meta=new\">2</value>\n"
|
||||
" </list>\n"
|
||||
" <list>\n"
|
||||
" <name yang:meta-delete=\"defaults:my-meta2=val22\" yang:meta-create=\"defaults:my-meta=val22\">c</name>\n"
|
||||
" <value yang:operation=\"none\">3</value>\n"
|
||||
" </list>\n"
|
||||
"</df>\n";
|
||||
const char *out_merge =
|
||||
"<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\" "
|
||||
"yang:meta-create=\"defaults:my-meta=top\">\n"
|
||||
" <list yang:operation=\"delete\" yang:meta-delete=\"defaults:my-meta=val1\">\n"
|
||||
" <name>a</name>\n"
|
||||
" <value yang:meta-delete=\"defaults:my-meta2=val2\">1</value>\n"
|
||||
" </list>\n"
|
||||
" <list>\n"
|
||||
" <name yang:meta-delete=\"defaults:my-meta=val10\">b</name>\n"
|
||||
" <value yang:orig-default=\"false\" yang:meta-delete=\"defaults:my-meta=repeated\" "
|
||||
"yang:meta-create=\"defaults:my-meta=new\">2</value>\n"
|
||||
" </list>\n"
|
||||
" <list yang:operation=\"create\">\n"
|
||||
" <name yang:meta-create=\"defaults:my-meta=val22\">c</name>\n"
|
||||
" <value yang:meta-create=\"defaults:my-meta2=val23\">3</value>\n"
|
||||
" </list>\n"
|
||||
"</df>\n";
|
||||
|
||||
TEST_DIFF_3(xml1, xml2, xml3, LYD_DIFF_META, out_diff_1, out_diff_2, out_merge);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
@ -1457,6 +1396,7 @@ main(void)
|
|||
UTEST(test_keyless_list, setup),
|
||||
UTEST(test_state_llist, setup),
|
||||
UTEST(test_wd, setup),
|
||||
UTEST(test_metadata, setup),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
|
|
|
@ -279,7 +279,7 @@ test_path(void **state)
|
|||
|
||||
lyd_free_tree(root);
|
||||
|
||||
/* try LYD_NEWOPT_OPAQ */
|
||||
/* try LYD_NEW_PATH_OPAQ */
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:l1", NULL, 0, 0, 0, NULL, NULL);
|
||||
assert_int_equal(ret, LY_EINVAL);
|
||||
CHECK_LOG_CTX("Predicate missing for list \"l1\" in path \"/a:l1\".", "/a:l1", 0);
|
||||
|
@ -424,7 +424,6 @@ test_path(void **state)
|
|||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:any", "<elem>val</elem>", 0, LYD_ANYDATA_XML, 0, &root, NULL);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
|
||||
lyd_print_mem(&str, root, LYD_XML, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"<any xmlns=\"urn:tests:a\">\n"
|
||||
|
@ -445,7 +444,6 @@ test_path(void **state)
|
|||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:anyx", "<a/><b/><c/>", 0, LYD_ANYDATA_XML, 0, &root, NULL);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
|
||||
lyd_print_mem(&str, root, LYD_XML, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"<anyx xmlns=\"urn:tests:a\">\n"
|
||||
|
@ -466,10 +464,44 @@ test_path(void **state)
|
|||
free(str);
|
||||
lyd_free_siblings(root);
|
||||
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:anyx", "<a/><b/><c/>", 0, LYD_ANYDATA_XML, 0, &root, NULL);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
ret = lyd_new_path2(root, NULL, "/a:anyx", "[10,11,12]", 0, LYD_ANYDATA_JSON, LYD_NEW_PATH_UPDATE, NULL, NULL);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
lyd_print_mem(&str, root, LYD_XML, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"<anyx xmlns=\"urn:tests:a\">[10,11,12]</anyx>\n");
|
||||
free(str);
|
||||
lyd_print_mem(&str, root, LYD_JSON, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"{\n"
|
||||
" \"a:anyx\": [10,11,12]\n"
|
||||
"}\n");
|
||||
free(str);
|
||||
lyd_free_siblings(root);
|
||||
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:anyx", "<a/><b/><c/>", 0, LYD_ANYDATA_XML, 0, &root, NULL);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
ret = lyd_new_path2(root, NULL, "/a:anyx", strdup("[10,11,12]"), 0, LYD_ANYDATA_JSON,
|
||||
LYD_NEW_PATH_UPDATE | LYD_NEW_ANY_USE_VALUE, NULL, NULL);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
lyd_print_mem(&str, root, LYD_XML, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"<anyx xmlns=\"urn:tests:a\">[10,11,12]</anyx>\n");
|
||||
free(str);
|
||||
lyd_print_mem(&str, root, LYD_JSON, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"{\n"
|
||||
" \"a:anyx\": [10,11,12]\n"
|
||||
"}\n");
|
||||
free(str);
|
||||
lyd_free_siblings(root);
|
||||
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:anyx", "{\"a\":[null],\"b\":[null],\"c\":[null]}", 0, LYD_ANYDATA_JSON, 0, &root, NULL);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
|
||||
lyd_print_mem(&str, root, LYD_XML, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"<anyx xmlns=\"urn:tests:a\">\n"
|
||||
|
|
|
@ -168,6 +168,21 @@ test_leaf(void **state)
|
|||
PARSER_CHECK_ERROR(data, 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID, "Invalid non-string-encoded string value \"\".", "/a:foo", 1);
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_JSON_NULL, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_null(tree);
|
||||
|
||||
/* validate integer in quotes errors out by default */
|
||||
data = "{\"a:foo3\":\"1234\"}";
|
||||
PARSER_CHECK_ERROR(data, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"Invalid non-number-encoded uint32 value \"1234\".", "/a:foo3", 1);
|
||||
|
||||
/* validate integers are parsed correctly */
|
||||
data = "{\"a:foo3\":1234}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* validate LYD_PARSE_JSON_STRING_DATATYPES parser flag allows integers in quotes */
|
||||
data = "{\"a:foo3\":\"1234\"}";
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_JSON_STRING_DATATYPES, LYD_VALIDATE_PRESENT, tree);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -920,6 +935,25 @@ test_metadata(void **state)
|
|||
CHECK_LOG_CTX("Invalid non-number-encoded int8 value \"value\".", "/a:c/x/@a:hint", 1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_parent(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct lyd_node *tree;
|
||||
struct ly_in *in;
|
||||
|
||||
/* create the parent */
|
||||
assert_int_equal(LY_SUCCESS, lyd_new_path(NULL, UTEST_LYCTX, "/a:l1[a='vala'][b='valb'][c='25']", NULL, 0, &tree));
|
||||
|
||||
/* parse nested data */
|
||||
data = "{\"cont\":{\"e\":false}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data(NULL, tree, in, LYD_JSON, 0, LYD_VALIDATE_PRESENT, NULL));
|
||||
|
||||
ly_in_free(in, 0);
|
||||
lyd_free_tree(tree);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
@ -939,6 +973,7 @@ main(void)
|
|||
UTEST(test_restconf_notification, setup),
|
||||
UTEST(test_restconf_reply, setup),
|
||||
UTEST(test_metadata, setup),
|
||||
UTEST(test_parent, setup),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
|
|
|
@ -722,6 +722,8 @@ test_netconf_reply_or_notification(void **state)
|
|||
struct ly_in *in;
|
||||
struct lyd_node *action, *tree, *op, *op2;
|
||||
|
||||
assert_non_null((ly_ctx_load_module(UTEST_LYCTX, "ietf-netconf", "2011-06-01", NULL)));
|
||||
|
||||
/* parse the action */
|
||||
data = "<c xmlns=\"urn:tests:a\">\n"
|
||||
" <act>\n"
|
||||
|
@ -817,6 +819,7 @@ test_netconf_reply_or_notification(void **state)
|
|||
" <error-type>rpc</error-type>\n"
|
||||
" <error-tag>missing-attribute</error-tag>\n"
|
||||
" <error-severity>error</error-severity>\n"
|
||||
" <error-path xmlns:a=\"urn:tests:a\">/a:c/a:x</error-path>\n"
|
||||
" <error-info>\n"
|
||||
" <bad-attribute>message-id</bad-attribute>\n"
|
||||
" <bad-element>rpc</bad-element>\n"
|
||||
|
@ -828,8 +831,6 @@ test_netconf_reply_or_notification(void **state)
|
|||
ly_in_free(in, 0);
|
||||
|
||||
CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 1, 1, LY_VALUE_XML, "rpc-reply", 0, 0, 0, 0, "");
|
||||
CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)lyd_child(tree), 0, 1, LY_VALUE_XML, "rpc-error", 0, 0, 0, 0, "");
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data);
|
||||
|
||||
lyd_free_all(tree);
|
||||
|
|
|
@ -277,12 +277,12 @@ test_minmax(void **state)
|
|||
CHECK_PARSE_LYD_PARAM("<l xmlns=\"urn:tests:c\">mate</l>"
|
||||
"<d xmlns=\"urn:tests:c\"/>",
|
||||
LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
|
||||
CHECK_LOG_CTX_APPTAG("Too few \"l\" instances.", "/c:choic/b/l", 0, "too-few-elements");
|
||||
CHECK_LOG_CTX_APPTAG("Too few \"l\" instances.", "/c:l[.='mate']", 0, "too-few-elements");
|
||||
|
||||
CHECK_PARSE_LYD_PARAM("<l xmlns=\"urn:tests:c\">val1</l>"
|
||||
"<l xmlns=\"urn:tests:c\">val2</l>",
|
||||
LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
|
||||
CHECK_LOG_CTX_APPTAG("Too few \"l\" instances.", "/c:choic/b/l", 0, "too-few-elements");
|
||||
CHECK_LOG_CTX_APPTAG("Too few \"l\" instances.", "/c:l[.='val2']", 0, "too-few-elements");
|
||||
|
||||
LYD_TREE_CREATE("<l xmlns=\"urn:tests:c\">val1</l>"
|
||||
"<l xmlns=\"urn:tests:c\">val2</l>"
|
||||
|
@ -1259,7 +1259,7 @@ test_multi_error(void **state)
|
|||
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, LYD_PARSE_ONLY, 0, LY_SUCCESS, tree);
|
||||
assert_int_equal(LY_EVALID, lyd_validate_all(&tree, NULL, LYD_VALIDATE_PRESENT | LYD_VALIDATE_MULTI_ERROR, NULL));
|
||||
lyd_free_tree(tree);
|
||||
CHECK_LOG_CTX_APPTAG("Too few \"ll\" instances.", "/ii:cont/ll", 0, "too-few-elements");
|
||||
CHECK_LOG_CTX_APPTAG("Too few \"ll\" instances.", "/ii:cont/ll[.='25']", 0, "too-few-elements");
|
||||
CHECK_LOG_CTX_APPTAG("l leaf is not left", "/ii:cont/l3", 0, "not-left");
|
||||
CHECK_LOG_CTX_APPTAG("Must condition \"../l = 'right'\" not satisfied.", "/ii:cont/l2", 0, "must-violation");
|
||||
CHECK_LOG_CTX_APPTAG("Duplicate instance of \"l\".", "/ii:cont/l", 0, NULL);
|
||||
|
|
|
@ -20,32 +20,32 @@
|
|||
|
||||
void **glob_state;
|
||||
|
||||
const char *glob_schema =
|
||||
"module sm {yang-version 1.1;namespace \"urn:sm\";prefix \"sm\";"
|
||||
"import ietf-yang-schema-mount {prefix yangmnt;}"
|
||||
"import ietf-interfaces {prefix if;}"
|
||||
"container root {yangmnt:mount-point \"root\";}"
|
||||
"container root2 {yangmnt:mount-point \"root\";}"
|
||||
"container root3 {"
|
||||
" list ls { key name; leaf name {type string;}"
|
||||
" yangmnt:mount-point \"mnt-root\";"
|
||||
" }"
|
||||
"}"
|
||||
"container root4 {config false; yangmnt:mount-point \"root\";}"
|
||||
"leaf target{type string;}"
|
||||
"augment /if:interfaces/if:interface {"
|
||||
" leaf sm-name {type leafref {path \"/sm:target\";}}"
|
||||
"}"
|
||||
"}";
|
||||
|
||||
static int
|
||||
setup(void **state)
|
||||
{
|
||||
const char *schema =
|
||||
"module sm {yang-version 1.1;namespace \"urn:sm\";prefix \"sm\";"
|
||||
"import ietf-yang-schema-mount {prefix yangmnt;}"
|
||||
"import ietf-interfaces {prefix if;}"
|
||||
"container root {yangmnt:mount-point \"root\";}"
|
||||
"container root2 {yangmnt:mount-point \"root\";}"
|
||||
"container root3 {"
|
||||
" list ls { key name; leaf name {type string;}"
|
||||
" yangmnt:mount-point \"mnt-root\";"
|
||||
" }"
|
||||
"}"
|
||||
"container root4 {config false; yangmnt:mount-point \"root\";}"
|
||||
"leaf target{type string;}"
|
||||
"augment /if:interfaces/if:interface {"
|
||||
" leaf sm-name {type leafref {path \"/sm:target\";}}"
|
||||
"}"
|
||||
"}";
|
||||
|
||||
UTEST_SETUP;
|
||||
glob_state = state;
|
||||
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_DIR_MODULES_YANG));
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, schema, LYS_IN_YANG, NULL));
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, glob_schema, LYS_IN_YANG, NULL));
|
||||
assert_non_null(ly_ctx_load_module(UTEST_LYCTX, "iana-if-type", NULL, NULL));
|
||||
|
||||
return 0;
|
||||
|
@ -1193,6 +1193,156 @@ test_parse_shared_parent_ref(void **state)
|
|||
lyd_free_siblings(data);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dup_shared(void **state)
|
||||
{
|
||||
struct ly_ctx *ctx2;
|
||||
const char *ext_data, *xml;
|
||||
struct ly_set *set;
|
||||
struct lyd_node *data, *node, *dup;
|
||||
uint32_t diff_opts;
|
||||
|
||||
ext_data = "<yang-library xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\" "
|
||||
" xmlns:ds=\"urn:ietf:params:xml:ns:yang:ietf-datastores\">"
|
||||
" <module-set>"
|
||||
" <name>test-set</name>"
|
||||
" <module>"
|
||||
" <name>ietf-datastores</name>"
|
||||
" <revision>2018-02-14</revision>"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-datastores</namespace>"
|
||||
" </module>"
|
||||
" <module>"
|
||||
" <name>ietf-yang-library</name>"
|
||||
" <revision>2019-01-04</revision>"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-library</namespace>"
|
||||
" </module>"
|
||||
" <module>"
|
||||
" <name>ietf-yang-schema-mount</name>"
|
||||
" <revision>2019-01-14</revision>"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount</namespace>"
|
||||
" </module>"
|
||||
" <module>"
|
||||
" <name>ietf-interfaces</name>"
|
||||
" <revision>2014-05-08</revision>"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-interfaces</namespace>"
|
||||
" </module>"
|
||||
" <module>"
|
||||
" <name>iana-if-type</name>"
|
||||
" <revision>2014-05-08</revision>"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:iana-if-type</namespace>"
|
||||
" </module>"
|
||||
" <import-only-module>"
|
||||
" <name>ietf-yang-types</name>"
|
||||
" <revision>2013-07-15</revision>"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-types</namespace>"
|
||||
" </import-only-module>"
|
||||
" </module-set>"
|
||||
" <schema>"
|
||||
" <name>test-schema</name>"
|
||||
" <module-set>test-set</module-set>"
|
||||
" </schema>"
|
||||
" <datastore>"
|
||||
" <name>ds:running</name>"
|
||||
" <schema>test-schema</schema>"
|
||||
" </datastore>"
|
||||
" <datastore>"
|
||||
" <name>ds:operational</name>"
|
||||
" <schema>test-schema</schema>"
|
||||
" </datastore>"
|
||||
" <content-id>1</content-id>"
|
||||
"</yang-library>"
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">"
|
||||
" <module-set-id>1</module-set-id>"
|
||||
"</modules-state>"
|
||||
"<schema-mounts xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount\">"
|
||||
" <mount-point>"
|
||||
" <module>sm</module>"
|
||||
" <label>mnt-root</label>"
|
||||
" <shared-schema/>"
|
||||
" </mount-point>"
|
||||
"</schema-mounts>";
|
||||
xml =
|
||||
"<root3 xmlns=\"urn:sm\">\n"
|
||||
" <ls>\n"
|
||||
" <name>ls1</name>\n"
|
||||
" <interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\">\n"
|
||||
" <interface>\n"
|
||||
" <name>if1</name>\n"
|
||||
" <type xmlns:ianaift=\"urn:ietf:params:xml:ns:yang:iana-if-type\">ianaift:ethernetCsmacd</type>\n"
|
||||
" </interface>\n"
|
||||
" </interfaces>\n"
|
||||
" </ls>\n"
|
||||
" <ls>\n"
|
||||
" <name>ls2</name>\n"
|
||||
" <interfaces-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\">\n"
|
||||
" <interface>\n"
|
||||
" <name>if2</name>\n"
|
||||
" <type xmlns:ianaift=\"urn:ietf:params:xml:ns:yang:iana-if-type\">ianaift:ethernetCsmacd</type>\n"
|
||||
" <oper-status>not-present</oper-status>\n"
|
||||
" <statistics>\n"
|
||||
" <discontinuity-time>2022-01-01T10:00:00-00:00</discontinuity-time>\n"
|
||||
" </statistics>\n"
|
||||
" </interface>\n"
|
||||
" </interfaces-state>\n"
|
||||
" </ls>\n"
|
||||
"</root3>\n";
|
||||
|
||||
ly_ctx_set_ext_data_clb(UTEST_LYCTX, test_ext_data_clb, (void *)ext_data);
|
||||
CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT | LYD_PARSE_ONLY, 0, LY_SUCCESS, data);
|
||||
|
||||
diff_opts = LYD_DUP_NO_META | LYD_DUP_WITH_PARENTS | LYD_DUP_RECURSIVE | LYD_DUP_NO_LYDS;
|
||||
|
||||
/* dup to the same context */
|
||||
assert_int_equal(LY_SUCCESS, lyd_find_xpath(data,
|
||||
"/sm:root3/ls[name='ls1']/ietf-interfaces:interfaces/interface[name='if1']", &set));
|
||||
assert_int_equal(1, set->count);
|
||||
node = set->dnodes[0];
|
||||
ly_set_free(set, NULL);
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single(node, NULL, diff_opts, &dup));
|
||||
|
||||
while (dup->parent) {
|
||||
dup = lyd_parent(dup);
|
||||
}
|
||||
assert_int_equal(LY_SUCCESS, lyd_find_xpath(data,
|
||||
"/sm:root3/ls[name='ls2']/ietf-interfaces:interfaces-state/interface[name='if2']", &set));
|
||||
assert_int_equal(1, set->count);
|
||||
node = set->dnodes[0];
|
||||
ly_set_free(set, NULL);
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single_to_ctx(node, LYD_CTX(data), (struct lyd_node_inner *)dup, diff_opts, NULL));
|
||||
|
||||
lyd_free_siblings(dup);
|
||||
|
||||
/* dup to another context */
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIR_CWD, &ctx2));
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(ctx2, TESTS_DIR_MODULES_YANG));
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_mem(ctx2, glob_schema, LYS_IN_YANG, NULL));
|
||||
assert_non_null(ly_ctx_load_module(ctx2, "iana-if-type", NULL, NULL));
|
||||
ly_ctx_set_ext_data_clb(ctx2, test_ext_data_clb, (void *)ext_data);
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lyd_find_xpath(data,
|
||||
"/sm:root3/ls[name='ls1']/ietf-interfaces:interfaces/interface[name='if1']", &set));
|
||||
assert_int_equal(1, set->count);
|
||||
node = set->dnodes[0];
|
||||
ly_set_free(set, NULL);
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single_to_ctx(node, ctx2, NULL, diff_opts, &dup));
|
||||
|
||||
while (dup->parent) {
|
||||
dup = lyd_parent(dup);
|
||||
}
|
||||
assert_int_equal(LY_SUCCESS, lyd_find_xpath(data,
|
||||
"/sm:root3/ls[name='ls2']/ietf-interfaces:interfaces-state/interface[name='if2']", &set));
|
||||
assert_int_equal(1, set->count);
|
||||
node = set->dnodes[0];
|
||||
ly_set_free(set, NULL);
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single_to_ctx(node, ctx2, (struct lyd_node_inner *)dup, diff_opts, NULL));
|
||||
|
||||
lyd_free_siblings(dup);
|
||||
|
||||
/* cleanup */
|
||||
ly_ctx_destroy(ctx2);
|
||||
lyd_free_siblings(data);
|
||||
}
|
||||
|
||||
static void
|
||||
test_parse_config(void **state)
|
||||
{
|
||||
|
@ -1648,6 +1798,7 @@ main(void)
|
|||
UTEST(test_parse_inline, setup),
|
||||
UTEST(test_parse_shared, setup),
|
||||
UTEST(test_parse_shared_parent_ref, setup),
|
||||
UTEST(test_dup_shared, setup),
|
||||
UTEST(test_parse_config, setup),
|
||||
UTEST(test_new, setup),
|
||||
UTEST(test_lys_getnext, setup),
|
||||
|
|
|
@ -1051,7 +1051,7 @@ test_xml(void **state)
|
|||
"</user>";
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
|
||||
assert_null(tree);
|
||||
CHECK_LOG_CTX("Too few \"user\" instances.", "/T2:user", 0);
|
||||
CHECK_LOG_CTX("Too few \"user\" instances.", "/T2:user[uid='1']", 0);
|
||||
|
||||
data =
|
||||
"<user xmlns=\"urn:tests:T2\">"
|
||||
|
@ -1347,7 +1347,7 @@ test_json(void **state)
|
|||
"]}";
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
|
||||
assert_null(tree);
|
||||
CHECK_LOG_CTX("Too few \"user\" instances.", "/T2:user", 0);
|
||||
CHECK_LOG_CTX("Too few \"user\" instances.", "/T2:user[uid='4']", 0);
|
||||
|
||||
data =
|
||||
"{\"T2:user\": ["
|
||||
|
|
|
@ -1045,11 +1045,7 @@ test_includes(void **state)
|
|||
ly_ctx_set_module_imp_clb(UTEST_LYCTX, module_clb, list);
|
||||
mod = ly_ctx_load_module(UTEST_LYCTX, "main_b", NULL, NULL);
|
||||
assert_null(mod);
|
||||
CHECK_LOG_CTX("Loading \"main_b\" module failed.", NULL, 0);
|
||||
CHECK_LOG_CTX("Data model \"main_b\" not found in local searchdirs.", NULL, 0);
|
||||
CHECK_LOG_CTX("Parsing module \"main_b\" failed.", NULL, 0);
|
||||
CHECK_LOG_CTX("Including \"sub_b_one\" submodule into \"main_b\" failed.", NULL, 0);
|
||||
CHECK_LOG_CTX("Data model \"sub_b_one\" not found in local searchdirs.", NULL, 0);
|
||||
CHECK_LOG_CTX("Parsing submodule \"sub_b_one\" failed.", NULL, 0);
|
||||
CHECK_LOG_CTX("YANG 1.1 requires all submodules to be included from main module. But submodule \"sub_b_one\" includes "
|
||||
"submodule \"sub_b_two\" which is not included by main module \"main_b\".", NULL, 0);
|
||||
|
@ -1479,7 +1475,7 @@ test_extension_argument(void **state)
|
|||
|
||||
/* context reset */
|
||||
ly_ctx_destroy(UTEST_LYCTX);
|
||||
ly_ctx_new(NULL, 0, &UTEST_LYCTX);
|
||||
ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIR_CWD, &UTEST_LYCTX);
|
||||
|
||||
/* from YIN */
|
||||
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, (void *)mod_def_yin);
|
||||
|
@ -1581,7 +1577,7 @@ test_extension_argument_element(void **state)
|
|||
|
||||
/* context reset */
|
||||
ly_ctx_destroy(UTEST_LYCTX);
|
||||
ly_ctx_new(NULL, 0, &UTEST_LYCTX);
|
||||
ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIR_CWD, &UTEST_LYCTX);
|
||||
|
||||
/* from YIN */
|
||||
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, (void *)mod_def_yin);
|
||||
|
@ -1853,7 +1849,7 @@ test_ext_recursive(void **state)
|
|||
|
||||
/* context reset */
|
||||
ly_ctx_destroy(UTEST_LYCTX);
|
||||
ly_ctx_new(NULL, 0, &UTEST_LYCTX);
|
||||
ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIR_CWD, &UTEST_LYCTX);
|
||||
|
||||
/* from YIN */
|
||||
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, (void *)mod_imp_yin);
|
||||
|
@ -1887,6 +1883,225 @@ test_lysc_path(void **state)
|
|||
free(path);
|
||||
}
|
||||
|
||||
/* TEST */
|
||||
static ly_bool
|
||||
compare_str_nodeset(struct ly_set *expected, struct ly_set *received)
|
||||
{
|
||||
ly_bool is_error = 0;
|
||||
size_t r;
|
||||
size_t e;
|
||||
|
||||
for (e = 0; expected && e < expected->count; e++) {
|
||||
const char *epath = expected->objs[e];
|
||||
ly_bool found = 0;
|
||||
|
||||
for (r = 0; received && (r < received->count); r++) {
|
||||
const char *rpath = received->objs[r];
|
||||
|
||||
if (!strcmp(epath, rpath)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
fprintf(stderr, "< %s\n", epath);
|
||||
is_error = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the count was equal and there was no error, no need to scan again */
|
||||
if (expected && received && (expected->count == received->count) && !is_error) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (r = 0; received && (r < received->count); r++) {
|
||||
ly_bool found = 0;
|
||||
const char *rpath = received->objs[r];
|
||||
|
||||
for (e = 0; expected && (e < expected->count) && !found; e++) {
|
||||
char *epath = expected->objs[e];
|
||||
|
||||
if (!strcmp(epath, rpath)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
fprintf(stderr, "> %s\n", rpath);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ly_set *
|
||||
strlist_to_pathset(const char **pathlist)
|
||||
{
|
||||
struct ly_set *set = NULL;
|
||||
uint32_t i;
|
||||
|
||||
if (!pathlist || !pathlist[0]) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ly_set_new(&set);
|
||||
|
||||
for (i = 0; pathlist[i]; i++) {
|
||||
ly_set_add(set, pathlist[i], 0, NULL);
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
static struct ly_set *
|
||||
lysc_nodeset_to_pathset(struct ly_set *nodeset)
|
||||
{
|
||||
struct ly_set *set = NULL;
|
||||
uint32_t i;
|
||||
|
||||
if (!nodeset || !nodeset->count) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ly_set_new(&set);
|
||||
|
||||
for (i = 0; i < nodeset->count; i++) {
|
||||
char *path = lysc_path(nodeset->snodes[i], LYSC_PATH_DATA, NULL, 0);
|
||||
|
||||
ly_set_add(set, path, 0, NULL);
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
static void
|
||||
test_lysc_backlinks(void **state)
|
||||
{
|
||||
const char *expect1[] = {
|
||||
/* Built-ins, not sure how to exclude those when not limiting by
|
||||
* path */
|
||||
"/ietf-yang-library:yang-library/module-set/module/deviation",
|
||||
"/ietf-yang-library:yang-library/schema/module-set",
|
||||
"/ietf-yang-library:yang-library/datastore/schema",
|
||||
"/ietf-yang-library:yang-library-update/content-id",
|
||||
"/ietf-yang-library:yang-library-change/module-set-id",
|
||||
/* Normal expected */
|
||||
"/b:my_extref_list/my_extref",
|
||||
"/a:refstr",
|
||||
"/a:refnum",
|
||||
"/b:my_extref_union",
|
||||
NULL
|
||||
};
|
||||
|
||||
const char *expect2[] = {
|
||||
"/b:my_extref_list/my_extref",
|
||||
"/a:refstr",
|
||||
"/b:my_extref_union",
|
||||
NULL
|
||||
};
|
||||
|
||||
const char *expect3[] = {
|
||||
"/b:my_extref_list/my_extref",
|
||||
"/a:refstr",
|
||||
"/a:refnum",
|
||||
"/b:my_extref_union",
|
||||
NULL
|
||||
};
|
||||
|
||||
struct {
|
||||
const char *match_path;
|
||||
ly_bool match_ancestors;
|
||||
const char **expected_paths;
|
||||
} tests[] = {
|
||||
{NULL, 0, expect1},
|
||||
{"/a:my_list/my_leaf_string", 0, expect2},
|
||||
{"/a:my_list", 1, expect3}
|
||||
};
|
||||
const char *str;
|
||||
uint32_t i;
|
||||
|
||||
str = "module a {\n"
|
||||
" namespace urn:a;\n"
|
||||
" prefix a;\n"
|
||||
" list my_list {\n"
|
||||
" key my_leaf_string;\n"
|
||||
" leaf my_leaf_string {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf my_leaf_number {\n"
|
||||
" type uint32;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" leaf refstr {\n"
|
||||
" type leafref {\n"
|
||||
" path \"../my_list/my_leaf_string\";\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" leaf refnum {\n"
|
||||
" type leafref {\n"
|
||||
" path \"../my_list/my_leaf_number\";\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_SUCCESS);
|
||||
CHECK_LOG_CTX(NULL, NULL, 0);
|
||||
|
||||
str = "module b {\n"
|
||||
" namespace urn:b;\n"
|
||||
" prefix b;\n"
|
||||
" import a {\n"
|
||||
" prefix a;\n"
|
||||
" }\n"
|
||||
" list my_extref_list {\n"
|
||||
" key my_leaf_string;\n"
|
||||
" leaf my_leaf_string {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf my_extref {\n"
|
||||
" type leafref {\n"
|
||||
" path \"/a:my_list/a:my_leaf_string\";\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" leaf my_extref_union {\n"
|
||||
" type union {\n"
|
||||
" type leafref {\n"
|
||||
" path \"/a:my_list/a:my_leaf_string\";\n"
|
||||
" }\n"
|
||||
" type leafref {\n"
|
||||
" path \"/a:my_list/a:my_leaf_number\";\n"
|
||||
" }\n"
|
||||
" type uint32;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_SUCCESS);
|
||||
CHECK_LOG_CTX(NULL, NULL, 0);
|
||||
|
||||
for (i = 0; i < sizeof tests / sizeof *tests; i++) {
|
||||
const struct lysc_node *node = NULL;
|
||||
struct ly_set *set = NULL, *expected = NULL, *received = NULL;
|
||||
|
||||
if (tests[i].match_path) {
|
||||
node = lys_find_path(UTEST_LYCTX, NULL, tests[i].match_path, 0);
|
||||
assert_non_null(node);
|
||||
}
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lysc_node_lref_backlinks(UTEST_LYCTX, node, tests[i].match_ancestors, &set));
|
||||
|
||||
expected = strlist_to_pathset(tests[i].expected_paths);
|
||||
received = lysc_nodeset_to_pathset(set);
|
||||
assert_int_equal(1, compare_str_nodeset(expected, received));
|
||||
|
||||
ly_set_free(expected, NULL);
|
||||
ly_set_free(received, free);
|
||||
ly_set_free(set, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
@ -1909,6 +2124,7 @@ main(void)
|
|||
UTEST(test_extension_compile),
|
||||
UTEST(test_ext_recursive),
|
||||
UTEST(test_lysc_path),
|
||||
UTEST(test_lysc_backlinks),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
|
|
|
@ -78,7 +78,7 @@ test_module(void **state)
|
|||
str = "module test {namespace urn:test; prefix t;"
|
||||
"feature f1;feature f2 {if-feature f1;}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod));
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, &unres.creating, &mod));
|
||||
lys_unres_glob_erase(&unres);
|
||||
ly_in_free(in, 0);
|
||||
assert_int_equal(0, mod->implemented);
|
||||
|
@ -104,7 +104,7 @@ test_module(void **state)
|
|||
/* submodules cannot be compiled directly */
|
||||
str = "submodule test {belongs-to xxx {prefix x;}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
|
||||
assert_int_equal(LY_EINVAL, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, NULL, &unres.creating, NULL));
|
||||
assert_int_equal(LY_EINVAL, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, &unres.creating, NULL));
|
||||
lys_unres_glob_erase(&unres);
|
||||
ly_in_free(in, 0);
|
||||
CHECK_LOG_CTX("Input data contains submodule which cannot be parsed directly without its main module.", NULL, 0);
|
||||
|
|
|
@ -886,18 +886,16 @@ test_module(void **state)
|
|||
/* include */
|
||||
ly_ctx_set_module_imp_clb(PARSER_CUR_PMOD(YCTX)->mod->ctx, test_imp_clb, "module xxx { namespace urn:xxx; prefix x;}");
|
||||
in.current = "module" SCHEMA_BEGINNING "include xxx;}";
|
||||
assert_int_equal(lys_parse_mem(PARSER_CUR_PMOD(YCTX)->mod->ctx, in.current, LYS_IN_YANG, NULL), LY_EVALID);
|
||||
assert_int_equal(lys_parse_mem(PARSER_CUR_PMOD(YCTX)->mod->ctx, in.current, LYS_IN_YANG, NULL), LY_EINVAL);
|
||||
CHECK_LOG_CTX("Parsing module \"name\" failed.", NULL, 0);
|
||||
CHECK_LOG_CTX("Including \"xxx\" submodule into \"name\" failed.", NULL, 0);
|
||||
CHECK_LOG_CTX("Data model \"xxx\" not found in local searchdirs.", NULL, 0);
|
||||
CHECK_LOG_CTX("Parsing submodule failed.", NULL, 0);
|
||||
CHECK_LOG_CTX("Parsing submodule \"xxx\" failed.", NULL, 0);
|
||||
CHECK_LOG_CTX("Input data contains module in situation when a submodule is expected.", NULL, 0);
|
||||
|
||||
ly_ctx_set_module_imp_clb(PARSER_CUR_PMOD(YCTX)->mod->ctx, test_imp_clb, "submodule xxx {belongs-to wrong-name {prefix w;}}");
|
||||
in.current = "module" SCHEMA_BEGINNING "include xxx;}";
|
||||
assert_int_equal(lys_parse_mem(PARSER_CUR_PMOD(YCTX)->mod->ctx, in.current, LYS_IN_YANG, NULL), LY_EVALID);
|
||||
CHECK_LOG_CTX("Parsing module \"name\" failed.", NULL, 0);
|
||||
CHECK_LOG_CTX("Including \"xxx\" submodule into \"name\" failed.", NULL, 0);
|
||||
CHECK_LOG_CTX("Parsing submodule \"xxx\" failed.", NULL, 0);
|
||||
UTEST_LOG_CTX_CLEAN;
|
||||
|
||||
ly_ctx_set_module_imp_clb(PARSER_CUR_PMOD(YCTX)->mod->ctx, test_imp_clb, "submodule xxx {belongs-to name {prefix x;}}");
|
||||
|
|
|
@ -111,11 +111,11 @@ test_schema_yang(void **state)
|
|||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
lysc_type = (struct lysc_type_bits *) lysc_leaf->type;
|
||||
CHECK_LYSC_TYPE_BITS(lysc_type, 0, 5);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 0, NULL, 0, 0, "zero", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 1, NULL, 0, 0, "one", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 10, NULL, 0, 0, "ten", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 11, NULL, 0, 0, "eleven", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[4]), 4294967295, NULL, 0, 0, "last", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 0, NULL, 0, LYS_STATUS_CURR, "zero", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 1, NULL, 0, LYS_STATUS_CURR, "one", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 10, NULL, 0, LYS_STATUS_CURR, "ten", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 11, NULL, 0, LYS_STATUS_CURR, "eleven", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[4]), 4294967295, NULL, 0, LYS_STATUS_CURR, "last", NULL);
|
||||
lysp_leaf = (void *)mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 5, 0, 0, 0, 0x02, 0, 0, "bits", 0, 0, 1, 0, 0, 0);
|
||||
|
@ -128,10 +128,10 @@ test_schema_yang(void **state)
|
|||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
lysc_type = (struct lysc_type_bits *) lysc_leaf->type;
|
||||
CHECK_LYSC_TYPE_BITS(lysc_type, 0, 4);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 2, NULL, 0, 0, "_two", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 10, NULL, 0, 0, "_ten", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 11, NULL, 0, 0, "_ten-one", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 12, NULL, 0, 0, "ten_end...", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 2, NULL, 0, LYS_STATUS_CURR, "_two", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 10, NULL, 0, LYS_STATUS_CURR, "_ten", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 11, NULL, 0, LYS_STATUS_CURR, "_ten-one", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 12, NULL, 0, LYS_STATUS_CURR, "ten_end...", NULL);
|
||||
lysp_leaf = (void *)mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 4, 0, 0, 0, 0x02, 0, 0, "bits", 0, 0, 1, 0, 0, 0);
|
||||
|
@ -146,10 +146,10 @@ test_schema_yang(void **state)
|
|||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
lysc_type = (struct lysc_type_bits *) lysc_leaf->type;
|
||||
CHECK_LYSC_TYPE_BITS(lysc_type, 0, 4);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 2, NULL, 0, 0, "two", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 10, NULL, 0, 0, "ten", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 11, NULL, 0, 0, "eleven", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 12, NULL, 0, 0, "twelve", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 2, NULL, 0, LYS_STATUS_CURR, "two", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 10, NULL, 0, LYS_STATUS_CURR, "ten", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 11, NULL, 0, LYS_STATUS_CURR, "eleven", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 12, NULL, 0, LYS_STATUS_CURR, "twelve", NULL);
|
||||
lysp_leaf = (void *)mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0, 0, 0, "my_type", 0, 0, 1, 0, 0, 0);
|
||||
|
@ -164,8 +164,8 @@ test_schema_yang(void **state)
|
|||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
lysc_type = (struct lysc_type_bits *) lysc_leaf->type;
|
||||
CHECK_LYSC_TYPE_BITS(lysc_type, 0, 2);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 2, NULL, 0, 0, "two", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 10, NULL, 0, 0, "ten", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 2, NULL, 0, LYS_STATUS_CURR, "two", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 10, NULL, 0, LYS_STATUS_CURR, "ten", NULL);
|
||||
lysp_leaf = (void *)mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 2, 0, 0, 0, 0x02, 0, 0, "my_type", 0, 0, 1, 0, 0, 0);
|
||||
|
@ -281,9 +281,9 @@ test_schema_yang(void **state)
|
|||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
lysc_type = (struct lysc_type_bits *) lysc_leaf->type;
|
||||
CHECK_LYSC_TYPE_BITS(lysc_type, 0, 3);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 0, NULL, 0, 0, "zero", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 1, NULL, 0, 0, "one", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 11, NULL, 0, 0, "eleven", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 0, NULL, 0, LYS_STATUS_CURR, "zero", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 1, NULL, 0, LYS_STATUS_CURR, "one", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 11, NULL, 0, LYS_STATUS_CURR, "eleven", NULL);
|
||||
lysp_leaf = (void *)mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 4, 0, 0, 0, 0x02, 0, 0, "bits", 0, 0, 1, 0, 0, 0);
|
||||
|
@ -300,10 +300,10 @@ test_schema_yang(void **state)
|
|||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
lysc_type = (struct lysc_type_bits *) lysc_leaf->type;
|
||||
CHECK_LYSC_TYPE_BITS(lysc_type, 0, 4);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 0, NULL, 0, 0, "zero", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 1, NULL, 0, 0, "one", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 10, NULL, 0, 0, "ten", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 11, NULL, 0, 0, "eleven", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 0, NULL, 0, LYS_STATUS_CURR, "zero", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 1, NULL, 0, LYS_STATUS_CURR, "one", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 10, NULL, 0, LYS_STATUS_CURR, "ten", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 11, NULL, 0, LYS_STATUS_CURR, "eleven", NULL);
|
||||
lysp_leaf = (void *)mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 4, 0, 0, 0, 0x02, 0, 0, "bits", 0, 0, 1, 0, 0, 0);
|
||||
|
@ -331,11 +331,11 @@ test_schema_yin(void **state)
|
|||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
lysc_type = (struct lysc_type_bits *) lysc_leaf->type;
|
||||
CHECK_LYSC_TYPE_BITS(lysc_type, 0, 5);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 0, NULL, 0, 0, "zero", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 1, NULL, 0, 0, "one", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 10, NULL, 0, 0, "ten", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 11, NULL, 0, 0, "eleven", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[4]), 4294967295, NULL, 0, 0, "last", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 0, NULL, 0, LYS_STATUS_CURR, "zero", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 1, NULL, 0, LYS_STATUS_CURR, "one", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 10, NULL, 0, LYS_STATUS_CURR, "ten", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 11, NULL, 0, LYS_STATUS_CURR, "eleven", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[4]), 4294967295, NULL, 0, LYS_STATUS_CURR, "last", NULL);
|
||||
lysp_leaf = (void *)mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 5, 0, 0, 0, 0x02, 0, 0, "bits", 0, 0, 1, 0, 0, 0);
|
||||
|
@ -351,10 +351,10 @@ test_schema_yin(void **state)
|
|||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
lysc_type = (struct lysc_type_bits *) lysc_leaf->type;
|
||||
CHECK_LYSC_TYPE_BITS(lysc_type, 0, 4);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 2, NULL, 0, 0, "_two", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 10, NULL, 0, 0, "_ten", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 11, NULL, 0, 0, "_ten-one", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 12, NULL, 0, 0, "ten_end...", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 2, NULL, 0, LYS_STATUS_CURR, "_two", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 10, NULL, 0, LYS_STATUS_CURR, "_ten", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 11, NULL, 0, LYS_STATUS_CURR, "_ten-one", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 12, NULL, 0, LYS_STATUS_CURR, "ten_end...", NULL);
|
||||
lysp_leaf = (void *)mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 4, 0, 0, 0, 0x02, 0, 0, "bits", 0, 0, 1, 0, 0, 0);
|
||||
|
@ -373,10 +373,10 @@ test_schema_yin(void **state)
|
|||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
lysc_type = (struct lysc_type_bits *) lysc_leaf->type;
|
||||
CHECK_LYSC_TYPE_BITS(lysc_type, 0, 4);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 2, NULL, 0, 0, "two", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 10, NULL, 0, 0, "ten", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 11, NULL, 0, 0, "eleven", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 12, NULL, 0, 0, "twelve", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 2, NULL, 0, LYS_STATUS_CURR, "two", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 10, NULL, 0, LYS_STATUS_CURR, "ten", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 11, NULL, 0, LYS_STATUS_CURR, "eleven", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 12, NULL, 0, LYS_STATUS_CURR, "twelve", NULL);
|
||||
lysp_leaf = (void *)mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0, 0, 0, "my_type", 0, 0, 1, 0, 0, 0);
|
||||
|
@ -396,8 +396,8 @@ test_schema_yin(void **state)
|
|||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
lysc_type = (struct lysc_type_bits *) lysc_leaf->type;
|
||||
CHECK_LYSC_TYPE_BITS(lysc_type, 0, 2);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 2, NULL, 0, 0, "two", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 10, NULL, 0, 0, "ten", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 2, NULL, 0, LYS_STATUS_CURR, "two", NULL);
|
||||
CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 10, NULL, 0, LYS_STATUS_CURR, "ten", NULL);
|
||||
lysp_leaf = (void *)mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 2, 0, 0, 0, 0x02, 0, 0, "my_type", 0, 0, 1, 0, 0, 0);
|
||||
|
|
|
@ -200,7 +200,7 @@ test_data_xml(void **state)
|
|||
|
||||
TEST_ERROR_XML2("<cont xmlns=\"urn:tests:mod\"/>",
|
||||
"defs", "xmlns:m=\"urn:tests:mod\"", "l1", "[1]", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid instance-identifier \"[1]\" value - syntax error: Unexpected XPath token \"[\" (\"[1]\"), expected \"Operator(Path)\".",
|
||||
CHECK_LOG_CTX("Invalid instance-identifier \"[1]\" value - syntax error: XPath \"[1]\" was expected to be absolute.",
|
||||
"/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML2("<cont xmlns=\"urn:tests:mod\"><l2/></cont>",
|
||||
|
|
|
@ -294,7 +294,7 @@ test_xpath_invalid_schema(void **state)
|
|||
"leaf r1 {type leafref {path \"deref(../l1)/../l2/t2\";}}");
|
||||
|
||||
UTEST_INVALID_MODULE(schema1, LYS_IN_YANG, NULL, LY_EVALID)
|
||||
CHECK_LOG_CTX("The deref function target node \"l1\" is not leaf nor leaflist", "/xp_test:r1", 0);
|
||||
CHECK_LOG_CTX("Deref function target node \"l1\" is not leaf nor leaflist.", "/xp_test:r1", 0);
|
||||
|
||||
schema2 = MODULE_CREATE_YANG("xp_test",
|
||||
"list l1 {key t1;"
|
||||
|
@ -307,7 +307,7 @@ test_xpath_invalid_schema(void **state)
|
|||
"leaf r2 {type leafref {path \"deref(../r1)/../l2/t2\";}}");
|
||||
|
||||
UTEST_INVALID_MODULE(schema2, LYS_IN_YANG, NULL, LY_EVALID)
|
||||
CHECK_LOG_CTX("The deref function target node \"r1\" is not leafref", "/xp_test:r2", 0);
|
||||
CHECK_LOG_CTX("Deref function target node \"r1\" is not leafref.", "/xp_test:r2", 0);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -105,8 +105,8 @@ test_data_xml(void **state)
|
|||
TEST_ERROR_XML2("",
|
||||
"defs", "", "un1", "123456789012345678901", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid union value \"123456789012345678901\" - no matching subtype found:\n"
|
||||
" libyang 2 - leafref, version 1: Invalid type int8 value \"123456789012345678901\".\n"
|
||||
" libyang 2 - leafref, version 1: Invalid type int64 value \"123456789012345678901\".\n"
|
||||
" libyang 2 - leafref, version 1: Invalid leafref value \"123456789012345678901\" - no target instance \"/int8\" with the same value.\n"
|
||||
" libyang 2 - leafref, version 1: Invalid leafref value \"123456789012345678901\" - no target instance \"/int64\" with the same value.\n"
|
||||
" libyang 2 - identityref, version 1: Invalid identityref \"123456789012345678901\" value - identity not found in module \"defs\".\n"
|
||||
" libyang 2 - instance-identifier, version 1: Invalid instance-identifier \"123456789012345678901\" value - syntax error.\n"
|
||||
" libyang 2 - string, version 1: Unsatisfied length - string \"123456789012345678901\" length is not allowed.\n",
|
||||
|
@ -295,7 +295,8 @@ test_validation(void **state)
|
|||
assert_int_equal(LY_EVALID, lyd_validate_all(&tree, NULL, LYD_VALIDATE_PRESENT, NULL));
|
||||
CHECK_LOG_CTX("Invalid LYB union value - no matching subtype found:\n"
|
||||
" libyang 2 - leafref, version 1: Invalid leafref value \"one\" - no target instance \"../../a/name\" with the same value.\n"
|
||||
" libyang 2 - leafref, version 1: Invalid type uint32 value \"one\".\n", "/lref:test/community[name='test']/view", 0);
|
||||
" libyang 2 - leafref, version 1: Invalid leafref value \"one\" - no target instance \"../../b/name\" with the same value.\n",
|
||||
"/lref:test/community[name='test']/view", 0);
|
||||
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
|
|
@ -161,7 +161,8 @@ struct utest_context {
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Compare two lyd_node structure. Macro print lyd_node structure into string and then compare string. Print function use these two parameters. LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK;
|
||||
* @brief Compare two lyd_node structure. Macro print lyd_node structure into string and then compare string.
|
||||
*
|
||||
* @param[in] NODE_1 pointer to lyd_node
|
||||
* @param[in] NODE_2 pointer to lyd_node
|
||||
*/
|
||||
|
@ -169,8 +170,8 @@ struct utest_context {
|
|||
{ \
|
||||
char *str1; \
|
||||
char *str2; \
|
||||
assert_int_equal(LY_SUCCESS, lyd_print_mem(&str1, NODE_1, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK)); \
|
||||
assert_int_equal(LY_SUCCESS, lyd_print_mem(&str2, NODE_2, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK)); \
|
||||
assert_int_equal(LY_SUCCESS, lyd_print_mem(&str1, NODE_1, LYD_XML, LYD_PRINT_WITHSIBLINGS)); \
|
||||
assert_int_equal(LY_SUCCESS, lyd_print_mem(&str2, NODE_2, LYD_XML, LYD_PRINT_WITHSIBLINGS)); \
|
||||
assert_non_null(str1); \
|
||||
assert_non_null(str2); \
|
||||
assert_string_equal(str1, str2); \
|
||||
|
@ -1315,7 +1316,7 @@ utest_setup(void **state)
|
|||
*state = current_utest_context;
|
||||
|
||||
/* libyang context */
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, ¤t_utest_context->ctx));
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIR_CWD, ¤t_utest_context->ctx));
|
||||
|
||||
/* backup timezone, if any */
|
||||
cur_tz = getenv("TZ");
|
||||
|
@ -1325,6 +1326,8 @@ utest_setup(void **state)
|
|||
|
||||
/* set CET */
|
||||
setenv("TZ", "CET+02:00", 1);
|
||||
/* call tzset explicitly, to update the tzname, timezone and daylight global variables */
|
||||
tzset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "cmd.h"
|
||||
#include "common.h"
|
||||
#include "compat.h"
|
||||
#include "out.h"
|
||||
#include "tools/config.h"
|
||||
#include "yl_opt.h"
|
||||
|
@ -228,7 +229,8 @@ help(int shortout)
|
|||
static void
|
||||
libyang_verbclb(LY_LOG_LEVEL level, const char *msg, const char *data_path, const char *schema_path, uint64_t line)
|
||||
{
|
||||
char *levstr;
|
||||
const char *levstr;
|
||||
char *full_msg = NULL, *aux;
|
||||
|
||||
switch (level) {
|
||||
case LY_LLERR:
|
||||
|
@ -244,15 +246,34 @@ libyang_verbclb(LY_LOG_LEVEL level, const char *msg, const char *data_path, cons
|
|||
levstr = "dbg :";
|
||||
break;
|
||||
}
|
||||
if (data_path) {
|
||||
fprintf(stderr, "libyang %s %s (%s)\n", levstr, msg, data_path);
|
||||
} else if (schema_path) {
|
||||
fprintf(stderr, "libyang %s %s (%s)\n", levstr, msg, schema_path);
|
||||
} else if (line) {
|
||||
fprintf(stderr, "libyang %s %s (line %" PRIu64 ")\n", levstr, msg, line);
|
||||
} else {
|
||||
fprintf(stderr, "libyang %s %s\n", levstr, msg);
|
||||
|
||||
if (asprintf(&full_msg, "libyang %s %s", levstr, msg) == -1) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (data_path || schema_path) {
|
||||
if (asprintf(&aux, "%s (%s)", full_msg, data_path ? data_path : schema_path) == -1) {
|
||||
goto error;
|
||||
}
|
||||
free(full_msg);
|
||||
full_msg = aux;
|
||||
}
|
||||
|
||||
if (line) {
|
||||
if (asprintf(&aux, "%s (line %" PRIu64 ")", full_msg, line) == -1) {
|
||||
goto error;
|
||||
}
|
||||
free(full_msg);
|
||||
full_msg = aux;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s\n", full_msg);
|
||||
free(full_msg);
|
||||
return;
|
||||
|
||||
error:
|
||||
free(full_msg);
|
||||
fprintf(stderr, "libyang %s Memory allocation failed.\n", levstr);
|
||||
}
|
||||
|
||||
static struct yl_schema_features *
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue