-
Notifications
You must be signed in to change notification settings - Fork 316
Add CBOR Support to libyang (#2130) #2449
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
de5666b
2498924
8a41192
2a5e854
d559711
1f36cab
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -231,6 +231,7 @@ set(format_sources | |
| src/*.h | ||
| src/plugins_exts/* | ||
| src/plugins_types/*) | ||
|
|
||
| # | ||
| # options | ||
| # | ||
|
|
@@ -249,6 +250,7 @@ option(ENABLE_YANGLINT_INTERACTIVE "Enable interactive CLI yanglint" ON) | |
| option(ENABLE_TOOLS "Build binary tools 'yanglint' and 'yangre'" ON) | ||
| option(ENABLE_COMMON_TARGETS "Define common custom target names such as 'doc' or 'uninstall', may cause conflicts when using add_subdirectory() to build this project" ON) | ||
| option(BUILD_SHARED_LIBS "By default, shared libs are enabled. Turn off for a static build." ON) | ||
| option(ENABLE_CBOR_SUPPORT "Enable CBOR support with libcbor" ON) | ||
| set(YANG_MODULE_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/yang/modules/libyang" CACHE STRING "Directory where to copy the YANG modules to") | ||
|
|
||
| if(ENABLE_INTERNAL_DOCS) | ||
|
|
@@ -316,6 +318,42 @@ if(ENABLE_COVERAGE) | |
| gen_coverage_enable(${ENABLE_TESTS}) | ||
| endif() | ||
|
|
||
| if(ENABLE_CBOR_SUPPORT) | ||
| find_package(PkgConfig) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is |
||
| if(PKG_CONFIG_FOUND) | ||
| pkg_check_modules(LIBCBOR REQUIRED libcbor) | ||
| if(LIBCBOR_FOUND) | ||
| message(STATUS "libcbor found, enabling CBOR support") | ||
| add_definitions(-DENABLE_CBOR_SUPPORT) | ||
| include_directories(${LIBCBOR_INCLUDE_DIRS}) | ||
| # Add CBOR parser files to the library sources | ||
| list(APPEND libsrc src/parser_cbor.c src/lcbor.c src/printer_cbor.c) | ||
| list(APPEND headers src/lcbor.h) | ||
| # Add CBOR files to format sources | ||
| list(APPEND format_sources src/parser_cbor.c src/lcbor.h src/lcbor.c src/printer_cbor.c) | ||
| else() | ||
| message(FATAL_ERROR "libcbor not found! Please install libcbor development package or disable CBOR support with -DENABLE_CBOR_SUPPORT=OFF") | ||
| endif() | ||
| else() | ||
| # Fallback to find_path and find_library if pkg-config is not available | ||
| find_path(LIBCBOR_INCLUDE_DIR cbor.h) | ||
| find_library(LIBCBOR_LIBRARY cbor) | ||
| if(LIBCBOR_INCLUDE_DIR AND LIBCBOR_LIBRARY) | ||
| message(STATUS "libcbor found via find_path/find_library, enabling CBOR support") | ||
| add_definitions(-DENABLE_CBOR_SUPPORT) | ||
| include_directories(${LIBCBOR_INCLUDE_DIR}) | ||
| set(LIBCBOR_LIBRARIES ${LIBCBOR_LIBRARY}) | ||
| # Add CBOR parser files to the library sources | ||
| list(APPEND libsrc src/parser_cbor.c src/lcbor.c src/printer_cbor.c) | ||
| list(APPEND headers src/lcbor.h) | ||
| # Add CBOR files to format sources | ||
| list(APPEND format_sources src/parser_cbor.c src/lcbor.h src/lcbor.c src/printer_cbor.c) | ||
| else() | ||
| message(FATAL_ERROR "libcbor not found! Please install libcbor development package or disable CBOR support with -DENABLE_CBOR_SUPPORT=OFF") | ||
| endif() | ||
| endif() | ||
| endif() | ||
|
|
||
| if ("${BUILD_TYPE_UPPER}" STREQUAL "DEBUG") | ||
| # enable before adding tests to let them detect that format checking is available - one of the tests is format checking | ||
| source_format_enable(0.77) | ||
|
|
@@ -408,6 +446,11 @@ find_package(PCRE2 10.21 REQUIRED) | |
| include_directories(${PCRE2_INCLUDE_DIRS}) | ||
| target_link_libraries(yang ${PCRE2_LIBRARIES}) | ||
|
|
||
| # link libcbor if CBOR support is enabled | ||
| if(ENABLE_CBOR_SUPPORT) | ||
| target_link_libraries(yang ${LIBCBOR_LIBRARIES}) | ||
| endif() | ||
|
|
||
| # XXHash include and library | ||
| find_package(XXHash) | ||
| if(XXHASH_FOUND) | ||
|
|
@@ -497,4 +540,4 @@ add_custom_target(cclean | |
| COMMAND make clean | ||
| COMMAND find . -iname '*cmake*' -not -name CMakeLists.txt -not -path './CMakeModules*' -exec rm -rf {} + | ||
| COMMAND rm -rf Makefile Doxyfile | ||
| WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| /** | ||
| * @file lcbor.h | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just |
||
| * @author MeherRushi <[email protected]> | ||
| * @brief CBOR data parser for libyang (abstraction over libcbor) | ||
| * | ||
| * Copyright (c) 2020 - 2023 CESNET, z.s.p.o. | ||
| * | ||
| * This source code is licensed under BSD 3-Clause License (the "License"). | ||
| * You may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * https://opensource.org/licenses/BSD-3-Clause | ||
| */ | ||
|
|
||
| #ifdef ENABLE_CBOR_SUPPORT | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems redundant if the define is around the whole file, the file should just not be compiled at all if disabled. In all the new files. |
||
|
|
||
| #include <assert.h> | ||
| #include <ctype.h> | ||
| #include <errno.h> | ||
|
|
||
| #include "in_internal.h" | ||
| #include "lcbor.h" | ||
| #include "log.h" | ||
| #include "ly_common.h" | ||
|
|
||
| const char * | ||
| lycbor_token2str(enum cbor_type cbortype) | ||
| { | ||
| switch (cbortype) { | ||
| case CBOR_TYPE_UINT: | ||
| return "unsigned integer"; | ||
| case CBOR_TYPE_NEGINT: | ||
| return "negative integer"; | ||
| case CBOR_TYPE_BYTESTRING: | ||
| return "byte string"; | ||
| case CBOR_TYPE_STRING: | ||
| return "string"; | ||
| case CBOR_TYPE_ARRAY: | ||
| return "array"; | ||
| case CBOR_TYPE_MAP: | ||
| return "map"; | ||
| case CBOR_TYPE_TAG: | ||
| return "tag"; | ||
| case CBOR_TYPE_FLOAT_CTRL: | ||
| return "decimals and special values (true, false, nil, ...)"; | ||
| } | ||
|
|
||
| return ""; | ||
| } | ||
|
|
||
| /** | ||
| * @brief Free CBOR context. | ||
| * | ||
| * @param[in] cborctx CBOR context to free. | ||
| */ | ||
| void lycbor_ctx_free(struct lycbor_ctx *cborctx) | ||
| { | ||
| if (cborctx) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Redundant |
||
| { | ||
| free(cborctx); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * @brief Detect CBOR format variant from input data. | ||
| * | ||
| * @param[in] in Input structure to analyze. | ||
| * @param[out] format Detected format. | ||
| * @return LY_ERR value. | ||
| */ | ||
| static LY_ERR | ||
| lydcbor_detect_format(struct ly_in *in, enum lyd_cbor_format *format) | ||
| { | ||
| /* Simple heuristic: try to parse as CBOR and examine structure */ | ||
| /* For now, default to named format */ | ||
| (void)in; | ||
| *format = LYD_CBOR_NAMED; | ||
| return LY_SUCCESS; | ||
| } | ||
|
|
||
| /** | ||
| * @brief Create new CBOR context for parsing. | ||
| * | ||
| * @param[in] ctx libyang context. | ||
| * @param[in] in Input handler. | ||
| * @param[out] cborctx_p Pointer to store the created CBOR context. | ||
| * @return LY_ERR value. | ||
| */ | ||
| LY_ERR | ||
| lycbor_ctx_new(const struct ly_ctx *ctx, struct ly_in *in, struct lycbor_ctx **cborctx_p) | ||
| { | ||
| /* TODO : Need to restructure error handling here */ | ||
| LY_ERR ret = LY_SUCCESS; | ||
| struct lycbor_ctx *cborctx; | ||
| struct cbor_load_result result = {0}; | ||
| enum lyd_cbor_format format; | ||
|
|
||
| assert(ctx && in && cborctx_p); | ||
|
|
||
| /* TODO : error handling after the detect_format function call */ | ||
| ret = lydcbor_detect_format(in, &format); | ||
|
|
||
| /* Allocate and initialize CBOR context */ | ||
| cborctx = calloc(1, sizeof *cborctx); | ||
| LY_CHECK_ERR_RET(!cborctx, LOGMEM(ctx), LY_EMEM); | ||
| cborctx->ctx = ctx; | ||
| cborctx->in = in; | ||
| cborctx->format = format; | ||
|
|
||
| /* load and parse CBOR data */ | ||
| cborctx->cbor_data = cbor_load(in->current, in->length, &result); | ||
| if (!cborctx->cbor_data) { | ||
| LOGVAL(ctx, LYVE_SYNTAX, "Failed to parse CBOR data."); | ||
| free(cborctx); | ||
| return LY_EVALID; | ||
| } | ||
| if (result.error.code != CBOR_ERR_NONE) { | ||
| LOGVAL(ctx, LYVE_SYNTAX, "CBOR parsing error (code %d).", result.error.code); | ||
| cbor_decref(&cborctx->cbor_data); | ||
| free(cborctx); | ||
| return LY_EVALID; | ||
| } | ||
|
|
||
| /* input line logging */ | ||
| ly_log_location(NULL, NULL, NULL, in); | ||
|
|
||
| *cborctx_p = cborctx; | ||
| return ret; | ||
| } | ||
|
|
||
| #endif /* ENABLE_CBOR_SUPPORT */ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| /** | ||
| * @file lcbor.h | ||
| * @author MeherRushi <[email protected]> | ||
| * @brief CBOR data parser routines for libyang (abstraction over libcbor) | ||
| * | ||
| * Copyright (c) 2020 - 2023 CESNET, z.s.p.o. | ||
| * | ||
| * This source code is licensed under BSD 3-Clause License (the "License"). | ||
| * You may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * https://opensource.org/licenses/BSD-3-Clause | ||
| */ | ||
|
|
||
| #ifndef LY_LCBOR_H_ | ||
| #define LY_LCBOR_H_ | ||
|
|
||
| #ifdef ENABLE_CBOR_SUPPORT | ||
|
|
||
| #include <stddef.h> | ||
| #include <stdint.h> | ||
| /* using libcbor as the low-level parser */ | ||
| #include <cbor.h> | ||
|
|
||
|
|
||
| #include "log.h" | ||
| #include "set.h" | ||
|
|
||
| struct ly_ctx; | ||
| struct ly_in; | ||
|
|
||
| /** | ||
| * @brief CBOR format variants for different encoding schemes | ||
| */ | ||
| enum lyd_cbor_format | ||
| { | ||
| LYD_CBOR_NAMED, /**< CBOR with named identifiers (JSON-like) */ | ||
| LYD_CBOR_SID /**< CBOR with Schema Item identifiers (future implementation) */ | ||
| }; | ||
|
|
||
| struct lycbor_ctx { | ||
| const struct ly_ctx *ctx; /**< libyang context */ | ||
| struct ly_in *in; /**< input structure */ | ||
|
|
||
| cbor_item_t *cbor_data; /**< parsed CBOR data */ | ||
|
|
||
| enum lyd_cbor_format format; /**< CBOR format variant */ | ||
|
|
||
| struct { | ||
| cbor_item_t *cbor_data; /**< parsed CBOR data */ | ||
| enum lyd_cbor_format format; /**< CBOR format variant */ | ||
| const char *input; | ||
| } backup; | ||
| }; | ||
|
|
||
| /** | ||
| * @brief Create new CBOR context for parsing. | ||
| * | ||
| * @param[in] ctx libyang context. | ||
| * @param[in] in Input handler. | ||
| * @param[out] cborctx_p Pointer to store the created CBOR context. | ||
| * @return LY_ERR value. | ||
| */ | ||
| LY_ERR | ||
| lycbor_ctx_new(const struct ly_ctx *ctx, struct ly_in *in, struct lycbor_ctx **cborctx_p); | ||
|
|
||
| /** | ||
| * @brief Free CBOR context. | ||
| * | ||
| * @param[in] cborctx CBOR context to free. | ||
| */ | ||
| void | ||
| lycbor_ctx_free(struct lycbor_ctx *cborctx); | ||
|
|
||
| #endif /* ENABLE_CBOR_SUPPORT */ | ||
|
|
||
| #endif /* LY_LCBOR_H_ */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, an
optionis probably redundant. You can just search forlibcborand if found, the support will be added, otherwise not.