Merge remote-tracking branch 'upstream/master'
diff --git a/.appveyor.yml b/.appveyor.yml
new file mode 100644
index 0000000..945cc33
--- /dev/null
+++ b/.appveyor.yml
@@ -0,0 +1,26 @@
+image:
+ - Visual Studio 2019
+
+platform:
+ - x64
+
+configuration:
+ - release
+ - debug
+
+environment:
+ matrix:
+ - OPTIONS: -DCN_CBOR_USE_CONTEXT=ON
+ - OPTIONS: -DCN_CBOR_USE_CONTEXT=OFF
+ - OPTIONS: -DCN_CBOR_NO_FLOATS=ON
+ - OPTIONS: -DCN_CBOR_ALIGN_READS=ON
+
+before_build:
+ - cmake -G "Visual Studio 16 2019" -DCN_CBOR_FATAL_WARNINGS=OFF %OPTIONS%
+
+build:
+ project: $(APPVEYOR_BUILD_FOLDER)\$(APPVEYOR_PROJECT_NAME).sln
+
+test_script:
+ - cd dist\test\%CONFIGURATION%
+ - cbor_test.exe
diff --git a/.gitignore b/.gitignore
index 2eef09e..241e782 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,30 @@
new.out
*.o
build
+Testing/Temporary
+*.pc
+
+# Emacs temp files
+*~
+.#*
+*#
+
+# Visual Stdio build directories
+Debug
+Release
+v16
+*.sln
+*.vcxproj
+*.vcxproj.filters
+*.vcxproj.user
+*.VC.db
+*.VC.opendb
+/.vscode/
+
+# Output of CMake
+CMakeCache.txt
+CMakeFiles
+Makefile
+*.cmake
+install_manifest.txt
+*.tcl
diff --git a/.mbedignore b/.mbedignore
new file mode 100644
index 0000000..b335ab6
--- /dev/null
+++ b/.mbedignore
@@ -0,0 +1,2 @@
+test/*
+cmake/*
diff --git a/.travis.yml b/.travis.yml
index 1d16cc7..8fe596f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,8 +1,13 @@
language: c
compiler:
-- clang
-- gcc
-sudo: false
+ - clang
+ - gcc
+
+env:
+ - OPTIONS=-DCN_CBOR_USE_CONTEXT=OFF
+ - OPTIONS=-DCN_CBOR_USE_CONTEXT=ON
+ - OPTIONS=-DCN_CBOR_NO_FLOATS=ON
+
addons:
apt:
sources:
@@ -12,6 +17,3 @@
- cmake-data
script:
- "./build.sh all test"
-notifications:
- slack:
- secure: WdgYxQrnFR5eu/eKygPuLjlFsuZxD9m2PLRWTLT85aj+18Gp2ooPjnI9UFdb1xY87+4InhWk6PvQU35j4bG0etPQtX+0H4T4Zdk/aD6KxgJBHIYGqtfZUMmdFfVpUH9cCPx99Jjw81mhKrxM+6rXiZdiWXuNhvbJOApRT6uxE2k=
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e076dc8..5ff9a59 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,137 +1,252 @@
-#
-#
-# top level build file for cn-cbor
+cmake_minimum_required(VERSION 3.0.0)
-## prepare CMAKE
-cmake_minimum_required ( VERSION 3.0.0 )
-
-set ( VERSION_MAJOR 0 CACHE STRING "Project major version number")
-set ( VERSION_MINOR "1" CACHE STRING "Project minor version number" )
-set ( VERSION_PATCH "0" CACHE STRING "Project patch version number" )
-set ( CN_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}" )
+set(VERSION_MAJOR
+ 1
+ CACHE STRING "Project major version number")
+set(VERSION_MINOR
+ "1"
+ CACHE STRING "Project minor version number")
+set(VERSION_PATCH
+ "0"
+ CACHE STRING "Project patch version number")
+set(CN_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
mark_as_advanced(VERSION_MAJOR VERSION_MINOR VERSION_PATCH CN_VERSION)
-project ( "cn-cbor" VERSION "${CN_VERSION}")
+project("cn-cbor" VERSION "${CN_VERSION}")
-find_package(Doxygen)
+# ##############################################################################
+# OPTIONS
+# ##############################################################################
-## setup options
-option ( use_context "Use context pointer for CBOR functions" OFF )
-option ( verbose "Produce verbose makefile output" OFF )
-option ( optimize "Optimize for size" OFF )
-option ( fatal_warnings "Treat build warnings as errors" ON )
-option ( coveralls "Generate coveralls data" ON )
-option ( coveralls_send "Send data to coveralls site" OFF )
-option ( build_docs "Create docs using Doxygen" ${DOXYGEN_FOUND} )
-option ( no_floats "Build without floating point support" OFF )
-option ( align_reads "Use memcpy in ntoh*p()" OFF )
+option(CN_CBOR_USE_CONTEXT "Use context pointer for CBOR functions" OFF)
+option(CN_CBOR_VERBOSE "Produce verbose makefile output" OFF)
+option(CN_CBOR_OPTIMIZE "Optimize for size" OFF)
+option(CN_CBOR_FATAL_WARNINGS "Treat build warnings as errors" ON)
+option(CN_CBOR_COVERALLS "Generate coveralls data" ON)
+option(CN_CBOR_COVERALLS_SEND "Send data to coveralls site" OFF)
+option(CN_CBOR_BUILD_DOCS "Create docs using Doxygen" OFF)
+option(CN_CBOR_BUILD_TESTS "Create tests" ON)
+option(CN_CBOR_NO_FLOATS "Build without floating point support" OFF)
+option(CN_CBOR_ALIGN_READS "Use memcpy in ntoh*p()" OFF)
-set ( dist_dir ${CMAKE_BINARY_DIR}/dist )
-set ( prefix ${CMAKE_INSTALL_PREFIX} )
-set ( exec_prefix ${CMAKE_INSTALL_PREFIX}/bin )
-set ( libdir ${CMAKE_INSTALL_PREFIX}/lib )
-set ( includedir ${CMAKE_INSTALL_PREFIX}/include )
+set(dist_dir ${CMAKE_BINARY_DIR}/dist)
+set(prefix ${CMAKE_INSTALL_PREFIX})
+set(exec_prefix ${CMAKE_INSTALL_PREFIX}/bin)
+set(libdir ${CMAKE_INSTALL_PREFIX}/lib)
+set(includedir ${CMAKE_INSTALL_PREFIX}/include)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cn-cbor.pc.in
${CMAKE_CURRENT_BINARY_DIR}/cn-cbor.pc @ONLY)
-install (FILES ${CMAKE_CURRENT_BINARY_DIR}/cn-cbor.pc DESTINATION lib/pkgconfig )
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cn-cbor.pc DESTINATION lib/pkgconfig)
-set ( package_prefix "${CMAKE_PACKAGE_NAME}-${CMAKE_SYSTEM_NAME}" )
+set(package_prefix "${CMAKE_PACKAGE_NAME}-${CMAKE_SYSTEM_NAME}")
-set ( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${dist_dir}/bin )
-set ( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${dist_dir}/lib )
-set ( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${dist_dir}/lib )
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${dist_dir}/bin)
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${dist_dir}/lib)
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${dist_dir}/lib)
-if (NOT CMAKE_BUILD_TYPE)
- if ( optimize )
- set ( CMAKE_BUILD_TYPE MinSizeRel )
- set ( coveralls OFF )
- set ( coveralls_send OFF )
- else ()
- set ( CMAKE_BUILD_TYPE Debug )
- endif ()
+if(NOT CMAKE_BUILD_TYPE)
+ if(CN_CBOR_OPTIMIZE)
+ set(CMAKE_BUILD_TYPE MinSizeRel)
+ set(CN_CBOR_COVERALLS OFF)
+ set(CN_CBOR_COVERALLS_SEND OFF)
+ else()
+ set(CMAKE_BUILD_TYPE Debug)
+ endif()
endif()
-message ( "Build type: ${CMAKE_BUILD_TYPE}" )
-
-if ( CMAKE_C_COMPILER_ID STREQUAL "GNU" OR
- CMAKE_C_COMPILER_ID MATCHES "Clang" )
- message ( STATUS "adding GCC/Clang options ")
- add_definitions ( -std=gnu99 -Wall -Wextra -pedantic )
- if ( fatal_warnings )
- add_definitions ( -Werror )
- endif ()
- if ( optimize )
- add_definitions ( -Os )
- endif ()
-elseif ( MSVC )
- add_definitions ( /W3 )
- if ( fatal_warnings )
- add_definitions ( /WX )
- endif ()
-else ()
- message ( FATAL_ERROR "unhandled compiler id: ${CMAKE_C_COMPILER_ID}" )
-endif ()
-
-if ( no_floats )
- add_definitions(-DCBOR_NO_FLOAT)
+if(MSVC)
+ set(CN_CBOR_COVERALLS OFF)
endif()
-if ( verbose )
- set ( CMAKE_VERBOSE_MAKEFILE ON )
-endif ()
+message("Build type: ${CMAKE_BUILD_TYPE}")
-## include the parts
-add_subdirectory ( include )
-add_subdirectory ( src )
-add_subdirectory ( test )
+if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang")
+ message(STATUS "adding GCC/Clang options ")
+ add_definitions(-std=gnu99 -Wall -Wextra -pedantic)
+ if(CN_CBOR_FATAL_WARNINGS)
+ add_definitions(-Werror)
+ endif()
+ if(CN_CBOR_OPTIMIZE)
+ add_definitions(-Os)
+ endif()
+elseif(MSVC)
+ add_definitions(/W3)
+ if(CN_CBOR_FATAL_WARNINGS)
+ add_definitions(/WX)
+ endif()
+else()
+ message(FATAL_ERROR "unhandled compiler id: ${CMAKE_C_COMPILER_ID}")
+endif()
-install (FILES LICENSE README.md DESTINATION .)
+if(CN_CBOR_NO_FLOATS)
+ add_definitions(-DCBOR_NO_FLOAT)
+endif()
-## setup packaging
-set ( CPACK_GENERATOR "TGZ" )
-set ( CPACK_PACKAGE_VERSION "${PROJECT_VERSION}" )
-set ( CPACK_SOURCE_GENERATOR "TGZ" )
-set ( CPACK_SOURCE_IGNORE_FILES "/\\\\.git/" )
-file(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/.gitignore igs)
-foreach (ig IN ITEMS ${igs})
- # remove comments
- string ( REGEX REPLACE "^\\s*#.*" "" ig "${ig}")
- # remove any other whitespace
- string ( STRIP "${ig}" ig)
- # anything left?
- if (ig)
- # dots are literal
- string ( REPLACE "." "\\\\." ig "${ig}" )
- # stars are on thars
- string ( REPLACE "*" ".*" ig "${ig}" )
- list ( APPEND CPACK_SOURCE_IGNORE_FILES "/${ig}/" )
- endif()
-endforeach()
+if(CN_CBOR_VERBOSE)
+ set(CMAKE_VERBOSE_MAKEFILE ON)
+endif()
-set ( CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/README.md )
-set ( CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE" )
+# ##############################################################################
+# LIBRARY
+# ##############################################################################
-include ( CPack )
-include ( CTest )
+set(cbor_srcs src/cn-cbor.c src/cn-create.c src/cn-encoder.c src/cn-error.c
+ src/cn-get.c src/cn-print.c)
+
+if(CN_CBOR_ALIGN_READS)
+ add_definitions(-DCBOR_ALIGN_READS)
+endif()
+if(CN_CBOR_USE_CONTEXT)
+ add_definitions(-DUSE_CBOR_CONTEXT)
+endif()
+# default is static, can be shared if -DBUILD_SHARED_LIBS=ON passed to cmake
+add_library(${PROJECT_NAME})
+target_sources(${PROJECT_NAME} PRIVATE include/cn-cbor/cn-cbor.h ${cbor_srcs})
+target_include_directories(
+ ${PROJECT_NAME}
+ PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
+ PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src)
+if(MSVC)
+ message("test: ${BUILD_SHARED_LIBS}")
+ message("CN_CBOR_VERBOSE: ${CN_CBOR_VERBOSE}")
+ target_link_libraries(${PROJECT_NAME} ws2_32)
+endif()
+add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake)
-include ( LCov )
+if(CN_CBOR_COVERALLS)
+ include(Coveralls)
+ coveralls_turn_on_coverage()
-if (build_docs)
- if(NOT DOXYGEN_FOUND)
- message(FATAL_ERROR "Doxygen is needed to build the documentation.")
- endif()
+ set(COVERAGE_SRCS "")
+ foreach(S ${cbor_srcs})
+ get_filename_component(S_ABS ${S} ABSOLUTE)
+ list(APPEND COVERAGE_SRCS ${S_ABS})
+ endforeach()
+ # Create the coveralls target.
+ coveralls_setup("${COVERAGE_SRCS}" ${CN_CBOR_COVERALLS_SEND} # If we should upload.
+ )
+
+ # add_dependencies(CN_CBOR_COVERALLS, all)
+endif()
+
+if(NOT MSVC)
+ add_custom_target(
+ size
+ COMMAND echo "${CMAKE_BINARY_DIR}/src/CMakeFiles/cn-cbor.dir/cn-cbor.c.o"
+ COMMAND size "${CMAKE_BINARY_DIR}/src/CMakeFiles/cn-cbor.dir/cn-cbor.c.o"
+ COMMAND size -m "${CMAKE_BINARY_DIR}/src/CMakeFiles/cn-cbor.dir/cn-cbor.c.o"
+ DEPENDS cn-cbor
+ COMMENT "Output the size of the parse routine")
+endif(NOT MSVC)
+
+# ##############################################################################
+# DOCS
+# ##############################################################################
+
+if(CN_CBOR_BUILD_DOCS)
+ find_package(Doxygen)
+
+ if(NOT DOXYGEN_FOUND)
+ message(WARNING "Doxygen is needed to build the documentation.")
+ else()
set(doxyfile_in ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in)
set(doxyfile ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
configure_file(${doxyfile_in} ${doxyfile} @ONLY)
- add_custom_target(doc
- COMMAND ${DOXYGEN_EXECUTABLE} ${doxyfile}
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- COMMENT "Generating API documentation with Doxygen"
- VERBATIM)
+ add_custom_target(
+ doc
+ COMMAND ${DOXYGEN_EXECUTABLE} ${doxyfile}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMENT "Generating API documentation with Doxygen"
+ VERBATIM)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html DESTINATION share/doc)
+ endif()
endif()
+
+# ##############################################################################
+# TESTS
+# ##############################################################################
+
+if(CN_CBOR_BUILD_TESTS)
+ include(CTest)
+ add_subdirectory(test)
+ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake)
+ include(LCov)
+endif()
+
+# ##############################################################################
+# PACKAGING
+# ##############################################################################
+
+set(CPACK_GENERATOR "TGZ")
+set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
+set(CPACK_SOURCE_GENERATOR "TGZ")
+set(CPACK_SOURCE_IGNORE_FILES "/\\\\.git/")
+file(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/.gitignore igs)
+foreach(ig IN ITEMS ${igs})
+ # remove comments
+ string(REGEX REPLACE "^\\s*#.*" "" ig "${ig}")
+ # remove any other whitespace
+ string(STRIP "${ig}" ig)
+ # anything left?
+ if(ig)
+ # dots are literal
+ string(REPLACE "." "\\\\." ig "${ig}")
+ # stars are on thars
+ string(REPLACE "*" ".*" ig "${ig}")
+ list(APPEND CPACK_SOURCE_IGNORE_FILES "/${ig}/")
+ endif()
+endforeach()
+
+set(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/README.md)
+set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
+
+include(CPack)
+
+# ##############################################################################
+# INSTALL
+# ##############################################################################
+
+include(GNUInstallDirs)
+include(CMakePackageConfigHelpers)
+
+install(FILES LICENSE README.md DESTINATION .)
+set(CN_CBOR_CONFIG_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
+
+install(
+ TARGETS ${PROJECT_NAME}
+ EXPORT ${PROJECT_NAME}Targets
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib)
+
+install(
+ EXPORT ${PROJECT_NAME}Targets
+ DESTINATION ${CN_CBOR_CONFIG_INSTALL_DIR}
+ NAMESPACE ${PROJECT_NAME}::
+ COMPONENT dev)
+
+configure_package_config_file(cmake/Config.cmake.in ${PROJECT_NAME}Config.cmake
+ INSTALL_DESTINATION ${CN_CBOR_CONFIG_INSTALL_DIR})
+write_basic_package_version_file(${PROJECT_NAME}ConfigVersion.cmake
+ COMPATIBILITY SameMajorVersion)
+install(
+ FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
+ DESTINATION ${CN_CBOR_CONFIG_INSTALL_DIR}
+ COMPONENT dev)
+
+install(
+ DIRECTORY include/
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+ COMPONENT dev
+ FILES_MATCHING
+ PATTERN "*.h")
+install(
+ TARGETS cn-cbor
+ LIBRARY DESTINATION lib
+ ARCHIVE DESTINATION lib
+ RUNTIME DESTINATION bin)
diff --git a/README.md b/README.md
index 4b57f09..34fa411 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[![Build Status](https://travis-ci.org/cabo/cn-cbor.png?branch=master)](https://travis-ci.org/cabo/cn-cbor)
+[![Build Status](https://travis-ci.org/jimsch/cn-cbor.png?branch=master)](https://travis-ci.org/jimsch/cn-cbor)
# cn-cbor: A constrained node implementation of CBOR in C
@@ -48,16 +48,47 @@
Building with `cmake`:
- ./build.sh
-
-Building including testing:
-
- ./build.sh all test
+```sh
+mkdir build
+cd build
+cmake ..
+cmake --build . -- all
+```
Generating a test coverage report (requires lcov[^1]; result in `build/lcov/index.html`):
- ./build.sh all coveralls coverage_report
-
-License: MIT
+```sh
+rm -rf build
+mkdir build
+cd build
+cmake .. -DCN_CBOR_COVERALLS_SEND=ON
+cmake --build . -- all coveralls coverage_report
+```
[^1]: Installation with homebrew: `brew install lcov`
+
+## Consuming
+
+### With cmake
+
+find_package
+```cmake
+find_package(cn-cbor)
+add_executable(myapp main.cpp)
+target_link_libraries(myapp cn-cbor::cn-cbor)
+```
+
+add_subdirectory
+```cmake
+add_subdirectory(vendor/cn-cbor)
+add_executable(myapp main.cpp)
+target_link_libraries(myapp cn-cbor::cn-cbor)
+```
+
+### With Conan
+
+This package is available in the [conan center](https://conan.io/center/cn-cbor/1.0.0)
+
+add `cn-cbor/[>=1.0.0]` to you conan file
+
+License: MIT
diff --git a/build.sh b/build.sh
index 69dd2e9..0da9e18 100755
--- a/build.sh
+++ b/build.sh
@@ -2,4 +2,4 @@
if [ ! -d "build" ]; then
mkdir build
fi
-cd build && cmake .. && make $*
+cd build && cmake .. $OPTIONS && make $*
diff --git a/cmake/Config.cmake.in b/cmake/Config.cmake.in
new file mode 100644
index 0000000..9c15f36
--- /dev/null
+++ b/cmake/Config.cmake.in
@@ -0,0 +1,4 @@
+@PACKAGE_INIT@
+
+include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
+check_required_components("@PROJECT_NAME@")
diff --git a/conanfile.py b/conanfile.py
new file mode 100644
index 0000000..e1664ba
--- /dev/null
+++ b/conanfile.py
@@ -0,0 +1,63 @@
+import os
+from conans import ConanFile, CMake, tools
+
+
+class CnCborConan(ConanFile):
+ name = "cn-cbor"
+ version = "20200227"
+ license = "BSD"
+ url = "https://github.com/cose-wg/cn-cbor"
+ description = """A constrained node implementation of CBOR in C"""
+ topics = ("cn-cbor")
+ settings = "os", "compiler", "build_type", "arch"
+ options = {
+ "shared": [True, False],
+ }
+ default_options = {
+ "shared": False,
+ }
+ generators = "cmake"
+
+ _cmake = None
+
+ @property
+ def _source_subfolder(self):
+ return "source_subfolder"
+
+ @property
+ def _build_subfolder(self):
+ return "build_subfolder"
+
+ def source(self):
+ self.run(
+ "git clone git@github.com:jimsch/cn-cbor.git")
+ os.rename("cn-cbor", self._source_subfolder)
+
+ def configure(self):
+ del self.settings.compiler.libcxx
+ del self.settings.compiler.cppstd
+
+ def _configure_cmake(self):
+ if not self._cmake:
+ self._cmake = CMake(self)
+ self._cmake.definitions["CN_CBOR_BUILD_TESTS"] = False
+ self._cmake.definitions["CN_CBOR_BUILD_DOCS"] = False
+ self._cmake.definitions["CN_CBOR_COVERALLS"] = False
+ self._cmake.configure(
+ source_folder=self._source_subfolder, build_folder=self._build_subfolder)
+
+ return self._cmake
+
+ def build(self):
+ cmake = self._configure_cmake()
+ cmake.build()
+
+ def package(self):
+ cmake = self._configure_cmake()
+ cmake.install()
+
+ def package_info(self):
+ self.cpp_info.libs = tools.collect_libs(self)
+ self.cpp_info.name = "cn-cbor"
+ if self.settings.os == "Linux":
+ self.cpp_info.system_libs = ["m"]
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
deleted file mode 100644
index 898676a..0000000
--- a/include/CMakeLists.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-install ( DIRECTORY ../include DESTINATION .
- PATTERN CMakeLists.txt EXCLUDE )
diff --git a/include/cn-cbor/cn-cbor.h b/include/cn-cbor/cn-cbor.h
index 187a55c..2dceae0 100644
--- a/include/cn-cbor/cn-cbor.h
+++ b/include/cn-cbor/cn-cbor.h
@@ -8,6 +8,22 @@
#ifndef CN_CBOR_H
#define CN_CBOR_H
+#ifdef __MBED__
+#include <stddef.h>
+#endif
+
+#ifndef MYLIB_EXPORT
+#if defined (_WIN32)
+#if defined(CN_CBOR_IS_DLL)
+#define MYLIB_EXPORT __declspec(dllimport)
+#else
+#define MYLIB_EXPORT
+#endif /* CN_CBOR_IS_DLL */
+#else /* defined (_WIN32) */
+#define MYLIB_EXPORT
+#endif
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -17,7 +33,21 @@
#include <stdbool.h>
#include <stdint.h>
+#ifdef _MSC_VER
+#include <WinSock2.h>
+typedef signed long ssize_t;
+#else
+#ifndef __MBED__
#include <unistd.h>
+#else
+#ifndef RETARGET_H
+#ifndef _SSIZE_T_DECLARED
+typedef signed long ssize_t;
+#define _SSIZE_T_DECLARED
+#endif
+#endif
+#endif
+#endif
/**
* All of the different kinds of CBOR values.
@@ -51,10 +81,12 @@
CN_CBOR_TAG,
/** Simple value, other than the defined ones */
CN_CBOR_SIMPLE,
+#ifndef CBOR_NO_FLOAT
/** Doubles, floats, and half-floats */
CN_CBOR_DOUBLE,
/** Floats, and half-floats */
CN_CBOR_FLOAT,
+#endif
/** An error has occurred */
CN_CBOR_INVALID
} cn_cbor_type;
@@ -89,19 +121,37 @@
/** CN_CBOR_TEXT */
const char* str;
/** CN_CBOR_INT */
+#ifdef _MSC_VER
+ int64_t sint;
+#else
long sint;
+#endif
/** CN_CBOR_UINT */
+#ifdef _MSC_VER
+ uint64_t uint;
+#else
unsigned long uint;
+#endif
+#ifndef CBOR_NO_FLOAT
/** CN_CBOR_DOUBLE */
double dbl;
/** CN_CBOR_FLOAT */
float f;
+#endif
/** for use during parsing */
- unsigned long count;
+#ifdef _MSC_VER
+ uint64_t count;
+#else
+ unsigned long count;
+#endif
} v; /* TBD: optimize immediate */
/** Number of children.
* @note: for maps, this is 2x the number of entries */
+#ifdef _MSC_VER
+ size_t length;
+#else
int length;
+#endif
/** The first child value */
struct cn_cbor* first_child;
/** The last child value */
@@ -149,6 +199,7 @@
*
* @todo: turn into a function to make the type safety more clear?
*/
+MYLIB_EXPORT
extern const char *cn_cbor_error_str[];
/**
@@ -223,6 +274,7 @@
* @param[out] errp Error, if NULL is returned
* @return The parsed CBOR structure, or NULL on error
*/
+MYLIB_EXPORT
cn_cbor* cn_cbor_decode(const uint8_t *buf, size_t len CBOR_CONTEXT, cn_cbor_errback *errp);
/**
@@ -232,6 +284,7 @@
* @param[in] key The string to look up in the map
* @return The matching value, or NULL if the key is not found
*/
+MYLIB_EXPORT
cn_cbor* cn_cbor_mapget_string(const cn_cbor* cb, const char* key);
/**
@@ -241,15 +294,17 @@
* @param[in] key The int to look up in the map
* @return The matching value, or NULL if the key is not found
*/
+MYLIB_EXPORT
cn_cbor* cn_cbor_mapget_int(const cn_cbor* cb, int key);
/**
* Get the item with the given index from a CBOR array.
*
- * @param[in] cb The CBOR map
+ * @param[in] cb The CBOR array
* @param[in] idx The array index
* @return The matching value, or NULL if the index is invalid
*/
+MYLIB_EXPORT
cn_cbor* cn_cbor_index(const cn_cbor* cb, unsigned int idx);
/**
@@ -260,15 +315,19 @@
* @param[in] cb The CBOR value to free. May be NULL, or a root object.
* @param[in] CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
*/
+MYLIB_EXPORT
void cn_cbor_free(cn_cbor* cb CBOR_CONTEXT);
/**
* Write a CBOR value and all of the child values.
*
- * @param[in] buf The buffer into which to write
+ * @param[in] buf The buffer into which to write. May be NULL to
+ * determine the necessary size.
* @param[in] buf_offset The offset (in bytes) from the beginning of the buffer
* to start writing at
- * @param[in] buf_size The total length (in bytes) of the buffer
+ * @param[in] buf_size The total length (in bytes) of the buffer. If buf is
+ * NULL, this is an upper limit and may be 0 to specify
+ * no limit.
* @param[in] cb [description]
* @return -1 on fail, or number of bytes written
*/
@@ -284,6 +343,7 @@
* @param[out] errp Error, if NULL is returned
* @return The created map, or NULL on error
*/
+MYLIB_EXPORT
cn_cbor* cn_cbor_map_create(CBOR_CONTEXT_COMMA cn_cbor_errback *errp);
/**
@@ -296,6 +356,7 @@
* @param[out] errp Error, if NULL is returned
* @return The created object, or NULL on error
*/
+MYLIB_EXPORT
cn_cbor* cn_cbor_data_create(const uint8_t* data, int len
CBOR_CONTEXT,
cn_cbor_errback *errp);
@@ -313,6 +374,7 @@
* @param[out] errp Error, if NULL is returned
* @return The created object, or NULL on error
*/
+MYLIB_EXPORT
cn_cbor* cn_cbor_string_create(const char* data
CBOR_CONTEXT,
cn_cbor_errback *errp);
@@ -325,6 +387,7 @@
* @param[out] errp Error, if NULL is returned
* @return The created object, or NULL on error
*/
+MYLIB_EXPORT
cn_cbor* cn_cbor_int_create(int64_t value
CBOR_CONTEXT,
cn_cbor_errback *errp);
@@ -365,6 +428,7 @@
* @param[out] errp Error
* @return True on success
*/
+MYLIB_EXPORT
bool cn_cbor_map_put(cn_cbor* cb_map,
cn_cbor *cb_key, cn_cbor *cb_value,
cn_cbor_errback *errp);
@@ -380,6 +444,7 @@
* @param[out] errp Error
* @return True on success
*/
+MYLIB_EXPORT
bool cn_cbor_mapput_int(cn_cbor* cb_map,
int64_t key, cn_cbor* cb_value
CBOR_CONTEXT,
@@ -399,6 +464,7 @@
* @param[out] errp Error
* @return True on success
*/
+MYLIB_EXPORT
bool cn_cbor_mapput_string(cn_cbor* cb_map,
const char* key, cn_cbor* cb_value
CBOR_CONTEXT,
@@ -411,6 +477,7 @@
* @param[out] errp Error, if NULL is returned
* @return The created object, or NULL on error
*/
+MYLIB_EXPORT
cn_cbor* cn_cbor_array_create(CBOR_CONTEXT_COMMA cn_cbor_errback *errp);
/**
@@ -421,10 +488,37 @@
* @param[out] errp Error
* @return True on success
*/
+MYLIB_EXPORT
bool cn_cbor_array_append(cn_cbor* cb_array,
cn_cbor* cb_value,
cn_cbor_errback *errp);
+/**
+ * Dump the object to a file pointer
+ * If buffer is NULL, then return required size to generate output
+ *
+ * @param[in] buffer Location to place output
+ * @param[in] bufferSize Size of return buffer
+ * @param[in] fp File pointer to print on
+ * @param[in] cb tree to be dumped
+ * @param[in] indent string to use for each level of indention
+ * @param[in] crlf string to use for end of line marker
+ * @return size of output generated, -1 if buffer is too small
+ */
+
+extern ssize_t cn_cbor_printer_write(char * buffer, size_t bufferSize, const cn_cbor * cb, const char * indent, const char * crlf);
+
+#ifdef __MBED__
+#define ntohs(a) ((uint16_t) (((((uint16_t) (a)) & 0xff) << 8) | (((uint16_t) (a)) & 0xff00) >> 8))
+#define htons(a) ntohs(a)
+#define ntohl(a) ((uint32_t) ( \
+ ((((uint32_t)(a)) & 0x000000ff) << 24) | \
+ ((((uint32_t)(a)) & 0x0000ff00) << 8) | \
+ ((((uint32_t)(a)) & 0x00ff0000) >> 8) | \
+ ((((uint32_t)(a)) & 0xff000000) >> 24)))
+#define htonl(a) ntohl(a)
+#endif // __MBED__
+
#ifdef __cplusplus
}
#endif
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
deleted file mode 100644
index babe95c..0000000
--- a/src/CMakeLists.txt
+++ /dev/null
@@ -1,53 +0,0 @@
-#
-#
-# compiling/installing sources for cn-cbor
-
-set ( cbor_srcs
- cn-cbor.c
- cn-create.c
- cn-encoder.c
- cn-error.c
- cn-get.c
-)
-
-if (align_reads)
- add_definitions(-DCBOR_ALIGN_READS)
-endif()
-if (use_context)
- add_definitions(-DUSE_CBOR_CONTEXT)
-endif()
-add_library ( cn-cbor SHARED ${cbor_srcs} )
-target_include_directories ( cn-cbor PUBLIC ../include )
-target_include_directories ( cn-cbor PRIVATE ../src )
-
-install ( TARGETS cn-cbor
- LIBRARY DESTINATION lib
- ARCHIVE DESTINATION lib
- RUNTIME DESTINATION bin)
-
-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake)
-if (coveralls)
- include(Coveralls)
- coveralls_turn_on_coverage()
-
- set(COVERAGE_SRCS "")
- foreach (S ${cbor_srcs})
- get_filename_component(S_ABS ${S} ABSOLUTE)
- list (APPEND COVERAGE_SRCS ${S_ABS})
- endforeach()
-
- # Create the coveralls target.
- coveralls_setup(
- "${COVERAGE_SRCS}"
- ${coveralls_send} # If we should upload.
- )
-
- #add_dependencies(coveralls, all)
-endif()
-
-add_custom_target(size
- COMMAND echo "${CMAKE_BINARY_DIR}/src/CMakeFiles/cn-cbor.dir/cn-cbor.c.o"
- COMMAND size "${CMAKE_BINARY_DIR}/src/CMakeFiles/cn-cbor.dir/cn-cbor.c.o"
- COMMAND size -m "${CMAKE_BINARY_DIR}/src/CMakeFiles/cn-cbor.dir/cn-cbor.c.o"
- DEPENDS cn-cbor
-COMMENT "Output the size of the parse routine")
diff --git a/src/cbor.h b/src/cbor.h
index 1859f09..6329477 100644
--- a/src/cbor.h
+++ b/src/cbor.h
@@ -1,6 +1,10 @@
#ifndef CBOR_PROTOCOL_H__
#define CBOR_PROTOCOL_H__
+#ifdef _MSC_VER
+#define inline _inline
+#endif
+
/* The 8 major types */
#define MT_UNSIGNED 0
#define MT_NEGATIVE 1
diff --git a/src/cn-cbor.c b/src/cn-cbor.c
index 9093537..d837606 100644
--- a/src/cn-cbor.c
+++ b/src/cn-cbor.c
@@ -13,15 +13,24 @@
#include <string.h>
#include <assert.h>
#include <math.h>
+#ifdef _MSC_VER
+#include <WinSock2.h> // needed for ntohl on Windows
+#else
+#ifndef __MBED__
#include <arpa/inet.h> // needed for ntohl (e.g.) on Linux
+#endif
+
+#include "dll-export.h"
+#endif // _MSC_VER
#include "cn-cbor/cn-cbor.h"
#include "cbor.h"
#define CN_CBOR_FAIL(code) do { pb->err = code; goto fail; } while(0)
+MYLIB_EXPORT
void cn_cbor_free(cn_cbor* cb CBOR_CONTEXT) {
- cn_cbor* p = cb;
+ cn_cbor* p = (cn_cbor*) cb;
assert(!p || !p->parent);
while (p) {
cn_cbor* p1;
@@ -173,7 +182,7 @@
break;
case MT_BYTES: case MT_TEXT:
cb->v.str = (char *) pos;
- cb->length = val;
+ cb->length = (size_t) val;
TAKE(pos, ebuf, val, ;);
break;
case MT_MAP:
@@ -205,7 +214,7 @@
case AI_4:
#ifndef CBOR_NO_FLOAT
cb->type = CN_CBOR_DOUBLE;
- u32.u = val;
+ u32.u = (uint32_t) val;
cb->v.dbl = u32.f;
#else /* CBOR_NO_FLOAT */
CN_CBOR_FAIL(CN_CBOR_ERR_FLOAT_NOT_SUPPORTED);
@@ -253,6 +262,7 @@
return 0;
}
+MYLIB_EXPORT
cn_cbor* cn_cbor_decode(const unsigned char* buf, size_t len CBOR_CONTEXT, cn_cbor_errback *errp) {
cn_cbor catcher = {CN_CBOR_INVALID, 0, {0}, 0, NULL, NULL, NULL, NULL};
struct parse_buf pb;
diff --git a/src/cn-create.c b/src/cn-create.c
index 4ddce3b..c9ab816 100644
--- a/src/cn-create.c
+++ b/src/cn-create.c
@@ -8,6 +8,7 @@
#include <string.h>
#include <stdlib.h>
+#include "dll-export.h"
#include "cn-cbor/cn-cbor.h"
#include "cbor.h"
@@ -16,6 +17,7 @@
(v) = CN_CALLOC_CONTEXT(); \
if (!(v)) { if (errp) {errp->err = CN_CBOR_ERR_OUT_OF_MEMORY;} return NULL; }
+MYLIB_EXPORT
cn_cbor* cn_cbor_map_create(CBOR_CONTEXT_COMMA cn_cbor_errback *errp)
{
cn_cbor* ret;
@@ -27,6 +29,7 @@
return ret;
}
+MYLIB_EXPORT
cn_cbor* cn_cbor_data_create(const uint8_t* data, int len
CBOR_CONTEXT,
cn_cbor_errback *errp)
@@ -41,6 +44,7 @@
return ret;
}
+MYLIB_EXPORT
cn_cbor* cn_cbor_string_create(const char* data
CBOR_CONTEXT,
cn_cbor_errback *errp)
@@ -55,6 +59,7 @@
return ret;
}
+MYLIB_EXPORT
cn_cbor* cn_cbor_int_create(int64_t value
CBOR_CONTEXT,
cn_cbor_errback *errp)
@@ -119,6 +124,7 @@
return true;
}
+MYLIB_EXPORT
bool cn_cbor_map_put(cn_cbor* cb_map,
cn_cbor *cb_key, cn_cbor *cb_value,
cn_cbor_errback *errp)
@@ -133,6 +139,7 @@
return _append_kv(cb_map, cb_key, cb_value);
}
+MYLIB_EXPORT
bool cn_cbor_mapput_int(cn_cbor* cb_map,
int64_t key, cn_cbor* cb_value
CBOR_CONTEXT,
@@ -152,6 +159,7 @@
return _append_kv(cb_map, cb_key, cb_value);
}
+MYLIB_EXPORT
bool cn_cbor_mapput_string(cn_cbor* cb_map,
const char* key, cn_cbor* cb_value
CBOR_CONTEXT,
@@ -171,6 +179,7 @@
return _append_kv(cb_map, cb_key, cb_value);
}
+MYLIB_EXPORT
cn_cbor* cn_cbor_array_create(CBOR_CONTEXT_COMMA cn_cbor_errback *errp)
{
cn_cbor* ret;
@@ -182,6 +191,7 @@
return ret;
}
+MYLIB_EXPORT
bool cn_cbor_array_append(cn_cbor* cb_array,
cn_cbor* cb_value,
cn_cbor_errback *errp)
diff --git a/src/cn-encoder.c b/src/cn-encoder.c
index d8a4d49..d5b5bf0 100644
--- a/src/cn-encoder.c
+++ b/src/cn-encoder.c
@@ -8,12 +8,24 @@
} /* Duh. */
#endif
+#ifdef _MSC_VER
+#include <WinSock2.h>
+#define inline _inline
+#else
+#ifndef __MBED__
#include <arpa/inet.h>
+#endif
+#endif
#include <string.h>
+#ifndef _MSC_VER
+#ifndef __MBED__
#include <strings.h>
+#endif
+#endif
#include <stdbool.h>
#include <assert.h>
+#include "dll-export.h"
#include "cn-cbor/cn-cbor.h"
#include "cbor.h"
@@ -35,22 +47,30 @@
ssize_t size;
} cn_write_state;
-#define ensure_writable(sz) if ((ws->offset<0) || (ws->offset + (sz) >= ws->size)) { \
+#define ensure_writable(sz) if ((ws->buf != NULL) && ((ws->offset<0) || (ws->offset + (sz) > ws->size))) { \
ws->offset = -1; \
return; \
}
#define write_byte_and_data(b, data, sz) \
-ws->buf[ws->offset++] = (b); \
-memcpy(ws->buf+ws->offset, (data), (sz)); \
+if(ws->buf) { \
+ ws->buf[ws->offset++] = (b); \
+ memcpy(ws->buf+ws->offset, (data), (sz)); \
+} else { \
+ ws->offset++; \
+} \
ws->offset += sz;
#define write_byte(b) \
-ws->buf[ws->offset++] = (b); \
+if(ws->buf) { \
+ ws->buf[ws->offset++] = (b); \
+} else { \
+ ws->offset++; \
+}
#define write_byte_ensured(b) \
ensure_writable(1); \
-write_byte(b); \
+write_byte(b);
static uint8_t _xlate[] = {
IB_FALSE, /* CN_CBOR_FALSE */
@@ -89,7 +109,7 @@
if (val < 24) {
ensure_writable(1);
- write_byte(ib | val);
+ write_byte(ib | (uint8_t) val);
} else if (val < 256) {
ensure_writable(2);
write_byte(ib | 24);
@@ -102,7 +122,8 @@
} else if (val < 0x100000000L) {
uint32_t be32 = (uint32_t)val;
ensure_writable(5);
- be32 = hton32p(&be32);
+ // be32 = hton32p(&be32);
+ be32 = htonl(be32);
write_byte_and_data(ib | 26, (const void*)&be32, 4);
} else {
uint64_t be64;
@@ -178,7 +199,7 @@
// TODO: make public?
typedef void (*cn_visit_func)(const cn_cbor *cb, int depth, void *context);
-static void _visit(const cn_cbor *cb,
+void _visit(const cn_cbor *cb,
cn_visit_func visitor,
cn_visit_func breaker,
void *context)
@@ -194,17 +215,25 @@
depth++;
} else{
// Empty indefinite
+#ifdef CN_INCLUDE_DUMPER
+ breaker(p, depth, context);
+#else
if (is_indefinite(p)) {
- breaker(p->parent, depth, context);
+ breaker(p, depth, context);
}
+#endif
if (p->next) {
p = p->next;
} else {
while (p->parent) {
depth--;
+#ifdef CN_INCLUDE_DUMPER
+ breaker(p->parent, depth, context);
+#else
if (is_indefinite(p->parent)) {
breaker(p->parent, depth, context);
}
+#endif
if (p->parent->next) {
p = p->parent->next;
goto visit;
@@ -249,7 +278,9 @@
case CN_CBOR_BYTES:
CHECK(_write_positive(ws, cb->type, cb->length));
ensure_writable(cb->length);
- memcpy(ws->buf+ws->offset, cb->v.str, cb->length);
+ if (ws->buf) {
+ memcpy(ws->buf+ws->offset, cb->v.str, cb->length);
+ }
ws->offset += cb->length;
break;
@@ -271,13 +302,12 @@
CHECK(_write_positive(ws, CN_CBOR_INT, ~(cb->v.sint)));
break;
+#ifndef CBOR_NO_FLOAT
case CN_CBOR_DOUBLE:
-#ifndef CBOR_NO_FLOAT
CHECK(_write_double(ws, cb->v.dbl));
-#endif /* CBOR_NO_FLOAT */
break;
+
case CN_CBOR_FLOAT:
-#ifndef CBOR_NO_FLOAT
CHECK(_write_double(ws, cb->v.f));
#endif /* CBOR_NO_FLOAT */
break;
@@ -293,7 +323,13 @@
cn_write_state *ws = context;
UNUSED_PARAM(cb);
UNUSED_PARAM(depth);
- write_byte_ensured(IB_BREAK);
+#ifdef CN_INCLUDE_DUMPER
+ if (is_indefinite(cb)) {
+#endif
+ write_byte_ensured(IB_BREAK);
+#ifdef CN_INCLUDE_DUMPER
+ }
+#endif
}
ssize_t cn_cbor_encoder_write(uint8_t *buf,
@@ -302,6 +338,7 @@
const cn_cbor *cb)
{
cn_write_state ws = { buf, buf_offset, buf_size };
+ if (!ws.buf && ws.size <= 0) { ws.size = (ssize_t)(((size_t)-1) / 2); }
_visit(cb, _encoder_visitor, _encoder_breaker, &ws);
if (ws.offset < 0) { return -1; }
return ws.offset - buf_offset;
diff --git a/src/cn-error.c b/src/cn-error.c
index 4953cc9..ad48746 100644
--- a/src/cn-error.c
+++ b/src/cn-error.c
@@ -1,3 +1,6 @@
+#include "dll-export.h"
+
+MYLIB_EXPORT
const char *cn_cbor_error_str[] = {
"CN_CBOR_NO_ERROR",
"CN_CBOR_ERR_OUT_OF_DATA",
diff --git a/src/cn-get.c b/src/cn-get.c
index 79d3d72..4b2ee13 100644
--- a/src/cn-get.c
+++ b/src/cn-get.c
@@ -2,8 +2,11 @@
#include <string.h>
#include <assert.h>
+#include "dll-export.h"
+
#include "cn-cbor/cn-cbor.h"
+MYLIB_EXPORT
cn_cbor* cn_cbor_mapget_int(const cn_cbor* cb, int key) {
cn_cbor* cp;
assert(cb);
@@ -26,6 +29,7 @@
return NULL;
}
+MYLIB_EXPORT
cn_cbor* cn_cbor_mapget_string(const cn_cbor* cb, const char* key) {
cn_cbor *cp;
int keylen;
@@ -49,6 +53,7 @@
return NULL;
}
+MYLIB_EXPORT
cn_cbor* cn_cbor_index(const cn_cbor* cb, unsigned int idx) {
cn_cbor *cp;
unsigned int i = 0;
diff --git a/src/cn-print.c b/src/cn-print.c
new file mode 100644
index 0000000..077b0a4
--- /dev/null
+++ b/src/cn-print.c
@@ -0,0 +1,261 @@
+#ifndef CN_PRINT_C
+#define CN_PRINT_C
+#define CN_INCLUDE_DUMPER
+#ifdef CN_INCLUDE_DUMPER
+#define _CRT_SECURE_NO_WARNINGS 1
+
+#include <stdio.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef EMACS_INDENTATION_HELPER
+} /* Duh. */
+#endif
+
+#include <stdio.h>
+#ifdef MSV_CRT
+#include <winsock2.h>
+#else
+#define _snprintf snprintf
+#endif
+#include <string.h>
+#include <stdbool.h>
+#include <assert.h>
+
+#include "cn-cbor/cn-cbor.h"
+#include "cbor.h"
+
+typedef struct _write_state
+{
+ char * rgbOutput;
+ ssize_t ib;
+ size_t cbLeft;
+ uint8_t * rgFlags;
+ const char * szIndentWith;
+ const char * szEndOfLine;
+} cn_write_state;
+
+typedef void(*cn_visit_func)(const cn_cbor *cb, int depth, void *context);
+extern void _visit(const cn_cbor *cb,
+ cn_visit_func visitor,
+ cn_visit_func breaker,
+ void *context);
+
+const char RgchHex[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+
+bool _isWritable(cn_write_state * ws, size_t cb)
+{
+ if (ws->rgbOutput == NULL) return true;
+ if ((ws->ib < 0) || (ws->ib + cb > ws->cbLeft)) {
+ ws->ib = -1;
+ return false;
+ }
+ return true;
+}
+
+void write_data(cn_write_state * ws, const char * sz, size_t cb)
+{
+ if (_isWritable(ws, cb)) {
+ if (ws->rgbOutput != NULL) memcpy(ws->rgbOutput + ws->ib, sz, cb);
+ ws->ib += cb;
+ }
+}
+
+void _doIndent(cn_write_state * ws, int depth)
+{
+ int i;
+ char * sz = ws->rgbOutput + ws->ib;
+ size_t cbIndentWith = strlen(ws->szIndentWith);
+ int cbIndent = depth * cbIndentWith;
+
+
+ if (ws->rgbOutput == NULL) {
+ ws->ib += cbIndent;
+ return;
+ }
+
+ if (_isWritable(ws, cbIndent)) {
+ for (i = 0; i < depth; i++) {
+ memcpy(sz, ws->szIndentWith, cbIndentWith);
+ sz += cbIndentWith;
+ }
+ }
+
+ ws->ib += cbIndent;
+
+ return;
+}
+
+void _print_encoder(const cn_cbor * cb, int depth, void * context)
+{
+ int i;
+ char rgchT[256];
+ int cch;
+ cn_write_state * ws = (cn_write_state *)context;
+ uint8_t flags = ws->rgFlags[depth];
+
+ if (flags & 1) {
+ write_data(ws, ", ", 2);
+ ws->rgFlags[depth] &= 0xfe;
+
+ if (ws->szIndentWith) {
+ write_data(ws, ws->szEndOfLine, strlen(ws->szEndOfLine));
+ _doIndent(ws, depth);
+ }
+ }
+
+ if (flags & 2) {
+ write_data(ws, ": ", 2);
+ ws->rgFlags[depth] &= 0xfd;
+ }
+
+ switch (cb->type) {
+ case CN_CBOR_BYTES_CHUNKED:
+ case CN_CBOR_TEXT_CHUNKED:
+ break;
+
+ case CN_CBOR_ARRAY:
+ write_data(ws, "[", 1);
+ ws->rgFlags[depth] |= 4;
+
+ if (ws->szIndentWith) {
+ write_data(ws, ws->szEndOfLine, strlen(ws->szEndOfLine));
+ _doIndent(ws, depth + 1);
+ }
+ break;
+
+ case CN_CBOR_MAP:
+ write_data(ws, "{", 1);
+ ws->rgFlags[depth] |= 8;
+
+ if (ws->szIndentWith) {
+ write_data(ws, ws->szEndOfLine, strlen(ws->szEndOfLine));
+ _doIndent(ws, depth + 1);
+ }
+ break;
+
+ case CN_CBOR_TAG:
+ case CN_CBOR_UINT:
+ case CN_CBOR_SIMPLE:
+ cch = _snprintf(rgchT, sizeof(rgchT), "%u", (unsigned int) cb->v.uint);
+ write_data(ws, rgchT, cch);
+ break;
+
+ case CN_CBOR_FALSE:
+ write_data(ws, "false", 5);
+ break;
+
+ case CN_CBOR_TRUE:
+ write_data(ws, "true", 4);
+ break;
+
+ case CN_CBOR_NULL:
+ write_data(ws, "null", 4);
+ break;
+
+ case CN_CBOR_UNDEF:
+ write_data(ws, "undef", 5);
+ break;
+
+ case CN_CBOR_INT:
+ cch = _snprintf(rgchT, sizeof(rgchT), "%d", (unsigned int) cb->v.sint);
+ write_data(ws, rgchT, cch);
+ break;
+
+#ifndef CBOR_NO_FLOAT
+ case CN_CBOR_FLOAT:
+ cch = _snprintf(rgchT, sizeof(rgchT), "%f", cb->v.f);
+ write_data(ws, rgchT, cch);
+ break;
+
+ case CN_CBOR_DOUBLE:
+ cch = _snprintf(rgchT, sizeof(rgchT), "%f", cb->v.dbl);
+ write_data(ws, rgchT, cch);
+ break;
+#endif
+
+ case CN_CBOR_INVALID:
+ write_data(ws, "invalid", 7);
+ break;
+
+ case CN_CBOR_TEXT:
+ write_data(ws, "\"", 1);
+ write_data(ws, cb->v.str, cb->length);
+ write_data(ws, "\"", 1);
+ break;
+
+ case CN_CBOR_BYTES:
+ write_data(ws, "h'", 2);
+ for (i = 0; i < cb->length; i++) {
+ write_data(ws, &RgchHex[(cb->v.str[i] / 16) & 0xf], 1);
+ write_data(ws, &RgchHex[cb->v.str[i] & 0xf], 1);
+ }
+ write_data(ws, "\'", 1);
+ break;
+
+ }
+
+ if (depth > 0) {
+ if (ws->rgFlags[depth - 1] & 4) ws->rgFlags[depth] |= 1;
+ else if (ws->rgFlags[depth - 1] & 8) {
+ if (flags & 2) ws->rgFlags[depth] |= 1;
+ else ws->rgFlags[depth] |= 2;
+ }
+ }
+}
+
+void _print_breaker(const cn_cbor * cb, int depth, void * context)
+{
+ cn_write_state * ws = (cn_write_state *)context;
+
+ switch (cb->type) {
+ case CN_CBOR_ARRAY:
+ if (ws->szIndentWith) {
+ write_data(ws, ws->szEndOfLine, strlen(ws->szEndOfLine));
+ _doIndent(ws, depth);
+ }
+
+ write_data(ws, "]", 1);
+ ws->rgFlags[depth + 1] = 0;
+ break;
+
+ case CN_CBOR_MAP:
+ if (ws->szIndentWith) {
+ write_data(ws, ws->szEndOfLine, strlen(ws->szEndOfLine));
+ _doIndent(ws, depth);
+ }
+
+ write_data(ws, "}", 1);
+ ws->rgFlags[depth + 1] = 0;
+ break;
+
+ default:
+ break;
+ }
+}
+
+ssize_t cn_cbor_printer_write(char * rgbBuffer, size_t cbBuffer, const cn_cbor * cb, const char * szIndentWith, const char * szEndOfLine)
+{
+ uint8_t flags[128] = { 0 };
+ char rgchZero[1] = { 0 };
+
+ cn_write_state ws = { rgbBuffer, 0, cbBuffer, flags, szIndentWith, szEndOfLine };
+ _visit(cb, _print_encoder, _print_breaker, &ws);
+ write_data(&ws, rgchZero, 1);
+
+ return ws.ib;
+}
+
+#ifdef EMACS_INDENTATION_HELPER
+{ /* Duh. */
+#endif
+#ifdef _cplusplus
+} /* extern "C" */
+#endif
+
+#endif // CN_INCLUDE_DUMPER
+#endif // CN_PRINT_C
+
diff --git a/src/dll-export.h b/src/dll-export.h
new file mode 100644
index 0000000..3d0c928
--- /dev/null
+++ b/src/dll-export.h
@@ -0,0 +1,23 @@
+// Contents of DLLDefines.h
+#ifndef _cn_cbor_DLLDEFINES_H_
+#define _cn_cbor_DLLDEFINES_H_
+
+/* Cmake will define cn_cbor_EXPORTS on Windows when it
+configures to build a shared library. If you are going to use
+another build system on windows or create the visual studio
+projects by hand you need to define cn_cbor_EXPORTS when
+building a DLL on windows.
+*/
+// We are using the Visual Studio Compiler and building Shared libraries
+
+#if defined (_WIN32)
+#if defined(CN_CBOR_IS_DLL)
+ #define MYLIB_EXPORT __declspec(dllexport)
+#else
+ #define MYLIB_EXPORT
+#endif /* cn_cbor_EXPORTS */
+#else /* defined (_WIN32) */
+ #define MYLIB_EXPORT
+#endif
+
+#endif /* _cn_cbor_DLLDEFINES_H_ */
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 3181a8d..c0b76d7 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,33 +1,32 @@
#
-#
# Compiling/running tests
-if (use_context)
+if(CN_CBOR_USE_CONTEXT)
add_definitions(-DUSE_CBOR_CONTEXT)
endif()
-set ( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${dist_dir}/test )
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${dist_dir}/test)
-function (create_test name)
- add_executable ( ${name}_test ${name}_test.c )
- target_link_libraries ( ${name}_test PRIVATE cn-cbor )
- target_include_directories ( ${name}_test PRIVATE ../include )
- add_test ( NAME ${name} COMMAND ${name}_test )
+function(create_test name)
+ add_executable(${name}_test ${name}_test.c)
+ target_link_libraries(${name}_test PRIVATE cn-cbor)
+ target_include_directories(${name}_test PRIVATE ../include)
+ add_test(NAME ${name} COMMAND ${name}_test)
endfunction()
-create_test ( cbor )
-include ( CTest )
+create_test(cbor)
+include(CTest)
-if (APPLE)
+if(APPLE)
# difftest uses Apple-specific memory tests
- add_executable (cn-test test.c )
- target_include_directories ( cn-test PRIVATE ../include )
- target_link_libraries ( cn-test PRIVATE cn-cbor )
+ add_executable(cn-test test.c)
+ target_link_libraries(cn-test PRIVATE cn-cbor)
configure_file(cases.cbor cases.cbor COPYONLY)
configure_file(expected.out expected.out COPYONLY)
- add_custom_target(difftest
+ add_custom_target(
+ difftest
COMMAND env MallocStackLogging=true ./cn-test >new.out
COMMAND diff new.out expected.out
DEPENDS cn-test
diff --git a/test/cbor_test.c b/test/cbor_test.c
index eafea5d..3888723 100644
--- a/test/cbor_test.c
+++ b/test/cbor_test.c
@@ -1,12 +1,22 @@
/*
* Copyright (c) 2015 SPUDlib authors. See LICENSE file.
*/
+
+#ifdef _MSC_VER
+#define _CRT_SECURE_NO_WARNINGS
+#define _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#endif
+
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
+#ifdef _MSC_VER
+#include "winsock2.h"
+#endif
#include "cn-cbor/cn-cbor.h"
@@ -43,7 +53,13 @@
b->sz = len / 2;
b->ptr = malloc(b->sz);
for (i=0; i<b->sz; i++) {
+#ifdef _MSC_VER
+ unsigned int iX;
+ sscanf(inp+(2*i), "%02hx", &iX);
+ b->ptr[i] = (byte)iX;
+#else
sscanf(inp+(2*i), "%02hhx", &b->ptr[i]);
+#endif
}
return true;
}
@@ -116,6 +132,7 @@
size_t i;
unsigned char encoded[1024];
ssize_t enc_sz;
+ ssize_t enc_sz2;
for (i=0; i<sizeof(tests)/sizeof(char*); i++) {
ASSERT_TRUE(parse_hex(tests[i], &b));
@@ -125,7 +142,9 @@
ASSERT_EQUAL(err.err, CN_CBOR_NO_ERROR);
ASSERT_NOT_NULL(cb);
+ enc_sz2 = cn_cbor_encoder_write(NULL, 0, sizeof(encoded), cb);
enc_sz = cn_cbor_encoder_write(encoded, 0, sizeof(encoded), cb);
+ ASSERT_EQUAL(enc_sz, enc_sz2);
ASSERT_DATA(b.ptr, b.sz, encoded, enc_sz);
free(b.ptr);
cn_cbor_free(cb CONTEXT_NULL);
@@ -164,6 +183,7 @@
size_t i;
unsigned char encoded[1024];
ssize_t enc_sz;
+ ssize_t enc_sz2;
for (i=0; i<sizeof(basic_tests)/sizeof(char*); i+=2) {
ASSERT_TRUE(parse_hex(basic_tests[i], &b));
@@ -174,7 +194,9 @@
ASSERT_EQUAL(err.err, CN_CBOR_NO_ERROR);
ASSERT_NOT_NULL(cb);
+ enc_sz2 = cn_cbor_encoder_write(NULL, 0, sizeof(encoded), cb);
enc_sz = cn_cbor_encoder_write(encoded, 0, sizeof(encoded), cb);
+ ASSERT_EQUAL(enc_sz, enc_sz2);
ASSERT_DATA(b2.ptr, b2.sz, encoded, enc_sz);
free(b.ptr);
free(b2.ptr);
@@ -195,7 +217,9 @@
ASSERT_NULL(cb);
#endif /* CBOR_NO_FLOAT */
+ /* enc_sz2 = cn_cbor_encoder_write(NULL, 0, sizeof(encoded), cb); */
/* enc_sz = cn_cbor_encoder_write(encoded, 0, sizeof(encoded), cb); */
+ /* ASSERT_EQUAL(enc_sz, enc_sz2); */
/* ASSERT_DATA(b2.ptr, b2.sz, encoded, enc_sz); */
free(b.ptr);
free(b2.ptr);
@@ -258,13 +282,16 @@
size_t i;
unsigned char encoded[1024];
ssize_t enc_sz;
+ ssize_t enc_sz2;
for (i=0; i<sizeof(tests)/sizeof(char*); i++) {
ASSERT_TRUE(parse_hex(tests[i], &b));
cb = cn_cbor_decode(b.ptr, b.sz CONTEXT_NULL, &err);
ASSERT_NOT_NULL(cb);
+ enc_sz2 = cn_cbor_encoder_write(NULL, 0, sizeof(encoded), cb);
enc_sz = cn_cbor_encoder_write(encoded, 0, sizeof(encoded), cb);
+ ASSERT_EQUAL(enc_sz, enc_sz2);
ASSERT_DATA(b.ptr, b.sz, encoded, enc_sz);
free(b.ptr);
@@ -446,6 +473,8 @@
ASSERT_NOT_NULL(cdata);
ASSERT_TRUE(cn_cbor_mapput_int(map, 0, cdata, CONTEXT_NULL_COMMA NULL));
+ enc_sz = cn_cbor_encoder_write(NULL, 0, sizeof(encoded), map);
+ ASSERT_EQUAL(7, enc_sz);
enc_sz = cn_cbor_encoder_write(encoded, 0, sizeof(encoded), map);
ASSERT_EQUAL(7, enc_sz);
}
diff --git a/test/ctest.h b/test/ctest.h
index 75fda66..c971c55 100644
--- a/test/ctest.h
+++ b/test/ctest.h
@@ -16,6 +16,14 @@
#ifndef CTEST_H
#define CTEST_H
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#pragma section(".ctest")
+
+#include <io.h>
+#define isatty _isatty
+#endif
+
#ifndef UNUSED_PARAM
/**
* \def UNUSED_PARAM(p);
@@ -47,11 +55,19 @@
#define __CTEST_MAGIC (0xdeadbeef)
#ifdef __APPLE__
#define __Test_Section __attribute__ ((unused,section ("__DATA, .ctest")))
+#define MS__Test_Section
+#else
+#ifdef _MSC_VER
+#define __Test_Section
+#define MS__Test_Section __declspec(allocate(".ctest"))
#else
#define __Test_Section __attribute__ ((unused,section (".ctest")))
+#define MS__Test_Section
+#endif
#endif
#define __CTEST_STRUCT(sname, tname, _skip, __data, __setup, __teardown) \
+ MS__Test_Section \
struct ctest __TNAME(sname, tname) __Test_Section = { \
.ssname=#sname, \
.ttname=#tname, \
@@ -138,9 +154,13 @@
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
+#ifndef _MSC_VER
#include <sys/time.h>
+#endif
#include <inttypes.h>
+#ifndef _MSC_VER
#include <unistd.h>
+#endif
#include <stdint.h>
#include <stdlib.h>
@@ -306,6 +326,27 @@
return strncmp(suite_name, t->ssname, strlen(suite_name)) == 0;
}
+#ifdef _MSC_VER
+int gettimeofday(struct timeval * tp, struct timezone * tzp)
+{
+ // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's
+ static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL);
+
+ SYSTEMTIME system_time;
+ FILETIME file_time;
+ uint64_t time;
+
+ GetSystemTime(&system_time);
+ SystemTimeToFileTime(&system_time, &file_time);
+ time = ((uint64_t)file_time.dwLowDateTime);
+ time += ((uint64_t)file_time.dwHighDateTime) << 32;
+
+ tp->tv_sec = (long)((time - EPOCH) / 10000000L);
+ tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
+ return 0;
+}
+#endif
+
static uint64_t getCurrentTime() {
struct timeval now;
gettimeofday(&now, NULL);
@@ -377,6 +418,7 @@
}
color_output = isatty(1);
+
uint64_t t1 = getCurrentTime();
struct ctest* ctest_begin = &__TNAME(suite, test);