mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-11-26 20:12:44 +00:00
libcbor: vendor update to 0.11.0
Sponsored by: The FreeBSD Foundation
This commit is contained in:
commit
abd872540f
@ -4,12 +4,14 @@ commands:
|
||||
linux-setup:
|
||||
steps:
|
||||
- run: sudo apt-get update
|
||||
- run: sudo apt-get install -y cmake ${TOOLCHAIN_PACKAGES}
|
||||
- run: sudo apt install libcmocka-dev
|
||||
# NEEDRESTART_MODE prevents automatic restarts which seem to hang.
|
||||
- run: sudo NEEDRESTART_MODE=l apt-get install -y cmake ${TOOLCHAIN_PACKAGES}
|
||||
- run: sudo NEEDRESTART_MODE=l apt-get install -y libcmocka-dev libcjson-dev
|
||||
build:
|
||||
steps:
|
||||
- run: >
|
||||
cmake -DWITH_TESTS=ON \
|
||||
-DWITH_EXAMPLES=ON \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DSANITIZE=OFF \
|
||||
-DCOVERAGE="${CMAKE_COVERAGE:='OFF'}" \
|
||||
@ -31,14 +33,14 @@ orbs:
|
||||
|
||||
jobs:
|
||||
static-test:
|
||||
machine:
|
||||
image: ubuntu-2204:2022.10.2
|
||||
machine: &default-machine
|
||||
image: ubuntu-2204:2023.07.2
|
||||
environment:
|
||||
TOOLCHAIN_PACKAGES: g++
|
||||
steps:
|
||||
- checkout
|
||||
- linux-setup
|
||||
- run: sudo apt-get install -y clang-format doxygen cppcheck
|
||||
- run: sudo NEEDRESTART_MODE=l apt-get install -y clang-format doxygen cppcheck
|
||||
- run: cppcheck --inline-suppr --error-exitcode=1 .
|
||||
- run: bash clang-format.sh --verbose
|
||||
- run: >
|
||||
@ -60,14 +62,14 @@ jobs:
|
||||
|
||||
build-and-test:
|
||||
machine:
|
||||
image: ubuntu-2204:2022.10.2
|
||||
<<: *default-machine
|
||||
environment:
|
||||
TOOLCHAIN_PACKAGES: g++
|
||||
CMAKE_COVERAGE: ON
|
||||
steps:
|
||||
- checkout
|
||||
- linux-setup
|
||||
- run: sudo apt-get install -y valgrind
|
||||
- run: sudo NEEDRESTART_MODE=l apt-get install -y valgrind
|
||||
- build
|
||||
- test
|
||||
- run: ctest -T Coverage
|
||||
@ -81,7 +83,7 @@ jobs:
|
||||
|
||||
build-and-test-clang:
|
||||
machine:
|
||||
image: ubuntu-2204:2022.10.2
|
||||
<<: *default-machine
|
||||
environment:
|
||||
TOOLCHAIN_PACKAGES: clang
|
||||
CC: clang
|
||||
@ -94,11 +96,11 @@ jobs:
|
||||
|
||||
build-and-test-32b:
|
||||
machine:
|
||||
image: ubuntu-2204:2022.10.2
|
||||
<<: *default-machine
|
||||
steps:
|
||||
- checkout
|
||||
- run: sudo apt-get update
|
||||
- run: sudo apt-get install -y cmake gcc-multilib g++-multilib libc6-dev-i386
|
||||
- run: sudo NEEDRESTART_MODE=l apt-get install -y cmake gcc-multilib g++-multilib libc6-dev-i386
|
||||
# Make cmocka from source w/ 32b setup
|
||||
- run: git clone https://git.cryptomilk.org/projects/cmocka.git ~/cmocka
|
||||
- run: >
|
||||
@ -117,7 +119,7 @@ jobs:
|
||||
|
||||
build-and-test-release-clang:
|
||||
machine:
|
||||
image: ubuntu-2204:2022.10.2
|
||||
<<: *default-machine
|
||||
environment:
|
||||
TOOLCHAIN_PACKAGES: clang
|
||||
CC: clang
|
||||
@ -130,7 +132,7 @@ jobs:
|
||||
|
||||
llvm-coverage:
|
||||
machine:
|
||||
image: ubuntu-2204:2022.10.2
|
||||
<<: *default-machine
|
||||
environment:
|
||||
TOOLCHAIN_PACKAGES: clang
|
||||
CC: clang
|
||||
@ -145,7 +147,7 @@ jobs:
|
||||
|
||||
build-and-test-arm:
|
||||
machine:
|
||||
image: ubuntu-2204:2022.10.2
|
||||
<<: *default-machine
|
||||
environment:
|
||||
TOOLCHAIN_PACKAGES: g++
|
||||
resource_class: arm.medium
|
||||
@ -157,7 +159,7 @@ jobs:
|
||||
|
||||
build-bazel:
|
||||
machine:
|
||||
image: ubuntu-2204:2022.10.2
|
||||
image: ubuntu-2204:2023.07.2
|
||||
environment:
|
||||
TOOLCHAIN_PACKAGES: g++
|
||||
steps:
|
||||
|
26
contrib/libcbor/.cirrus.yml
Normal file
26
contrib/libcbor/.cirrus.yml
Normal file
@ -0,0 +1,26 @@
|
||||
freebsd_task:
|
||||
install_script:
|
||||
- ASSUME_ALWAYS_YES=yes pkg bootstrap -f && pkg install -y cmocka cmake ninja
|
||||
build_script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake -GNinja -DWITH_TESTS=ON
|
||||
-DCBOR_CUSTOM_ALLOC=ON
|
||||
-DCMAKE_BUILD_TYPE=Debug
|
||||
-DSANITIZE=OFF
|
||||
..
|
||||
- ninja -j $(sysctl -n hw.ncpu)
|
||||
test_script:
|
||||
- cd build
|
||||
- ctest -VV
|
||||
matrix:
|
||||
# From gcloud compute images list --project freebsd-org-cloud-dev --no-standard-images
|
||||
- name: freebsd-13-2
|
||||
freebsd_instance:
|
||||
image_family: freebsd-13-2
|
||||
- name: freebsd-14-0
|
||||
freebsd_instance:
|
||||
image_family: freebsd-14-0
|
||||
- name: freebsd-15-0-snap
|
||||
freebsd_instance:
|
||||
image_family: freebsd-15-0-snap
|
21
contrib/libcbor/.readthedocs.yaml
Normal file
21
contrib/libcbor/.readthedocs.yaml
Normal file
@ -0,0 +1,21 @@
|
||||
# .readthedocs.yaml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Set the version of Python and other tools you might need
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3.11"
|
||||
|
||||
sphinx:
|
||||
configuration: doc/source/conf.py
|
||||
|
||||
# We recommend specifying your dependencies to enable reproducible builds:
|
||||
# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
|
||||
python:
|
||||
install:
|
||||
- requirements: doc/source/requirements.txt
|
@ -4,6 +4,19 @@ Template:
|
||||
Next
|
||||
---------------------
|
||||
|
||||
0.11.0 (2024-02-04)
|
||||
---------------------
|
||||
- [Updated documentation to refer to RFC 8949](https://github.com/PJK/libcbor/issues/269)
|
||||
- Improvements to `cbor_describe`
|
||||
- [Bytestring data will now be printed as well](https://github.com/PJK/libcbor/pull/281) by [akallabeth](https://github.com/akallabeth)
|
||||
- [Formatting consistency and clarity improvements](https://github.com/PJK/libcbor/pull/285)
|
||||
- [Fix `cbor_string_set_handle` not setting the codepoint count](https://github.com/PJK/libcbor/pull/286)
|
||||
- BREAKING: [`cbor_load` will no longer fail on input strings that are well-formed but not valid UTF-8](https://github.com/PJK/libcbor/pull/286)
|
||||
- If you were relying on the validation, please check the result using `cbor_string_codepoint_count` instead
|
||||
- BREAKING: [All decoders like `cbor_load` and `cbor_stream_decode` will accept all well-formed tag values](https://github.com/PJK/libcbor/pull/308) (bug discovered by [dskern-github](https://github.com/dskern-github))
|
||||
- Previously, decoding of certain values would fail with `CBOR_ERR_MALFORMATED` or `CBOR_DECODER_ERROR`
|
||||
- This also makes decoding symmetrical with serialization, which already accepts all values
|
||||
|
||||
0.10.2 (2023-01-31)
|
||||
---------------------
|
||||
- [Fixed minor test bug causing failures for x86 Linux](https://github.com/PJK/libcbor/pull/266) (discovered by [trofi](https://github.com/PJK/libcbor/issues/263))
|
||||
@ -117,7 +130,7 @@ Next
|
||||
Breaks build & header compatibility due to:
|
||||
|
||||
- Improved build configuration and feature check macros
|
||||
- Endianess configuration fixes (by Erwin Kroon and David Grigsby)
|
||||
- Endianness configuration fixes (by Erwin Kroon and David Grigsby)
|
||||
- pkg-config compatibility (by Vincent Bernat)
|
||||
- enable use of versioned SONAME (by Vincent Bernat)
|
||||
- better fuzzer (wasn't random until now, ooops)
|
||||
|
@ -1,14 +1,18 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
project(libcbor)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/")
|
||||
include(CTest)
|
||||
include(GNUInstallDirs) # Provides CMAKE_INSTALL_ variables
|
||||
|
||||
SET(CBOR_VERSION_MAJOR "0")
|
||||
SET(CBOR_VERSION_MINOR "10")
|
||||
SET(CBOR_VERSION_PATCH "2")
|
||||
SET(CBOR_VERSION_MINOR "11")
|
||||
SET(CBOR_VERSION_PATCH "0")
|
||||
SET(CBOR_VERSION ${CBOR_VERSION_MAJOR}.${CBOR_VERSION_MINOR}.${CBOR_VERSION_PATCH})
|
||||
|
||||
set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY true)
|
||||
option(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY "cmake --build --target install does not depend on cmake --build" true)
|
||||
option(BUILD_SHARED_LIBS "Build as a shared library" false)
|
||||
|
||||
include(CheckIncludeFiles)
|
||||
|
||||
include(TestBigEndian)
|
||||
@ -19,10 +23,10 @@ endif()
|
||||
|
||||
option(CBOR_CUSTOM_ALLOC "Custom, dynamically defined allocator support" OFF)
|
||||
if(CBOR_CUSTOM_ALLOC)
|
||||
message(WARNING
|
||||
message(WARNING
|
||||
"CBOR_CUSTOM_ALLOC has been deprecated. Custom allocators are now enabled by default."
|
||||
"The flag is a no-op and will be removed in the next version. "
|
||||
"Please remove CBOR_CUSTOM_ALLOC from your build configuation.")
|
||||
"Please remove CBOR_CUSTOM_ALLOC from your build configuration.")
|
||||
endif(CBOR_CUSTOM_ALLOC)
|
||||
|
||||
option(CBOR_PRETTY_PRINTER "Include a pretty-printing routine" ON)
|
||||
@ -138,12 +142,10 @@ if (COVERAGE)
|
||||
endif()
|
||||
endif (COVERAGE)
|
||||
|
||||
|
||||
# We want to generate configuration.h from the template and make it so that it is accessible using the same
|
||||
# path during both library build and installed header use, without littering the source dir.
|
||||
# Using cbor/configuration.h in the build dir works b/c headers will be installed to <prefix>/cbor
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/cbor/configuration.h.in ${PROJECT_BINARY_DIR}/cbor/configuration.h)
|
||||
install(FILES ${PROJECT_BINARY_DIR}/cbor/configuration.h DESTINATION include/cbor)
|
||||
install(FILES ${PROJECT_BINARY_DIR}/cbor/configuration.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cbor)
|
||||
# Make the header visible at compile time
|
||||
include_directories(${PROJECT_BINARY_DIR})
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
libcbor is maintained by [@PJK](https://github.com/PJK) in his spare time on a best-effort basis.
|
||||
|
||||
Community contributions are welcome as long as they align with the [project priorities](https://github.com/PJK/libcbor#main-features) and [goals](https://libcbor.readthedocs.io/en/latest/development.html#goals) and follow the guidelines described belows.
|
||||
Community contributions are welcome as long as they align with the [project priorities](https://github.com/PJK/libcbor#main-features) and [goals](https://libcbor.readthedocs.io/en/latest/development.html#goals) and follow the guidelines described below.
|
||||
|
||||
## Principles
|
||||
|
||||
|
@ -48,7 +48,7 @@ PROJECT_NAME = libcbor
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = 0.10.2
|
||||
PROJECT_NUMBER = 0.11.0
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
|
@ -1,16 +1,15 @@
|
||||
# [libcbor](https://github.com/PJK/libcbor)
|
||||
|
||||
[![CircleCI](https://circleci.com/gh/PJK/libcbor/tree/master.svg?style=svg)](https://circleci.com/gh/PJK/libcbor/tree/master)
|
||||
[![Build status](https://ci.appveyor.com/api/projects/status/8kkmvmefelsxp5u2?svg=true)](https://ci.appveyor.com/project/PJK/libcbor)
|
||||
[![Documentation Status](https://readthedocs.org/projects/libcbor/badge/?version=latest)](https://readthedocs.org/projects/libcbor/?badge=latest)
|
||||
[![latest packaged version(s)](https://repology.org/badge/latest-versions/libcbor.svg)](https://repology.org/project/libcbor/versions)
|
||||
[![codecov](https://codecov.io/gh/PJK/libcbor/branch/master/graph/badge.svg)](https://codecov.io/gh/PJK/libcbor)
|
||||
|
||||
**libcbor** is a C library for parsing and generating [CBOR](https://tools.ietf.org/html/rfc7049), the general-purpose schema-less binary data format.
|
||||
**libcbor** is a C library for parsing and generating [CBOR](https://cbor.io/), the general-purpose schema-less binary data format.
|
||||
|
||||
## Main features
|
||||
- Complete RFC conformance
|
||||
- Robust C99 implementation
|
||||
- Complete [IETF RFC 8949 (STD 94)](https://www.rfc-editor.org/info/std94) conformance
|
||||
- Robust platform-independent C99 implementation
|
||||
- Layered architecture offers both control and convenience
|
||||
- Flexible memory management
|
||||
- No shared global state - threading friendly
|
||||
|
@ -1,14 +0,0 @@
|
||||
image: Visual Studio 2022
|
||||
version: '{build}'
|
||||
platform: x64
|
||||
|
||||
skip_branch_with_pr: true
|
||||
|
||||
before_build:
|
||||
- cmake -H. -Bbuild
|
||||
|
||||
build_script:
|
||||
- if "%APPVEYOR_REPO_TAG%"=="true" (set CONFIGURATION=RelWithDebInfo) else (set CONFIGURATION=Debug)
|
||||
- cmake --build build --config "%CONFIGURATION%"
|
||||
|
||||
# TODO enable CMocka tests, maybe package the binaries
|
@ -1,7 +1,7 @@
|
||||
Types of items
|
||||
===============================================
|
||||
|
||||
Every :type:`cbor_item_t` has a :type:`cbor_type` associated with it - these constants correspond to the types specified by the `CBOR standard <http://tools.ietf.org/html/rfc7049>`_:
|
||||
Every :type:`cbor_item_t` has a :type:`cbor_type` associated with it - these constants correspond to the types specified by the `CBOR standard <https://www.rfc-editor.org/info/std94>`_:
|
||||
|
||||
.. doxygenenum:: cbor_type
|
||||
|
||||
|
@ -33,7 +33,8 @@ extensions = [
|
||||
'breathe',
|
||||
'sphinx.ext.mathjax',
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.ifconfig'
|
||||
'sphinx.ext.ifconfig',
|
||||
'sphinx_rtd_theme'
|
||||
]
|
||||
|
||||
import subprocess, os
|
||||
@ -76,8 +77,8 @@ copyright = '2014 - 2020, Pavel Kalvoda'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.10'
|
||||
release = '0.10.2'
|
||||
version = '0.11'
|
||||
release = '0.11.0'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
@ -127,7 +128,7 @@ pygments_style = 'sphinx'
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
@ -285,12 +286,3 @@ texinfo_documents = [
|
||||
|
||||
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||
#texinfo_no_detailmenu = False
|
||||
|
||||
|
||||
if not on_rtd: # only import and set the theme if we're building docs locally
|
||||
import sphinx_rtd_theme
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
||||
|
||||
# otherwise, readthedocs.org uses their theme by default, so no need to specify it
|
||||
|
||||
|
@ -22,15 +22,15 @@ everywhere.
|
||||
Goals
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
RFC-conformance and full feature support
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Standard conformance and full feature support
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Anything the standard allows, libcbor can do.
|
||||
|
||||
**Why?** Because conformance and interoperability is the point of defining
|
||||
standards. Clients expect the support to be feature-complete and
|
||||
there is no significant complexity reduction that can be achieved by slightly
|
||||
cutting corners, which means that the incremental cost of full RFC support is
|
||||
cutting corners, which means that the incremental cost of full [CBOR standard](https://www.rfc-editor.org/info/std94) support is
|
||||
comparatively small over "almost-conformance" seen in many alternatives.
|
||||
|
||||
|
||||
|
@ -9,7 +9,7 @@ Overview
|
||||
|
||||
|
||||
Main features
|
||||
- Complete RFC conformance [#]_
|
||||
- Complete `IETF RFC 8949 (STD 94) <https://www.rfc-editor.org/info/std94>`_ conformance [#]_
|
||||
- Robust C99 implementation
|
||||
- Layered architecture offers both control and convenience
|
||||
- Flexible memory management
|
||||
@ -19,7 +19,7 @@ Main features
|
||||
- Extensive documentation and test suite
|
||||
- No runtime dependencies, small footprint
|
||||
|
||||
.. [#] See :doc:`rfc_conformance`
|
||||
.. [#] See :doc:`standard_conformance`
|
||||
|
||||
.. [#] With the exception of custom memory allocators (see :doc:`api/item_reference_counting`)
|
||||
|
||||
@ -31,9 +31,9 @@ Contents
|
||||
using
|
||||
api
|
||||
tests
|
||||
rfc_conformance
|
||||
standard_conformance
|
||||
internal
|
||||
changelog
|
||||
development
|
||||
|
||||
.. _CBOR: http://tools.ietf.org/html/rfc7049
|
||||
.. _CBOR: https://www.rfc-editor.org/info/std94
|
||||
|
@ -6,7 +6,7 @@ Internal workings of *libcbor* are mostly derived from the specification. The pu
|
||||
Terminology
|
||||
---------------
|
||||
=== ====================== ========================================================================================================================================
|
||||
MTB Major Type Byte http://tools.ietf.org/html/rfc7049#section-2.1
|
||||
MTB Major Type Byte https://www.rfc-editor.org/rfc/rfc8949.html#section-3.1
|
||||
--- ---------------------- ----------------------------------------------------------------------------------------------------------------------------------------
|
||||
DST Dynamically Sized Type Type whose storage requirements cannot be determined
|
||||
|
||||
@ -32,7 +32,7 @@ and also borrowing from
|
||||
|
||||
General notes on the API design
|
||||
--------------------------------
|
||||
The API design has two main driving priciples:
|
||||
The API design has two main driving principles:
|
||||
|
||||
1. Let the client manage the memory as much as possible
|
||||
2. Behave exactly as specified by the standard
|
||||
|
@ -1,31 +1,31 @@
|
||||
alabaster==0.7.12
|
||||
Babel==2.9.1
|
||||
breathe==4.33.1
|
||||
certifi==2022.12.7
|
||||
charset-normalizer==2.0.12
|
||||
colorama==0.4.4
|
||||
docutils==0.17.1
|
||||
idna==3.3
|
||||
imagesize==1.3.0
|
||||
importlib-metadata==4.11.3
|
||||
Jinja2==3.0.3
|
||||
alabaster==0.7.13
|
||||
Babel==2.13.1
|
||||
breathe==4.35.0
|
||||
certifi==2023.11.17
|
||||
charset-normalizer==3.3.2
|
||||
colorama==0.4.6
|
||||
docutils==0.18.1
|
||||
idna==3.4
|
||||
imagesize==1.4.1
|
||||
importlib-metadata==6.8.0
|
||||
Jinja2==3.1.2
|
||||
livereload==2.6.3
|
||||
MarkupSafe==2.1.1
|
||||
packaging==21.3
|
||||
Pygments==2.11.2
|
||||
pyparsing==3.0.7
|
||||
MarkupSafe==2.1.3
|
||||
packaging==23.2
|
||||
Pygments==2.16.1
|
||||
pyparsing==3.1.1
|
||||
pytz==2021.3
|
||||
requests==2.27.1
|
||||
requests==2.31.0
|
||||
snowballstemmer==2.2.0
|
||||
Sphinx==4.4.0
|
||||
Sphinx==7.2.6
|
||||
sphinx-autobuild==2021.3.14
|
||||
sphinx-rtd-theme==1.0.0
|
||||
sphinxcontrib-applehelp==1.0.2
|
||||
sphinxcontrib-devhelp==1.0.2
|
||||
sphinxcontrib-htmlhelp==2.0.0
|
||||
sphinx-rtd-theme==1.3.0
|
||||
sphinxcontrib-applehelp==1.0.7
|
||||
sphinxcontrib-devhelp==1.0.5
|
||||
sphinxcontrib-htmlhelp==2.0.4
|
||||
sphinxcontrib-jsmath==1.0.1
|
||||
sphinxcontrib-qthelp==1.0.3
|
||||
sphinxcontrib-serializinghtml==1.1.5
|
||||
tornado==6.1
|
||||
urllib3==1.26.9
|
||||
zipp==3.7.0
|
||||
sphinxcontrib-qthelp==1.0.6
|
||||
sphinxcontrib-serializinghtml==1.1.9
|
||||
tornado==6.3.3
|
||||
urllib3==2.1.0
|
||||
zipp==3.17.0
|
||||
|
@ -1,13 +1,13 @@
|
||||
RFC conformance
|
||||
IETF standard conformance
|
||||
=========================
|
||||
|
||||
*libcbor* is, generally speaking, very faithful implementation of `RFC 7049 <https://tools.ietf.org/html/rfc7049>`_. There are, however, some limitations imposed by technical constraints.
|
||||
*libcbor* is, generally speaking, a very faithful implementation of `IETF RFC 8949 (STD 94) <https://www.rfc-editor.org/info/std94>`_. There are, however, some limitations related to the numerical range and precision available in portable C99.
|
||||
|
||||
Bytestring length
|
||||
-------------------
|
||||
There is no explicit limitation of indefinite length byte strings. [#]_ *libcbor* will not handle byte strings with more chunks than the maximum value of :type:`size_t`. On any sane platform, such string would not fit in the memory anyway. It is, however, possible to process arbitrarily long strings and byte strings using the streaming decoder.
|
||||
|
||||
.. [#] https://tools.ietf.org/html/rfc7049#section-2.2.2
|
||||
.. [#] https://www.rfc-editor.org/rfc/rfc8949.html#section-3.2.3
|
||||
|
||||
"Half-precision" IEEE 754 floats
|
||||
---------------------------------
|
@ -22,6 +22,10 @@ if(CJSON_FOUND)
|
||||
add_executable(cjson2cbor cjson2cbor.c)
|
||||
target_include_directories(cjson2cbor PUBLIC ${CJSON_INCLUDE_DIRS})
|
||||
target_link_libraries(cjson2cbor cbor ${CJSON_LIBRARY})
|
||||
|
||||
add_executable(cbor2cjson cbor2cjson.c)
|
||||
target_include_directories(cbor2cjson PUBLIC ${CJSON_INCLUDE_DIRS})
|
||||
target_link_libraries(cbor2cjson cbor ${CJSON_LIBRARY})
|
||||
endif()
|
||||
|
||||
file(COPY data DESTINATION .)
|
||||
|
@ -2,8 +2,8 @@
|
||||
#define LIBCBOR_CONFIGURATION_H
|
||||
|
||||
#define CBOR_MAJOR_VERSION 0
|
||||
#define CBOR_MINOR_VERSION 10
|
||||
#define CBOR_PATCH_VERSION 2
|
||||
#define CBOR_MINOR_VERSION 11
|
||||
#define CBOR_PATCH_VERSION 0
|
||||
|
||||
#define CBOR_BUFFER_GROWTH 2
|
||||
#define CBOR_MAX_STACK_SIZE 2048
|
||||
|
123
contrib/libcbor/examples/cbor2cjson.c
Normal file
123
contrib/libcbor/examples/cbor2cjson.c
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
|
||||
*
|
||||
* libcbor is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#include <cjson/cJSON.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cbor.h"
|
||||
|
||||
void usage(void) {
|
||||
printf("Usage: cbor2cjson [input file]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cJSON* cbor_to_cjson(cbor_item_t* item) {
|
||||
switch (cbor_typeof(item)) {
|
||||
case CBOR_TYPE_UINT:
|
||||
return cJSON_CreateNumber(cbor_get_int(item));
|
||||
case CBOR_TYPE_NEGINT:
|
||||
return cJSON_CreateNumber(-1 - cbor_get_int(item));
|
||||
case CBOR_TYPE_BYTESTRING:
|
||||
// cJSON only handles null-terminated string -- binary data would have to
|
||||
// be escaped
|
||||
return cJSON_CreateString("Unsupported CBOR item: Bytestring");
|
||||
case CBOR_TYPE_STRING:
|
||||
if (cbor_string_is_definite(item)) {
|
||||
// cJSON only handles null-terminated string
|
||||
char* null_terminated_string = malloc(cbor_string_length(item) + 1);
|
||||
memcpy(null_terminated_string, cbor_string_handle(item),
|
||||
cbor_string_length(item));
|
||||
null_terminated_string[cbor_string_length(item)] = 0;
|
||||
cJSON* result = cJSON_CreateString(null_terminated_string);
|
||||
free(null_terminated_string);
|
||||
return result;
|
||||
}
|
||||
return cJSON_CreateString("Unsupported CBOR item: Chunked string");
|
||||
case CBOR_TYPE_ARRAY: {
|
||||
cJSON* result = cJSON_CreateArray();
|
||||
for (size_t i = 0; i < cbor_array_size(item); i++) {
|
||||
cJSON_AddItemToArray(result, cbor_to_cjson(cbor_array_get(item, i)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
case CBOR_TYPE_MAP: {
|
||||
cJSON* result = cJSON_CreateObject();
|
||||
for (size_t i = 0; i < cbor_map_size(item); i++) {
|
||||
char* key = malloc(128);
|
||||
snprintf(key, 128, "Surrogate key %zu", i);
|
||||
// JSON only support string keys
|
||||
if (cbor_isa_string(cbor_map_handle(item)[i].key) &&
|
||||
cbor_string_is_definite(cbor_map_handle(item)[i].key)) {
|
||||
size_t key_length = cbor_string_length(cbor_map_handle(item)[i].key);
|
||||
if (key_length > 127) key_length = 127;
|
||||
// Null-terminated madness
|
||||
memcpy(key, cbor_string_handle(cbor_map_handle(item)[i].key),
|
||||
key_length);
|
||||
key[key_length] = 0;
|
||||
}
|
||||
|
||||
cJSON_AddItemToObject(result, key,
|
||||
cbor_to_cjson(cbor_map_handle(item)[i].value));
|
||||
free(key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
case CBOR_TYPE_TAG:
|
||||
return cJSON_CreateString("Unsupported CBOR item: Tag");
|
||||
case CBOR_TYPE_FLOAT_CTRL:
|
||||
if (cbor_float_ctrl_is_ctrl(item)) {
|
||||
if (cbor_is_bool(item)) return cJSON_CreateBool(cbor_get_bool(item));
|
||||
if (cbor_is_null(item)) return cJSON_CreateNull();
|
||||
return cJSON_CreateString("Unsupported CBOR item: Control value");
|
||||
}
|
||||
return cJSON_CreateNumber(cbor_float_get_float(item));
|
||||
}
|
||||
|
||||
return cJSON_CreateNull();
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads CBOR data from a file and outputs JSON using cJSON
|
||||
* $ ./examples/cbor2cjson examples/data/nested_array.cbor
|
||||
*/
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 2) usage();
|
||||
FILE* f = fopen(argv[1], "rb");
|
||||
if (f == NULL) usage();
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t length = (size_t)ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
unsigned char* buffer = malloc(length);
|
||||
fread(buffer, length, 1, f);
|
||||
|
||||
/* Assuming `buffer` contains `length` bytes of input data */
|
||||
struct cbor_load_result result;
|
||||
cbor_item_t* item = cbor_load(buffer, length, &result);
|
||||
free(buffer);
|
||||
|
||||
if (result.error.code != CBOR_ERR_NONE) {
|
||||
printf(
|
||||
"There was an error while reading the input near byte %zu (read %zu "
|
||||
"bytes in total): ",
|
||||
result.error.position, result.read);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cJSON* cjson_item = cbor_to_cjson(item);
|
||||
char* json_string = cJSON_Print(cjson_item);
|
||||
printf("%s\n", json_string);
|
||||
free(json_string);
|
||||
fflush(stdout);
|
||||
|
||||
/* Deallocate the result */
|
||||
cbor_decref(&item);
|
||||
cJSON_Delete(cjson_item);
|
||||
|
||||
fclose(f);
|
||||
}
|
@ -7,7 +7,7 @@
|
||||
|
||||
/**
|
||||
* This code demonstrates how cJSON (https://github.com/DaveGamble/cJSON)
|
||||
* callbacks can be used in conjuction with the streaming parser to translate
|
||||
* callbacks can be used in conjunction with the streaming parser to translate
|
||||
* JSON to CBOR. Please note that cbor_builder_* APIs are internal and thus
|
||||
* subject to change.
|
||||
*
|
||||
@ -111,7 +111,7 @@ void cjson_cbor_stream_decode(cJSON *source,
|
||||
}
|
||||
|
||||
void usage(void) {
|
||||
printf("Usage: cjson [input JSON file]\n");
|
||||
printf("Usage: cjson2cbor [input JSON file]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
BIN
contrib/libcbor/examples/data/all_types.cbor
Normal file
BIN
contrib/libcbor/examples/data/all_types.cbor
Normal file
Binary file not shown.
@ -58,7 +58,7 @@ int main(int argc, char* argv[]) {
|
||||
case CBOR_ERR_SYNTAXERROR: {
|
||||
printf(
|
||||
"Syntactically malformed data -- see "
|
||||
"http://tools.ietf.org/html/rfc7049\n");
|
||||
"https://www.rfc-editor.org/info/std94\n");
|
||||
break;
|
||||
}
|
||||
case CBOR_ERR_NONE: {
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/bin/bash -eu
|
||||
#!/bin/bash -eux
|
||||
# Copyright 2019 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,6 +1,5 @@
|
||||
set(SOURCES cbor.c allocators.c cbor/streaming.c cbor/internal/encoders.c cbor/internal/builder_callbacks.c cbor/internal/loaders.c cbor/internal/memory_utils.c cbor/internal/stack.c cbor/internal/unicode.c cbor/encoding.c cbor/serialization.c cbor/arrays.c cbor/common.c cbor/floats_ctrls.c cbor/bytestrings.c cbor/callbacks.c cbor/strings.c cbor/maps.c cbor/tags.c cbor/ints.c)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(JoinPaths)
|
||||
include(CheckFunctionExists)
|
||||
set(CMAKE_SKIP_BUILD_RPATH FALSE)
|
||||
@ -49,3 +48,23 @@ install(FILES cbor.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libcbor.pc"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
configure_package_config_file(
|
||||
libcborConfig.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libcborConfig.cmake
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libcbor
|
||||
PATH_VARS CMAKE_INSTALL_INCLUDEDIR
|
||||
)
|
||||
write_basic_package_version_file(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libcborConfigVersion.cmake
|
||||
VERSION ${CBOR_VERSION}
|
||||
COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libcborConfig.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libcborConfigVersion.cmake
|
||||
DESTINATION
|
||||
${CMAKE_INSTALL_LIBDIR}/cmake/libcbor
|
||||
)
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "cbor/internal/builder_callbacks.h"
|
||||
#include "cbor/internal/loaders.h"
|
||||
|
||||
#pragma clang diagnostic push
|
||||
cbor_item_t *cbor_load(cbor_data source, size_t source_size,
|
||||
struct cbor_load_result *result) {
|
||||
/* Context stack */
|
||||
@ -289,7 +290,6 @@ cbor_item_t *cbor_copy(cbor_item_t *item) {
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#define __STDC_FORMAT_MACROS
|
||||
@ -301,89 +301,105 @@ static int _pow(int b, int ex) {
|
||||
return res;
|
||||
}
|
||||
|
||||
static void _cbor_type_marquee(FILE *out, char *label, int indent) {
|
||||
fprintf(out, "%*.*s[%s] ", indent, indent, " ", label);
|
||||
}
|
||||
|
||||
static void _cbor_nested_describe(cbor_item_t *item, FILE *out, int indent) {
|
||||
setlocale(LC_ALL, "");
|
||||
const int indent_offset = 4;
|
||||
switch (cbor_typeof(item)) {
|
||||
case CBOR_TYPE_UINT: {
|
||||
fprintf(out, "%*s[CBOR_TYPE_UINT] ", indent, " ");
|
||||
_cbor_type_marquee(out, "CBOR_TYPE_UINT", indent);
|
||||
fprintf(out, "Width: %dB, ", _pow(2, cbor_int_get_width(item)));
|
||||
fprintf(out, "Value: %" PRIu64 "\n", cbor_get_int(item));
|
||||
break;
|
||||
}
|
||||
case CBOR_TYPE_NEGINT: {
|
||||
fprintf(out, "%*s[CBOR_TYPE_NEGINT] ", indent, " ");
|
||||
_cbor_type_marquee(out, "CBOR_TYPE_NEGINT", indent);
|
||||
fprintf(out, "Width: %dB, ", _pow(2, cbor_int_get_width(item)));
|
||||
fprintf(out, "Value: -%" PRIu64 " -1\n", cbor_get_int(item));
|
||||
fprintf(out, "Value: -%" PRIu64 " - 1\n", cbor_get_int(item));
|
||||
break;
|
||||
}
|
||||
case CBOR_TYPE_BYTESTRING: {
|
||||
fprintf(out, "%*s[CBOR_TYPE_BYTESTRING] ", indent, " ");
|
||||
_cbor_type_marquee(out, "CBOR_TYPE_BYTESTRING", indent);
|
||||
if (cbor_bytestring_is_indefinite(item)) {
|
||||
fprintf(out, "Indefinite, with %zu chunks:\n",
|
||||
fprintf(out, "Indefinite, Chunks: %zu, Chunk data:\n",
|
||||
cbor_bytestring_chunk_count(item));
|
||||
for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++)
|
||||
_cbor_nested_describe(cbor_bytestring_chunks_handle(item)[i], out,
|
||||
indent + 4);
|
||||
indent + indent_offset);
|
||||
} else {
|
||||
fprintf(out, "Definite, length %zuB\n", cbor_bytestring_length(item));
|
||||
const unsigned char *data = cbor_bytestring_handle(item);
|
||||
fprintf(out, "Definite, Length: %zuB, Data:\n",
|
||||
cbor_bytestring_length(item));
|
||||
fprintf(out, "%*s", indent + indent_offset, " ");
|
||||
for (size_t i = 0; i < cbor_bytestring_length(item); i++)
|
||||
fprintf(out, "%02x", (int)(data[i] & 0xff));
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CBOR_TYPE_STRING: {
|
||||
fprintf(out, "%*s[CBOR_TYPE_STRING] ", indent, " ");
|
||||
_cbor_type_marquee(out, "CBOR_TYPE_STRING", indent);
|
||||
if (cbor_string_is_indefinite(item)) {
|
||||
fprintf(out, "Indefinite, with %zu chunks:\n",
|
||||
fprintf(out, "Indefinite, Chunks: %zu, Chunk data:\n",
|
||||
cbor_string_chunk_count(item));
|
||||
for (size_t i = 0; i < cbor_string_chunk_count(item); i++)
|
||||
_cbor_nested_describe(cbor_string_chunks_handle(item)[i], out,
|
||||
indent + 4);
|
||||
indent + indent_offset);
|
||||
} else {
|
||||
fprintf(out, "Definite, length %zuB, %zu codepoints\n",
|
||||
fprintf(out, "Definite, Length: %zuB, Codepoints: %zu, Data:\n",
|
||||
cbor_string_length(item), cbor_string_codepoint_count(item));
|
||||
/* Careful - this doesn't support multibyte characters! */
|
||||
/* Printing those is out of the scope of this demo :) */
|
||||
/* libICU is your friend */
|
||||
fprintf(out, "%*s", indent + 4, " ");
|
||||
/* XXX: no null at the end -> confused vprintf */
|
||||
fwrite(cbor_string_handle(item), (int)cbor_string_length(item), 1, out);
|
||||
fprintf(out, "%*s", indent + indent_offset, " ");
|
||||
// Note: The string is not escaped, whitespace and control character
|
||||
// will be printed in verbatim and take effect.
|
||||
fwrite(cbor_string_handle(item), sizeof(unsigned char),
|
||||
cbor_string_length(item), out);
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CBOR_TYPE_ARRAY: {
|
||||
fprintf(out, "%*s[CBOR_TYPE_ARRAY] ", indent, " ");
|
||||
_cbor_type_marquee(out, "CBOR_TYPE_ARRAY", indent);
|
||||
if (cbor_array_is_definite(item)) {
|
||||
fprintf(out, "Definite, size: %zu\n", cbor_array_size(item));
|
||||
fprintf(out, "Definite, Size: %zu, Contents:\n", cbor_array_size(item));
|
||||
} else {
|
||||
fprintf(out, "Indefinite, size: %zu\n", cbor_array_size(item));
|
||||
fprintf(out, "Indefinite, Size: %zu, Contents:\n",
|
||||
cbor_array_size(item));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < cbor_array_size(item); i++)
|
||||
_cbor_nested_describe(cbor_array_handle(item)[i], out, indent + 4);
|
||||
_cbor_nested_describe(cbor_array_handle(item)[i], out,
|
||||
indent + indent_offset);
|
||||
break;
|
||||
}
|
||||
case CBOR_TYPE_MAP: {
|
||||
fprintf(out, "%*s[CBOR_TYPE_MAP] ", indent, " ");
|
||||
_cbor_type_marquee(out, "CBOR_TYPE_MAP", indent);
|
||||
if (cbor_map_is_definite(item)) {
|
||||
fprintf(out, "Definite, size: %zu\n", cbor_map_size(item));
|
||||
fprintf(out, "Definite, Size: %zu, Contents:\n", cbor_map_size(item));
|
||||
} else {
|
||||
fprintf(out, "Indefinite, size: %zu\n", cbor_map_size(item));
|
||||
fprintf(out, "Indefinite, Size: %zu, Contents:\n", cbor_map_size(item));
|
||||
}
|
||||
|
||||
// TODO: Label and group keys and values
|
||||
for (size_t i = 0; i < cbor_map_size(item); i++) {
|
||||
_cbor_nested_describe(cbor_map_handle(item)[i].key, out, indent + 4);
|
||||
_cbor_nested_describe(cbor_map_handle(item)[i].value, out, indent + 4);
|
||||
fprintf(out, "%*sMap entry %zu\n", indent + indent_offset, " ", i);
|
||||
_cbor_nested_describe(cbor_map_handle(item)[i].key, out,
|
||||
indent + 2 * indent_offset);
|
||||
_cbor_nested_describe(cbor_map_handle(item)[i].value, out,
|
||||
indent + 2 * indent_offset);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CBOR_TYPE_TAG: {
|
||||
fprintf(out, "%*s[CBOR_TYPE_TAG] ", indent, " ");
|
||||
_cbor_type_marquee(out, "CBOR_TYPE_TAG", indent);
|
||||
fprintf(out, "Value: %" PRIu64 "\n", cbor_tag_value(item));
|
||||
_cbor_nested_describe(cbor_move(cbor_tag_item(item)), out, indent + 4);
|
||||
_cbor_nested_describe(cbor_move(cbor_tag_item(item)), out,
|
||||
indent + indent_offset);
|
||||
break;
|
||||
}
|
||||
case CBOR_TYPE_FLOAT_CTRL: {
|
||||
fprintf(out, "%*s[CBOR_TYPE_FLOAT_CTRL] ", indent, " ");
|
||||
_cbor_type_marquee(out, "CBOR_TYPE_FLOAT_CTRL", indent);
|
||||
if (cbor_float_ctrl_is_ctrl(item)) {
|
||||
if (cbor_is_bool(item))
|
||||
fprintf(out, "Bool: %s\n", cbor_get_bool(item) ? "true" : "false");
|
||||
@ -392,10 +408,10 @@ static void _cbor_nested_describe(cbor_item_t *item, FILE *out, int indent) {
|
||||
else if (cbor_is_null(item))
|
||||
fprintf(out, "Null\n");
|
||||
else
|
||||
fprintf(out, "Simple value %d\n", cbor_ctrl_value(item));
|
||||
fprintf(out, "Simple value: %d\n", cbor_ctrl_value(item));
|
||||
} else {
|
||||
fprintf(out, "Width: %dB, ", _pow(2, cbor_float_get_width(item)));
|
||||
fprintf(out, "value: %lf\n", cbor_float_get_float(item));
|
||||
fprintf(out, "Value: %lf\n", cbor_float_get_float(item));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ _CBOR_NODISCARD
|
||||
CBOR_EXPORT cbor_type cbor_typeof(
|
||||
const cbor_item_t *item); /* Will be inlined iff link-time opt is enabled */
|
||||
|
||||
/* Standard item types as described by the RFC */
|
||||
/* Standard CBOR Major item types */
|
||||
|
||||
/** Does the item have the appropriate major type?
|
||||
* @param item the item
|
||||
|
@ -67,14 +67,14 @@ void _cbor_builder_append(cbor_item_t *item,
|
||||
// Note: We use 0 and 1 subitems to distinguish between keys and values in
|
||||
// indefinite items
|
||||
if (ctx->stack->top->subitems % 2) {
|
||||
/* Odd record, this is a value */
|
||||
if (!_cbor_map_add_value(ctx->stack->top->item, item)) {
|
||||
ctx->creation_failed = true;
|
||||
cbor_decref(&item);
|
||||
break;
|
||||
}
|
||||
// Odd record, this is a value.
|
||||
ctx->creation_failed =
|
||||
!_cbor_map_add_value(ctx->stack->top->item, item);
|
||||
// Adding a value never fails since the memory is allocated when the
|
||||
// key is added
|
||||
CBOR_ASSERT(!ctx->creation_failed);
|
||||
} else {
|
||||
/* Even record, this is a key */
|
||||
// Even record, this is a key.
|
||||
if (!_cbor_map_add_key(ctx->stack->top->item, item)) {
|
||||
ctx->creation_failed = true;
|
||||
cbor_decref(&item);
|
||||
@ -256,18 +256,8 @@ void cbor_builder_string_callback(void *context, cbor_data data,
|
||||
uint64_t length) {
|
||||
struct _cbor_decoder_context *ctx = context;
|
||||
CHECK_LENGTH(ctx, length);
|
||||
struct _cbor_unicode_status unicode_status;
|
||||
uint64_t codepoint_count =
|
||||
_cbor_unicode_codepoint_count(data, length, &unicode_status);
|
||||
|
||||
if (unicode_status.status != _CBOR_UNICODE_OK) {
|
||||
ctx->syntax_error = true;
|
||||
return;
|
||||
}
|
||||
CBOR_ASSERT(codepoint_count <= length);
|
||||
|
||||
unsigned char *new_handle = _cbor_malloc(length);
|
||||
|
||||
if (new_handle == NULL) {
|
||||
ctx->creation_failed = true;
|
||||
return;
|
||||
@ -281,7 +271,6 @@ void cbor_builder_string_callback(void *context, cbor_data data,
|
||||
return;
|
||||
}
|
||||
cbor_string_set_handle(new_chunk, new_handle, length);
|
||||
new_chunk->metadata.string_metadata.codepoint_count = codepoint_count;
|
||||
|
||||
// If an indef string is on the stack, extend it (if it were closed, it would
|
||||
// have been popped). Handle any syntax errors upstream.
|
||||
@ -355,6 +344,8 @@ bool _cbor_is_indefinite(cbor_item_t *item) {
|
||||
case CBOR_TYPE_MAP:
|
||||
return cbor_map_is_indefinite(item);
|
||||
default:
|
||||
// Should never happen since a non-nested item cannot be on top of the
|
||||
// stack.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ uint64_t _cbor_load_uint64(const unsigned char *source) {
|
||||
#endif
|
||||
}
|
||||
|
||||
/* As per http://tools.ietf.org/html/rfc7049#appendix-D */
|
||||
/* As per https://www.rfc-editor.org/rfc/rfc8949.html#name-half-precision */
|
||||
float _cbor_decode_half(unsigned char *halfp) {
|
||||
int half = (halfp[0] << 8) + halfp[1];
|
||||
int exp = (half >> 10) & 0x1f;
|
||||
|
@ -21,7 +21,7 @@ bool _cbor_safe_to_multiply(size_t a, size_t b);
|
||||
_CBOR_NODISCARD
|
||||
bool _cbor_safe_to_add(size_t a, size_t b);
|
||||
|
||||
/** Adds `a` and `b`, propagating zeros and returing 0 on overflow. */
|
||||
/** Adds `a` and `b`, propagating zeros and returning 0 on overflow. */
|
||||
_CBOR_NODISCARD
|
||||
size_t _cbor_safe_signaling_add(size_t a, size_t b);
|
||||
|
||||
|
@ -66,12 +66,12 @@ uint32_t _cbor_unicode_decode(uint32_t* state, uint32_t* codep, uint32_t byte) {
|
||||
return *state;
|
||||
}
|
||||
|
||||
uint64_t _cbor_unicode_codepoint_count(cbor_data source, uint64_t source_length,
|
||||
struct _cbor_unicode_status* status) {
|
||||
size_t _cbor_unicode_codepoint_count(cbor_data source, size_t source_length,
|
||||
struct _cbor_unicode_status* status) {
|
||||
*status =
|
||||
(struct _cbor_unicode_status){.location = 0, .status = _CBOR_UNICODE_OK};
|
||||
uint32_t codepoint, state = UTF8_ACCEPT, res;
|
||||
uint64_t pos = 0, count = 0;
|
||||
size_t pos = 0, count = 0;
|
||||
|
||||
for (; pos < source_length; pos++) {
|
||||
res = _cbor_unicode_decode(&state, &codepoint, source[pos]);
|
||||
|
@ -19,12 +19,12 @@ enum _cbor_unicode_status_error { _CBOR_UNICODE_OK, _CBOR_UNICODE_BADCP };
|
||||
/** Signals unicode validation error and possibly its location */
|
||||
struct _cbor_unicode_status {
|
||||
enum _cbor_unicode_status_error status;
|
||||
uint64_t location;
|
||||
size_t location;
|
||||
};
|
||||
|
||||
_CBOR_NODISCARD
|
||||
uint64_t _cbor_unicode_codepoint_count(cbor_data source, uint64_t source_length,
|
||||
struct _cbor_unicode_status* status);
|
||||
size_t _cbor_unicode_codepoint_count(cbor_data source, size_t source_length,
|
||||
struct _cbor_unicode_status* status);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -103,6 +103,7 @@ bool _cbor_map_add_value(cbor_item_t *item, cbor_item_t *value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Add a more convenient API like add(item, key, val)
|
||||
bool cbor_map_add(cbor_item_t *item, struct cbor_pair pair) {
|
||||
CBOR_ASSERT(cbor_isa_map(item));
|
||||
if (!_cbor_map_add_key(item, pair.key)) return false;
|
||||
|
@ -437,23 +437,21 @@ struct cbor_decoder_result cbor_stream_decode(
|
||||
callbacks->indef_map_start(context);
|
||||
return result;
|
||||
}
|
||||
case 0xC0:
|
||||
/* Text date/time - RFC 3339 tag, fallthrough */
|
||||
case 0xC1:
|
||||
/* Epoch date tag, fallthrough */
|
||||
case 0xC2:
|
||||
/* Positive bignum tag, fallthrough */
|
||||
case 0xC3:
|
||||
/* Negative bignum tag, fallthrough */
|
||||
case 0xC4:
|
||||
/* Fraction, fallthrough */
|
||||
case 0xC5:
|
||||
/* Big float */
|
||||
{
|
||||
callbacks->tag(context, (uint64_t)(_cbor_load_uint8(source) -
|
||||
0xC0)); /* 0xC0 offset */
|
||||
return result;
|
||||
}
|
||||
/* See https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml for tag
|
||||
* assignment. All well-formed tags are processed regardless of validity
|
||||
* since maintaining the known mapping would be impractical.
|
||||
*
|
||||
* Moreover, even tags in the reserved "standard" range are not assigned
|
||||
* but may get assigned in the future (see e.g.
|
||||
* https://github.com/PJK/libcbor/issues/307), so processing all tags
|
||||
* improves forward compatibility.
|
||||
*/
|
||||
case 0xC0: /* Fallthrough */
|
||||
case 0xC1: /* Fallthrough */
|
||||
case 0xC2: /* Fallthrough */
|
||||
case 0xC3: /* Fallthrough */
|
||||
case 0xC4: /* Fallthrough */
|
||||
case 0xC5: /* Fallthrough */
|
||||
case 0xC6: /* Fallthrough */
|
||||
case 0xC7: /* Fallthrough */
|
||||
case 0xC8: /* Fallthrough */
|
||||
@ -468,13 +466,10 @@ struct cbor_decoder_result cbor_stream_decode(
|
||||
case 0xD1: /* Fallthrough */
|
||||
case 0xD2: /* Fallthrough */
|
||||
case 0xD3: /* Fallthrough */
|
||||
case 0xD4: /* Unassigned tag value */
|
||||
{
|
||||
return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR};
|
||||
}
|
||||
case 0xD5: /* Expected b64url conversion tag - fallthrough */
|
||||
case 0xD6: /* Expected b64 conversion tag - fallthrough */
|
||||
case 0xD7: /* Expected b16 conversion tag */
|
||||
case 0xD4: /* Fallthrough */
|
||||
case 0xD5: /* Fallthrough */
|
||||
case 0xD6: /* Fallthrough */
|
||||
case 0xD7: /* Fallthrough */
|
||||
{
|
||||
callbacks->tag(context, (uint64_t)(_cbor_load_uint8(source) -
|
||||
0xC0)); /* 0xC0 offset */
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "strings.h"
|
||||
#include <string.h>
|
||||
#include "internal/memory_utils.h"
|
||||
#include "internal/unicode.h"
|
||||
|
||||
cbor_item_t *cbor_new_definite_string(void) {
|
||||
cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t));
|
||||
@ -66,6 +67,15 @@ void cbor_string_set_handle(cbor_item_t *item,
|
||||
CBOR_ASSERT(cbor_string_is_definite(item));
|
||||
item->data = data;
|
||||
item->metadata.string_metadata.length = length;
|
||||
struct _cbor_unicode_status unicode_status;
|
||||
size_t codepoint_count =
|
||||
_cbor_unicode_codepoint_count(data, length, &unicode_status);
|
||||
CBOR_ASSERT(codepoint_count <= length);
|
||||
if (unicode_status.status == _CBOR_UNICODE_OK) {
|
||||
item->metadata.string_metadata.codepoint_count = codepoint_count;
|
||||
} else {
|
||||
item->metadata.string_metadata.codepoint_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
cbor_item_t **cbor_string_chunks_handle(const cbor_item_t *item) {
|
||||
|
@ -33,7 +33,8 @@ _CBOR_NODISCARD CBOR_EXPORT size_t cbor_string_length(const cbor_item_t *item);
|
||||
|
||||
/** The number of codepoints in this string
|
||||
*
|
||||
* Might differ from length if there are multibyte ones
|
||||
* Might differ from `cbor_string_length` if there are multibyte codepoints.
|
||||
* If the string data is not valid UTF-8, returns 0.
|
||||
*
|
||||
* @param item A string
|
||||
* @return The number of codepoints in this string
|
||||
@ -71,6 +72,8 @@ cbor_string_handle(const cbor_item_t *item);
|
||||
|
||||
/** Set the handle to the underlying string
|
||||
*
|
||||
* The data is assumed to be a valid UTF-8 string. If the string is non-empty
|
||||
* and invalid, `cbor_string_codepoint_count` will return 0.
|
||||
*
|
||||
* \rst
|
||||
* .. warning:: Using a pointer to a stack allocated constant is a common
|
||||
@ -144,7 +147,11 @@ _CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_indefinite_string(void);
|
||||
|
||||
/** Creates a new string and initializes it
|
||||
*
|
||||
* The `val` will be copied to a newly allocated block
|
||||
* The data from `val` will be copied to a newly allocated memory block.
|
||||
*
|
||||
* Note that valid UTF-8 strings do not contain null bytes, so this routine is
|
||||
* correct for all valid inputs. If the input is not guaranteed to be valid,
|
||||
* use `cbor_build_stringn` instead.
|
||||
*
|
||||
* @param val A null-terminated UTF-8 string
|
||||
* @return Reference to the new string item. The item's reference count is
|
||||
@ -155,10 +162,12 @@ _CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_string(const char *val);
|
||||
|
||||
/** Creates a new string and initializes it
|
||||
*
|
||||
* The `handle` will be copied to a newly allocated block
|
||||
* The data from `handle` will be copied to a newly allocated memory block.
|
||||
*
|
||||
* @param val A UTF-8 string, at least @p `length` long (excluding the null
|
||||
* byte)
|
||||
* All @p `length` bytes will be stored in the string, even if there are null
|
||||
* bytes or invalid UTF-8 sequences.
|
||||
*
|
||||
* @param val A UTF-8 string, at least @p `length` bytes long
|
||||
* @param length Length (in bytes) of the string passed in @p `val`.
|
||||
* @return Reference to the new string item. The item's reference count is
|
||||
* initialized to one.
|
||||
|
8
contrib/libcbor/src/libcborConfig.cmake.in
Normal file
8
contrib/libcbor/src/libcborConfig.cmake.in
Normal file
@ -0,0 +1,8 @@
|
||||
set(CBOR_VERSION @CBOR_VERSION@)
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
set_and_check(CBOR_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@")
|
||||
set_and_check(CBOR_INCLUDE_DIRS "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@")
|
||||
|
||||
check_required_components(libcbor)
|
@ -371,6 +371,30 @@ static void test_invalid_indef_break(void** _CBOR_UNUSED(_state)) {
|
||||
assert_true(res.error.code == CBOR_ERR_SYNTAXERROR);
|
||||
}
|
||||
|
||||
static void test_invalid_state_indef_break(void** _CBOR_UNUSED(_state)) {
|
||||
struct _cbor_stack stack = _cbor_stack_init();
|
||||
assert_non_null(_cbor_stack_push(&stack, cbor_new_int8(), /*subitems=*/0));
|
||||
struct _cbor_decoder_context context = {
|
||||
.creation_failed = false,
|
||||
.syntax_error = false,
|
||||
.root = NULL,
|
||||
.stack = &stack,
|
||||
};
|
||||
|
||||
cbor_builder_indef_break_callback(&context);
|
||||
|
||||
assert_false(context.creation_failed);
|
||||
assert_true(context.syntax_error);
|
||||
assert_size_equal(context.stack->size, 1);
|
||||
// The stack remains unchanged
|
||||
cbor_item_t* small_int = stack.top->item;
|
||||
assert_size_equal(cbor_refcount(small_int), 1);
|
||||
assert_true(cbor_isa_uint(small_int));
|
||||
|
||||
cbor_decref(&small_int);
|
||||
_cbor_stack_pop(&stack);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(test_default_callbacks),
|
||||
@ -388,6 +412,7 @@ int main(void) {
|
||||
cmocka_unit_test(test_append_array_failure),
|
||||
cmocka_unit_test(test_append_map_failure),
|
||||
cmocka_unit_test(test_invalid_indef_break),
|
||||
cmocka_unit_test(test_invalid_state_indef_break),
|
||||
};
|
||||
|
||||
cmocka_run_group_tests(tests, NULL, NULL);
|
||||
|
@ -218,6 +218,34 @@ static void test_serialize_definite_string(void **_CBOR_UNUSED(_state)) {
|
||||
cbor_decref(&item);
|
||||
}
|
||||
|
||||
static void test_serialize_definite_string_4b_header(
|
||||
void **_CBOR_UNUSED(_state)) {
|
||||
#if SIZE_MAX > UINT16_MAX
|
||||
cbor_item_t *item = cbor_new_definite_string();
|
||||
const size_t size = (size_t)UINT16_MAX + 1;
|
||||
unsigned char *data = malloc(size);
|
||||
memset(data, 0, size);
|
||||
cbor_string_set_handle(item, data, size);
|
||||
assert_size_equal(cbor_serialized_size(item), 1 + 4 + size);
|
||||
cbor_decref(&item);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_serialize_definite_string_8b_header(
|
||||
void **_CBOR_UNUSED(_state)) {
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
cbor_item_t *item = cbor_new_definite_string();
|
||||
const size_t size = (size_t)UINT32_MAX + 1;
|
||||
unsigned char *data = malloc(1);
|
||||
data[0] = '\0';
|
||||
cbor_string_set_handle(item, data, 1);
|
||||
// Pretend that we have a big item to avoid the huge malloc
|
||||
item->metadata.string_metadata.length = size;
|
||||
assert_size_equal(cbor_serialized_size(item), 1 + 8 + size);
|
||||
cbor_decref(&item);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_serialize_indefinite_string(void **_CBOR_UNUSED(_state)) {
|
||||
cbor_item_t *item = cbor_new_indefinite_string();
|
||||
cbor_item_t *chunk = cbor_new_definite_string();
|
||||
@ -242,6 +270,7 @@ static void test_serialize_indefinite_string(void **_CBOR_UNUSED(_state)) {
|
||||
static void test_serialize_string_no_space(void **_CBOR_UNUSED(_state)) {
|
||||
cbor_item_t *item = cbor_new_definite_string();
|
||||
unsigned char *data = malloc(12);
|
||||
memset(data, 0, 12);
|
||||
cbor_string_set_handle(item, data, 12);
|
||||
|
||||
assert_size_equal(cbor_serialize(item, buffer, 1), 0);
|
||||
@ -254,6 +283,7 @@ static void test_serialize_indefinite_string_no_space(
|
||||
cbor_item_t *item = cbor_new_indefinite_string();
|
||||
cbor_item_t *chunk = cbor_new_definite_string();
|
||||
unsigned char *data = malloc(256);
|
||||
memset(data, 0, 256);
|
||||
cbor_string_set_handle(chunk, data, 256);
|
||||
assert_true(cbor_string_add_chunk(item, cbor_move(chunk)));
|
||||
|
||||
@ -638,6 +668,8 @@ int main(void) {
|
||||
cmocka_unit_test(test_serialize_bytestring_no_space),
|
||||
cmocka_unit_test(test_serialize_indefinite_bytestring_no_space),
|
||||
cmocka_unit_test(test_serialize_definite_string),
|
||||
cmocka_unit_test(test_serialize_definite_string_4b_header),
|
||||
cmocka_unit_test(test_serialize_definite_string_8b_header),
|
||||
cmocka_unit_test(test_serialize_indefinite_string),
|
||||
cmocka_unit_test(test_serialize_string_no_space),
|
||||
cmocka_unit_test(test_serialize_indefinite_string_no_space),
|
||||
|
@ -613,9 +613,9 @@ static void test_int64_tag_decoding(void **_CBOR_UNUSED(_state)) {
|
||||
assert_minimum_input_size(9, int64_tag_data);
|
||||
}
|
||||
|
||||
unsigned char bad_tag_data[] = {0xC6};
|
||||
static void test_bad_tag_decoding(void **_CBOR_UNUSED(_state)) {
|
||||
assert_decoder_result(0, CBOR_DECODER_ERROR, decode(bad_tag_data, 1));
|
||||
unsigned char reserved_byte_data[] = {0xDC};
|
||||
static void test_reserved_byte_decoding(void **_CBOR_UNUSED(_state)) {
|
||||
assert_decoder_result(0, CBOR_DECODER_ERROR, decode(reserved_byte_data, 1));
|
||||
}
|
||||
|
||||
unsigned char float2_data[] = {0xF9, 0x7B, 0xFF};
|
||||
@ -729,7 +729,7 @@ int main(void) {
|
||||
stream_test(test_int16_tag_decoding),
|
||||
stream_test(test_int32_tag_decoding),
|
||||
stream_test(test_int64_tag_decoding),
|
||||
stream_test(test_bad_tag_decoding),
|
||||
stream_test(test_reserved_byte_decoding),
|
||||
|
||||
stream_test(test_float2_decoding),
|
||||
stream_test(test_float4_decoding),
|
||||
|
@ -30,7 +30,7 @@ static void test_float2(void **_CBOR_UNUSED(_state)) {
|
||||
assert_true(cbor_is_float(float_ctrl));
|
||||
assert_true(cbor_float_get_width(float_ctrl) == CBOR_FLOAT_16);
|
||||
assert_true(cbor_float_get_float2(float_ctrl) == 65504.0F);
|
||||
assert_true(fabs(cbor_float_get_float(float_ctrl) - 65504.0F) < eps);
|
||||
assert_float_equal(cbor_float_get_float(float_ctrl), 65504.0F, eps);
|
||||
cbor_decref(&float_ctrl);
|
||||
assert_null(float_ctrl);
|
||||
}
|
||||
@ -43,7 +43,7 @@ static void test_float4(void **_CBOR_UNUSED(_state)) {
|
||||
assert_true(cbor_is_float(float_ctrl));
|
||||
assert_true(cbor_float_get_width(float_ctrl) == CBOR_FLOAT_32);
|
||||
assert_true(cbor_float_get_float4(float_ctrl) == 100000.0F);
|
||||
assert_true(fabs(cbor_float_get_float(float_ctrl) - 100000.0F) < eps);
|
||||
assert_float_equal(cbor_float_get_float(float_ctrl), 100000.0F, eps);
|
||||
cbor_decref(&float_ctrl);
|
||||
assert_null(float_ctrl);
|
||||
}
|
||||
@ -58,6 +58,8 @@ static void test_float8(void **_CBOR_UNUSED(_state)) {
|
||||
assert_true(cbor_float_get_width(float_ctrl) == CBOR_FLOAT_64);
|
||||
// XXX: the cast prevents promotion to 80-bit floats on 32-bit x86
|
||||
assert_true(cbor_float_get_float8(float_ctrl) == (double)1.0e+300);
|
||||
// Not using `assert_double_equal` since CI has an old version of cmocka
|
||||
assert_true(fabs(cbor_float_get_float(float_ctrl) - (double)1.0e+300) < eps);
|
||||
cbor_decref(&float_ctrl);
|
||||
assert_null(float_ctrl);
|
||||
}
|
||||
|
@ -6,33 +6,200 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "assertions.h"
|
||||
#include "cbor.h"
|
||||
|
||||
unsigned char data[] = {0x8B, 0x01, 0x20, 0x5F, 0x41, 0x01, 0x41, 0x02,
|
||||
0xFF, 0x7F, 0x61, 0x61, 0x61, 0x62, 0xFF, 0x9F,
|
||||
0xFF, 0xA1, 0x61, 0x61, 0x61, 0x62, 0xC0, 0xBF,
|
||||
0xFF, 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB,
|
||||
0x85, 0x1F, 0xF6, 0xF7, 0xF5};
|
||||
|
||||
static void test_pretty_printer(void **_CBOR_UNUSED(_state)) {
|
||||
void assert_describe_result(cbor_item_t *item, char *expected_result) {
|
||||
#if CBOR_PRETTY_PRINTER
|
||||
// We know the expected size based on `expected_result`, but read everything
|
||||
// in order to get the full actual output in a useful error message.
|
||||
const size_t buffer_size = 512;
|
||||
FILE *outfile = tmpfile();
|
||||
struct cbor_load_result res;
|
||||
cbor_item_t *item = cbor_load(data, 37, &res);
|
||||
cbor_describe(item, outfile);
|
||||
cbor_decref(&item);
|
||||
|
||||
item = cbor_new_ctrl();
|
||||
cbor_set_ctrl(item, 1);
|
||||
cbor_describe(item, outfile);
|
||||
cbor_decref(&item);
|
||||
|
||||
rewind(outfile);
|
||||
// Treat string as null-terminated since cmocka doesn't have asserts
|
||||
// for explicit length strings.
|
||||
char *output = malloc(buffer_size);
|
||||
assert_non_null(output);
|
||||
size_t output_size = fread(output, sizeof(char), buffer_size, outfile);
|
||||
output[output_size] = '\0';
|
||||
assert_string_equal(output, expected_result);
|
||||
assert_true(feof(outfile));
|
||||
free(output);
|
||||
fclose(outfile);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_uint(void **_CBOR_UNUSED(_state)) {
|
||||
cbor_item_t *item = cbor_build_uint8(42);
|
||||
assert_describe_result(item, "[CBOR_TYPE_UINT] Width: 1B, Value: 42\n");
|
||||
cbor_decref(&item);
|
||||
}
|
||||
|
||||
static void test_negint(void **_CBOR_UNUSED(_state)) {
|
||||
cbor_item_t *item = cbor_build_negint16(40);
|
||||
assert_describe_result(item,
|
||||
"[CBOR_TYPE_NEGINT] Width: 2B, Value: -40 - 1\n");
|
||||
cbor_decref(&item);
|
||||
}
|
||||
|
||||
static void test_definite_bytestring(void **_CBOR_UNUSED(_state)) {
|
||||
unsigned char data[] = {0x01, 0x02, 0x03};
|
||||
cbor_item_t *item = cbor_build_bytestring(data, 3);
|
||||
assert_describe_result(item,
|
||||
"[CBOR_TYPE_BYTESTRING] Definite, Length: 3B, Data:\n"
|
||||
" 010203\n");
|
||||
cbor_decref(&item);
|
||||
}
|
||||
|
||||
static void test_indefinite_bytestring(void **_CBOR_UNUSED(_state)) {
|
||||
unsigned char data[] = {0x01, 0x02, 0x03};
|
||||
cbor_item_t *item = cbor_new_indefinite_bytestring();
|
||||
assert_true(cbor_bytestring_add_chunk(
|
||||
item, cbor_move(cbor_build_bytestring(data, 3))));
|
||||
assert_true(cbor_bytestring_add_chunk(
|
||||
item, cbor_move(cbor_build_bytestring(data, 2))));
|
||||
assert_describe_result(
|
||||
item,
|
||||
"[CBOR_TYPE_BYTESTRING] Indefinite, Chunks: 2, Chunk data:\n"
|
||||
" [CBOR_TYPE_BYTESTRING] Definite, Length: 3B, Data:\n"
|
||||
" 010203\n"
|
||||
" [CBOR_TYPE_BYTESTRING] Definite, Length: 2B, Data:\n"
|
||||
" 0102\n");
|
||||
cbor_decref(&item);
|
||||
}
|
||||
|
||||
static void test_definite_string(void **_CBOR_UNUSED(_state)) {
|
||||
char *string = "Hello!";
|
||||
cbor_item_t *item = cbor_build_string(string);
|
||||
assert_describe_result(
|
||||
item,
|
||||
"[CBOR_TYPE_STRING] Definite, Length: 6B, Codepoints: 6, Data:\n"
|
||||
" Hello!\n");
|
||||
cbor_decref(&item);
|
||||
}
|
||||
|
||||
static void test_indefinite_string(void **_CBOR_UNUSED(_state)) {
|
||||
char *string = "Hello!";
|
||||
cbor_item_t *item = cbor_new_indefinite_string();
|
||||
assert_true(
|
||||
cbor_string_add_chunk(item, cbor_move(cbor_build_string(string))));
|
||||
assert_true(
|
||||
cbor_string_add_chunk(item, cbor_move(cbor_build_string(string))));
|
||||
assert_describe_result(
|
||||
item,
|
||||
"[CBOR_TYPE_STRING] Indefinite, Chunks: 2, Chunk data:\n"
|
||||
" [CBOR_TYPE_STRING] Definite, Length: 6B, Codepoints: 6, Data:\n"
|
||||
" Hello!\n"
|
||||
" [CBOR_TYPE_STRING] Definite, Length: 6B, Codepoints: 6, Data:\n"
|
||||
" Hello!\n");
|
||||
cbor_decref(&item);
|
||||
}
|
||||
|
||||
static void test_multibyte_string(void **_CBOR_UNUSED(_state)) {
|
||||
// "Štěstíčko" in UTF-8
|
||||
char *string = "\xc5\xa0t\xc4\x9bst\xc3\xad\xc4\x8dko";
|
||||
cbor_item_t *item = cbor_build_string(string);
|
||||
assert_describe_result(
|
||||
item,
|
||||
"[CBOR_TYPE_STRING] Definite, Length: 13B, Codepoints: 9, Data:\n"
|
||||
" \xc5\xa0t\xc4\x9bst\xc3\xad\xc4\x8dko\n");
|
||||
cbor_decref(&item);
|
||||
}
|
||||
|
||||
static void test_definite_array(void **_CBOR_UNUSED(_state)) {
|
||||
cbor_item_t *item = cbor_new_definite_array(2);
|
||||
assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(1))));
|
||||
assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(2))));
|
||||
assert_describe_result(item,
|
||||
"[CBOR_TYPE_ARRAY] Definite, Size: 2, Contents:\n"
|
||||
" [CBOR_TYPE_UINT] Width: 1B, Value: 1\n"
|
||||
" [CBOR_TYPE_UINT] Width: 1B, Value: 2\n");
|
||||
cbor_decref(&item);
|
||||
}
|
||||
|
||||
static void test_indefinite_array(void **_CBOR_UNUSED(_state)) {
|
||||
cbor_item_t *item = cbor_new_indefinite_array();
|
||||
assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(1))));
|
||||
assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(2))));
|
||||
assert_describe_result(item,
|
||||
"[CBOR_TYPE_ARRAY] Indefinite, Size: 2, Contents:\n"
|
||||
" [CBOR_TYPE_UINT] Width: 1B, Value: 1\n"
|
||||
" [CBOR_TYPE_UINT] Width: 1B, Value: 2\n");
|
||||
cbor_decref(&item);
|
||||
}
|
||||
|
||||
static void test_definite_map(void **_CBOR_UNUSED(_state)) {
|
||||
cbor_item_t *item = cbor_new_definite_map(1);
|
||||
assert_true(cbor_map_add(
|
||||
item, (struct cbor_pair){.key = cbor_move(cbor_build_uint8(1)),
|
||||
.value = cbor_move(cbor_build_uint8(2))}));
|
||||
assert_describe_result(item,
|
||||
"[CBOR_TYPE_MAP] Definite, Size: 1, Contents:\n"
|
||||
" Map entry 0\n"
|
||||
" [CBOR_TYPE_UINT] Width: 1B, Value: 1\n"
|
||||
" [CBOR_TYPE_UINT] Width: 1B, Value: 2\n");
|
||||
cbor_decref(&item);
|
||||
}
|
||||
|
||||
static void test_indefinite_map(void **_CBOR_UNUSED(_state)) {
|
||||
cbor_item_t *item = cbor_new_indefinite_map();
|
||||
assert_true(cbor_map_add(
|
||||
item, (struct cbor_pair){.key = cbor_move(cbor_build_uint8(1)),
|
||||
.value = cbor_move(cbor_build_uint8(2))}));
|
||||
assert_describe_result(item,
|
||||
"[CBOR_TYPE_MAP] Indefinite, Size: 1, Contents:\n"
|
||||
" Map entry 0\n"
|
||||
" [CBOR_TYPE_UINT] Width: 1B, Value: 1\n"
|
||||
" [CBOR_TYPE_UINT] Width: 1B, Value: 2\n");
|
||||
cbor_decref(&item);
|
||||
}
|
||||
|
||||
static void test_tag(void **_CBOR_UNUSED(_state)) {
|
||||
cbor_item_t *item = cbor_build_tag(42, cbor_move(cbor_build_uint8(1)));
|
||||
assert_describe_result(item,
|
||||
"[CBOR_TYPE_TAG] Value: 42\n"
|
||||
" [CBOR_TYPE_UINT] Width: 1B, Value: 1\n");
|
||||
cbor_decref(&item);
|
||||
}
|
||||
|
||||
static void test_floats(void **_CBOR_UNUSED(_state)) {
|
||||
cbor_item_t *item = cbor_new_indefinite_array();
|
||||
assert_true(cbor_array_push(item, cbor_move(cbor_build_bool(true))));
|
||||
assert_true(
|
||||
cbor_array_push(item, cbor_move(cbor_build_ctrl(CBOR_CTRL_UNDEF))));
|
||||
assert_true(
|
||||
cbor_array_push(item, cbor_move(cbor_build_ctrl(CBOR_CTRL_NULL))));
|
||||
assert_true(cbor_array_push(item, cbor_move(cbor_build_ctrl(24))));
|
||||
assert_true(cbor_array_push(item, cbor_move(cbor_build_float4(3.14f))));
|
||||
assert_describe_result(
|
||||
item,
|
||||
"[CBOR_TYPE_ARRAY] Indefinite, Size: 5, Contents:\n"
|
||||
" [CBOR_TYPE_FLOAT_CTRL] Bool: true\n"
|
||||
" [CBOR_TYPE_FLOAT_CTRL] Undefined\n"
|
||||
" [CBOR_TYPE_FLOAT_CTRL] Null\n"
|
||||
" [CBOR_TYPE_FLOAT_CTRL] Simple value: 24\n"
|
||||
" [CBOR_TYPE_FLOAT_CTRL] Width: 4B, Value: 3.140000\n");
|
||||
cbor_decref(&item);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
const struct CMUnitTest tests[] = {cmocka_unit_test(test_pretty_printer)};
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(test_uint),
|
||||
cmocka_unit_test(test_negint),
|
||||
cmocka_unit_test(test_definite_bytestring),
|
||||
cmocka_unit_test(test_indefinite_bytestring),
|
||||
cmocka_unit_test(test_definite_string),
|
||||
cmocka_unit_test(test_indefinite_string),
|
||||
cmocka_unit_test(test_multibyte_string),
|
||||
cmocka_unit_test(test_definite_array),
|
||||
cmocka_unit_test(test_indefinite_array),
|
||||
cmocka_unit_test(test_definite_map),
|
||||
cmocka_unit_test(test_indefinite_map),
|
||||
cmocka_unit_test(test_tag),
|
||||
cmocka_unit_test(test_floats),
|
||||
};
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
|
@ -217,6 +217,22 @@ static void test_short_indef_string(void **_CBOR_UNUSED(_state)) {
|
||||
assert_null(string);
|
||||
}
|
||||
|
||||
static void test_invalid_utf(void **_CBOR_UNUSED(_state)) {
|
||||
/* 0x60 + 1 | 0xC5 (invalid unfinished 2B codepoint) */
|
||||
unsigned char string_data[] = {0x61, 0xC5};
|
||||
string = cbor_load(string_data, 2, &res);
|
||||
|
||||
assert_non_null(string);
|
||||
assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
|
||||
assert_true(cbor_isa_string(string));
|
||||
assert_size_equal(cbor_string_length(string), 1);
|
||||
assert_size_equal(cbor_string_codepoint_count(string), 0);
|
||||
assert_true(cbor_string_is_definite(string));
|
||||
assert_true(res.read == 2);
|
||||
|
||||
cbor_decref(&string);
|
||||
}
|
||||
|
||||
static void test_inline_creation(void **_CBOR_UNUSED(_state)) {
|
||||
string = cbor_build_string("Hello!");
|
||||
assert_memory_equal(cbor_string_handle(string), "Hello!", strlen("Hello!"));
|
||||
@ -275,6 +291,53 @@ static void test_add_chunk_reallocation_overflow(void **_CBOR_UNUSED(_state)) {
|
||||
cbor_decref(&string);
|
||||
}
|
||||
|
||||
static void test_set_handle(void **_CBOR_UNUSED(_state)) {
|
||||
string = cbor_new_definite_string();
|
||||
char *test_string = "Hello";
|
||||
unsigned char *string_data = malloc(strlen(test_string));
|
||||
memcpy(string_data, test_string, strlen(test_string));
|
||||
assert_ptr_not_equal(string_data, NULL);
|
||||
cbor_string_set_handle(string, string_data, strlen(test_string));
|
||||
|
||||
assert_ptr_equal(cbor_string_handle(string), string_data);
|
||||
assert_size_equal(cbor_string_length(string), 5);
|
||||
assert_size_equal(cbor_string_codepoint_count(string), 5);
|
||||
|
||||
cbor_decref(&string);
|
||||
}
|
||||
|
||||
static void test_set_handle_multibyte_codepoint(void **_CBOR_UNUSED(_state)) {
|
||||
string = cbor_new_definite_string();
|
||||
// "Štěstíčko" in UTF-8
|
||||
char *test_string = "\xc5\xa0t\xc4\x9bst\xc3\xad\xc4\x8dko";
|
||||
unsigned char *string_data = malloc(strlen(test_string));
|
||||
memcpy(string_data, test_string, strlen(test_string));
|
||||
assert_ptr_not_equal(string_data, NULL);
|
||||
cbor_string_set_handle(string, string_data, strlen(test_string));
|
||||
|
||||
assert_ptr_equal(cbor_string_handle(string), string_data);
|
||||
assert_size_equal(cbor_string_length(string), 13);
|
||||
assert_size_equal(cbor_string_codepoint_count(string), 9);
|
||||
|
||||
cbor_decref(&string);
|
||||
}
|
||||
|
||||
static void test_set_handle_invalid_utf(void **_CBOR_UNUSED(_state)) {
|
||||
string = cbor_new_definite_string();
|
||||
// Invalid multi-byte character (missing the second byte).
|
||||
char *test_string = "Test: \xc5";
|
||||
unsigned char *string_data = malloc(strlen(test_string));
|
||||
memcpy(string_data, test_string, strlen(test_string));
|
||||
assert_ptr_not_equal(string_data, NULL);
|
||||
cbor_string_set_handle(string, string_data, strlen(test_string));
|
||||
|
||||
assert_ptr_equal(cbor_string_handle(string), string_data);
|
||||
assert_size_equal(cbor_string_length(string), 7);
|
||||
assert_size_equal(cbor_string_codepoint_count(string), 0);
|
||||
|
||||
cbor_decref(&string);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(test_empty_string),
|
||||
@ -285,10 +348,14 @@ int main(void) {
|
||||
cmocka_unit_test(test_int32_string),
|
||||
cmocka_unit_test(test_int64_string),
|
||||
cmocka_unit_test(test_short_indef_string),
|
||||
cmocka_unit_test(test_invalid_utf),
|
||||
cmocka_unit_test(test_inline_creation),
|
||||
cmocka_unit_test(test_string_creation),
|
||||
cmocka_unit_test(test_string_add_chunk),
|
||||
cmocka_unit_test(test_add_chunk_reallocation_overflow),
|
||||
cmocka_unit_test(test_set_handle),
|
||||
cmocka_unit_test(test_set_handle_multibyte_codepoint),
|
||||
cmocka_unit_test(test_set_handle_invalid_utf),
|
||||
};
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
|
@ -102,6 +102,28 @@ static void test_nested_tag(void **_CBOR_UNUSED(_state)) {
|
||||
assert_null(nested_tag);
|
||||
}
|
||||
|
||||
static void test_all_tag_values_supported(void **_CBOR_UNUSED(_state)) {
|
||||
/* Test all items in the protected range of
|
||||
* https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml */
|
||||
for (int64_t tag_value = 0; tag_value <= 32767; tag_value++) {
|
||||
cbor_item_t *tag_item =
|
||||
cbor_build_tag(tag_value, cbor_move(cbor_build_uint8(42)));
|
||||
unsigned char *serialized_tag;
|
||||
size_t serialized_tag_size =
|
||||
cbor_serialize_alloc(tag_item, &serialized_tag, NULL);
|
||||
assert_true(serialized_tag_size > 0);
|
||||
tag = cbor_load(serialized_tag, serialized_tag_size, &res);
|
||||
assert_true(res.read == serialized_tag_size);
|
||||
assert_true(cbor_typeof(tag) == CBOR_TYPE_TAG);
|
||||
assert_true(cbor_tag_value(tag) == tag_value);
|
||||
cbor_decref(&tag);
|
||||
assert_null(tag);
|
||||
cbor_decref(&tag_item);
|
||||
assert_null(tag_item);
|
||||
free(serialized_tag);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_build_tag(void **_CBOR_UNUSED(_state)) {
|
||||
tag = cbor_build_tag(1, cbor_move(cbor_build_uint8(42)));
|
||||
|
||||
@ -134,6 +156,7 @@ int main(void) {
|
||||
cmocka_unit_test(test_int32_tag),
|
||||
cmocka_unit_test(test_int64_tag),
|
||||
cmocka_unit_test(test_nested_tag),
|
||||
cmocka_unit_test(test_all_tag_values_supported),
|
||||
cmocka_unit_test(test_build_tag),
|
||||
cmocka_unit_test(test_build_tag_failure),
|
||||
cmocka_unit_test(test_tag_creation),
|
||||
|
@ -29,7 +29,7 @@ void finalize_mock_malloc(void) {
|
||||
free(expectations);
|
||||
}
|
||||
|
||||
void print_backtrace() {
|
||||
void print_backtrace(void) {
|
||||
#if HAS_EXECINFO
|
||||
void *buffer[128];
|
||||
int frames = backtrace(buffer, 128);
|
||||
|
Loading…
Reference in New Issue
Block a user