Compare commits

..

28 Commits

Author SHA1 Message Date
Takatoshi Kondo
a9a48cea3a Merge pull request #976 from redboltz/update_to_c_4
Updated the version to 4.0.0.
2021-09-01 11:10:58 +09:00
Takatoshi Kondo
e96853a946 Updated the version to 4.0.0. 2021-09-01 10:50:27 +09:00
Takatoshi Kondo
2ebe884c0e Merge pull request #962 from jrtc27/c-cheri
Support building for CHERI/Morello
2021-08-17 14:20:42 +09:00
Jessica Clarke
823caa8d8c Increase portability by masking rather than dividing and multiplying pointers
If (u)intptr_t exist, the only guarantee provided by the C standard is
that you can cast a pointer to one and back. No claims are made about
what that injective pointer-to-integer mapping is, nor the surjective
reverse integer-to-pointer mapping; for example, nowhere is it specified
that, given a char *p, p + 1 == (char *)((uintptr_t)p + 1), although no
sensible implementation would make that not the case (provided p is a
valid strictly in bounds pointer).

With real pointers, taking them out of bounds (other than the one
exception that is a one-past-the-end pointer) of their corresponding
allocation is UB. Whilst the semantics of arithmetic on uintptr_t is not
specified when cast back to a pointer, compilers already assume that
uintptr_t arithmetic does not go out of bounds (or, put another way,
that the result always ends up pointing to the same allocation) and
their alias analysis-based optimisations already assume this. CHERI, and
Arm's Morello, implement C language pointers with hardware capabilities,
which are unforgeable pointers with bounds and permissions. In order to
only double rather than quadruple the size of pointers, CHERI exploits
C's requirement that pointers not be taken out of bounds, and compresses
these bounds using a floating-point-like representation. The important
implication of this for most software is that if a capability, i.e. C
pointer in CHERI C, is taken too far out of bounds (where "too far" is
proportional to the size of the allocation) it can no longer be
represented and thus is invalidated, meaning it will trap on a later
dereference. This also extends to (u)intptr_t, which are also
implemented as capabilities, since if it were just a plain integer then
casting a pointer to (u)intptr_t would lose the metadata and break the
ability to cast back to a pointer.

Whilst the composition of dividing a pointer and then multiplying it
again has a somewhat sensible interpretation of rounding it down (even
though technically no such guarantees are made by the spec), the
individual operations do not, and the division is highly likely to take
the pointer far out of bounds of its allocation and, on CHERI, result in
it being unrepresentable and thus invalidated. Instead, we can perform a
more standard bitwise AND with a mask to clear the low bits, exploiting
the fact that alignments are powers of two; note that technically the
rounding up variant of this does take the pointer out of bounds slightly
and, whilst there are other ways to write such code that avoid doing so,
they are more cumbersome, and this code does not need to worry about
that.
2021-08-07 00:19:46 +01:00
Jessica Clarke
9c5654ed44 Increase portability by using uintptr_t rather than size_t for pointers
The only integral types guaranteed by the C standard, if they exist, to
support having a pointer cast to them and back are (u)intptr_t. On most
architectures, size_t and uintptr_t are typedefs for the same underlying
type, so this code ends up working. However, on CHERI, and thus Arm's
experimental Morello prototype, C language pointers are implemented with
hardware capabilities, which are unforgeable pointers with bounds and
permissions. This means that, whilst size_t remains a plain 32/64-bit
integer size, (u)intotr_t is represented with a capability. Casting to
size_t and back to a pointer causes the capability metadata to be lost
and the resulting capability to be invalid, meaning it will trap when
dereferenced. Instead, use uintptr_t, and provide fallback definitions
for old versions of MSVC like for the other C99 integer types.
2021-08-06 23:49:16 +01:00
Takatoshi Kondo
5d30e42c01 Merge pull request #953 from kovdan01/fix_name_conflicts_c
Fix name conflicts (C)
2021-05-09 12:12:18 +09:00
Daniil Kovalev
6b4a7b3b16 Fix iovec-related tests 2021-05-08 17:58:09 +03:00
Daniil Kovalev
0f1d0ed78c Fix name conflicts (C version)
Same as #952, but for C
2021-05-08 16:51:02 +03:00
Takatoshi Kondo
825017ac50 Merge pull request #949 from redboltz/fix_948
Fixed #948.
2021-04-24 15:41:02 +09:00
Takatoshi Kondo
4bc64de0ec Fixed #948.
Added msgpack_unpacked_destroy() call.
2021-04-24 15:25:37 +09:00
Takatoshi Kondo
08a42a347c Merge pull request #944 from vmallet/ctests_verbose
C: Increase tests visibility (Issue #943)
2021-04-03 09:39:06 +09:00
Takatoshi Kondo
734e47c067 Merge pull request #942 from vmallet/fix_print_buffer_empty_str
Fix #941: empty strings break msgpack_object_print_buffer() (C)
2021-04-03 09:23:26 +09:00
Vincent Mallet
fa7bb8ec77 README: make reference to gtest 2021-03-23 17:05:54 -07:00
Vincent Mallet
dc51f5d236 Better visibility for C tests:
- turn on output-on-failure by default
 - explain how to run tests in README
2021-03-23 16:33:52 -07:00
Vincent Mallet
f06b46d412 Attempt to fix Windows build for tests.
Use sprintf_s (windows) or snprintf (others) instead of sprintf in unit tests.
2021-03-23 14:57:07 -07:00
Vincent Mallet
1c97e051ad Fixes #941
Don't abort serialization when running into empty strings in msgpack_object_print_buffer().
Added a couple of unit tests to test empty string cases.
2021-03-23 13:56:03 -07:00
Takatoshi Kondo
4f59b98185 Merge pull request #899 from redboltz/fix_buffer_ptr_size
Fix buffer ptr size
2020-07-03 19:42:50 +09:00
Takatoshi Kondo
208ec65034 Set -fsanitize=undefined on CI.
Propagate CXXFLAGS correctly.
Set CFLAGS in the same way.
2020-07-03 09:30:05 +09:00
Takatoshi Kondo
3bd0172a9a Unified NULL buf handling for all *buffer.
*buffer means sbuffer, zbuffer, fbuffer, and vrefbuffer.

The logic is as follows:

if buf is NULL
   if len is 0
      do nothing return 0 (success)
   else
      assertion fail
else
   set contants to *buffer
2020-07-03 09:18:00 +09:00
Takatoshi Kondo
3bb121fb8f Merge pull request #890 from ygj6/c_master
check null pointer before using memcpy()
2020-07-01 18:25:08 +09:00
yuangongji
fd9e377bac check null pointer before using memcpy() 2020-07-01 16:39:40 +08:00
Takatoshi Kondo
82ddfc1170 Merge pull request #885 from redboltz/fix_gha_badge_for_c
Replaced travis-ci badge with github actiond badge.
2020-06-12 12:29:26 +09:00
Takatoshi Kondo
6b195acba0 Replaced travis-ci badge with github actiond badge. 2020-06-12 11:36:41 +09:00
Takatoshi Kondo
ea1435784d Merge pull request #877 from ygj6/c_master
remove C++ library in c_master branch
2020-06-08 09:25:43 +09:00
yuangongji
9eba7c482c remove C++ part in source code 2020-06-05 18:16:07 +08:00
yuangongji
9c6857c425 rename pack_template.h and sysdep.h
include/msgpack/pack_template.h => cmake/pack_template.h.in
include/msgpack/sysdep.h => cmake/sysdep.h.in

Use `git log --follow cmake/filename.h.in` to see full log
2020-06-05 16:09:17 +08:00
yuangongji
111b91a3e2 move exmple/c/* to example/
example/c/cmake/CMakeLists.txt => example/cmake/CMakeLists.txt
example/c/lib_buffer_unpack.c => example/lib_buffer_unpack.c
example/c/simple_c.c => example/simple_c.c
example/c/speed_test_uint32_array.c => example/speed_test_uint32_array.c
example/c/speed_test_uint64_array.c => example/speed_test_uint64_array.c
example/c/user_buffer_unpack.c => example/user_buffer_unpack.c

Use `git log --follow example/filename` to see full log
2020-06-05 16:09:17 +08:00
yuangongji
ee546036a1 remove C++ part files
remove the following files or folders:
erb
example/boost
example/cpp03
example/cpp11
example/x3
example/CMakeLists.txt
fuzz
include/msgpack/adaptor
include/msgpack/predef.h
include/msgpack/predef
include/msgpack/preprocessor
include/msgpack/v1
include/msgpack/v2
include/msgpack/v3
include/msgpack/*.hpp
include/msgpack.hpp
.gitmodules
external
make_file_list.sh
msgpack_vc8.sln
msgpack_vc8.vcproj
preprocess
QUICKSTART-CPP.md
test/*.cpp exclude test/*_c.cpp
.github/depends/boost.sh
ci/build_regression.sh
2020-06-05 16:09:17 +08:00
58 changed files with 11203 additions and 24 deletions

View File

@@ -1,19 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
msgpack-c or msgpack-cxx version.
e.g) msgpack-cxx 5.0.0
**To Reproduce**
Please prepare https://stackoverflow.com/help/minimal-reproducible-example
**Expected behavior**
A clear and concise description of what you expected to happen.

53
.github/workflows/coverage.yml vendored Normal file
View File

@@ -0,0 +1,53 @@
name: coverage
on:
pull_request:
types: [opened, synchronize]
push:
branches:
- c_master
tags:
- '*'
jobs:
codecov:
timeout-minutes: 30
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: install depends
run: |
sudo apt-get update
sudo apt-get install g++-multilib lcov
- name: Compile tests
run: |
# install gtest
BASE=`pwd`
wget https://github.com/google/googletest/archive/release-1.7.0.zip -O googletest-release-1.7.0.zip
unzip -q googletest-release-1.7.0.zip
cd googletest-release-1.7.0
g++ -m64 src/gtest-all.cc -I. -Iinclude -c -fPIC
g++ -m64 src/gtest_main.cc -I. -Iinclude -c -fPIC
ar -rv libgtest.a gtest-all.o
ar -rv libgtest_main.a gtest_main.o
mkdir -p ${BASE}/usr/include
cp -r include/gtest ${BASE}/usr/include
mkdir -p ${BASE}/usr/lib
mv *.a ${BASE}/usr/lib
cd ..
mkdir build && cd build
CMAKE_LIBRARY_PATH="${BASE}/build" GTEST_ROOT="${BASE}/usr" CMAKE_PREFIX_PATH="${BASE}/usr/gcc/lib64/cmake" cmake -DMSGPACK_32BIT=OFF -DBUILD_SHARED_LIBS=ON -DMSGPACK_CHAR_SIGN=signed -DMSGPACK_BUILD_EXAMPLES=ON -DMSGPACK_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Debug -DMSGPACK_GEN_COVERAGE=ON ..
make -j4
make test
- name: Upload coverage to Codecov
working-directory: build
run: |
# Create lcov report
lcov --capture --directory . --output-file coverage.info
lcov --remove coverage.info '/usr/*' --output-file coverage.info # filter system-files
lcov --list coverage.info # debug info
# Uploading report to CodeCov
bash <(curl -s https://codecov.io/bash) -f coverage.info || echo "Codecov did not collect coverage reports"

225
.github/workflows/gha.yml vendored Normal file
View File

@@ -0,0 +1,225 @@
name: CI
on:
pull_request:
types: [opened, synchronize]
push:
branches:
- c_master
tags:
- '*'
jobs:
macos:
runs-on: macos-latest
strategy:
fail-fast: false
matrix:
pattern: [0, 1, 2, 3]
steps:
- uses: actions/checkout@v1
- name: build and test
env:
CC: clang
CXX: clang++
shell: bash
run: |
BASE=`pwd`;
# matrix config
ACTION="ci/build_cmake.sh"
export ARCH="64"
if [ ${{ matrix.pattern }} == 0 ]; then
export SHARED="ON"
export CHAR_SIGN="unsigned"
fi
if [ ${{ matrix.pattern }} == 1 ]; then
export SHARED="ON"
export CHAR_SIGN="signed"
fi
if [ ${{ matrix.pattern }} == 2 ]; then
export SHARED="OFF"
export CHAR_SIGN="signed"
fi
if [ ${{ matrix.pattern }} == 3 ]; then
export SHARED="OFF"
export CHAR_SIGN="unsigned"
fi
# install gtest
wget https://github.com/google/googletest/archive/release-1.7.0.zip -O googletest-release-1.7.0.zip
unzip -q googletest-release-1.7.0.zip
cd googletest-release-1.7.0
$CXX -m${ARCH} src/gtest-all.cc -I. -Iinclude -c
$CXX -m${ARCH} src/gtest_main.cc -I. -Iinclude -c
ar -rv libgtest.a gtest-all.o
ar -rv libgtest_main.a gtest_main.o
mkdir -p ${BASE}/usr/include
cp -r include/gtest ${BASE}/usr/include
mkdir -p ${BASE}/usr/lib
mv *.a ${BASE}/usr/lib
cd ..
# build and test
CMAKE_CXX_COMPILER="${CXX}" CMAKE_C_COMPILER="${CC}" GTEST_ROOT="${BASE}/usr" CFLAGS="-Werror -g -fsanitize=undefined" CXXFLAGS="-Werror -g -fsanitize=undefined" ${ACTION}
linux:
runs-on: ubuntu-18.04
strategy:
fail-fast: false
matrix:
pattern: [0, 1, 2, 3, 4, 5, 6, 7, 8]
steps:
- uses: actions/checkout@v1
- name: install build depends
run: |
sudo apt-get update
sudo apt-get install g++-multilib clang-8 valgrind
- name: build and test
shell: bash
run: |
BASE=`pwd`;
# matrix config
if [ ${{ matrix.pattern }} == 0 ]; then
export CC=clang
export CXX=clang++
ACTION="ci/build_cmake.sh"
export ARCH="64"
export SHARED="ON"
export CHAR_SIGN="unsigned"
fi
if [ ${{ matrix.pattern }} == 1 ]; then
export CC=clang
export CXX=clang++
ACTION="ci/build_cmake.sh"
export ARCH="32"
export SHARED="ON"
export CHAR_SIGN="signed"
fi
if [ ${{ matrix.pattern }} == 2 ]; then
export CC=clang
export CXX=clang++
ACTION="ci/build_cmake.sh"
export ARCH="64"
export SHARED="ON"
export CHAR_SIGN="signed"
fi
if [ ${{ matrix.pattern }} == 3 ]; then
export CC=clang
export CXX=clang++
ACTION="ci/build_cmake.sh"
export ARCH="32"
export SHARED="OFF"
export CHAR_SIGN="unsigned"
fi
if [ ${{ matrix.pattern }} == 4 ]; then
export CC=gcc
export CXX=g++
ACTION="ci/build_cmake.sh"
export ARCH="64"
export SHARED="ON"
export CHAR_SIGN="signed"
fi
if [ ${{ matrix.pattern }} == 5 ]; then
export CC=gcc
export CXX=g++
ACTION="ci/build_cmake.sh"
export ARCH="32"
export SHARED="ON"
export CHAR_SIGN="unsigned"
fi
if [ ${{ matrix.pattern }} == 6 ]; then
export CC=gcc
export CXX=g++
ACTION="ci/build_cmake.sh"
export ARCH="64"
export SHARED="ON"
export CHAR_SIGN="unsigned"
fi
if [ ${{ matrix.pattern }} == 7 ]; then
export CC=gcc
export CXX=g++
ACTION="ci/build_cmake.sh"
export ARCH="32"
export SHARED="OFF"
export CHAR_SIGN="signed"
fi
if [ ${{ matrix.pattern }} == 8 ]; then
export CC=gcc
export CXX=g++
ACTION="ci/build_cmake_embedded.sh"
export ARCH="64"
fi
# install gtest
wget https://github.com/google/googletest/archive/release-1.7.0.zip -O googletest-release-1.7.0.zip
unzip -q googletest-release-1.7.0.zip
cd googletest-release-1.7.0
$CXX -m${ARCH} src/gtest-all.cc -I. -Iinclude -c -fPIC
$CXX -m${ARCH} src/gtest_main.cc -I. -Iinclude -c -fPIC
ar -rv libgtest.a gtest-all.o
ar -rv libgtest_main.a gtest_main.o
mkdir -p ${BASE}/usr/include
cp -r include/gtest ${BASE}/usr/include
mkdir -p ${BASE}/usr/lib
mv *.a ${BASE}/usr/lib
cd ..
# install zlib
if [ ${ARCH} == 32 ]; then
sudo apt-get install lib32z1-dev
fi
# build and test
CMAKE_CXX_COMPILER="${CXX}" CMAKE_C_COMPILER="${CC}" GTEST_ROOT="${BASE}/usr" CFLAGS="-Werror -g -fsanitize=undefined" CXXFLAGS="-Werror -g -fsanitize=undefined" MSGPACK_SAN="${SAN}" ${ACTION}
windows:
runs-on: windows-2019
strategy:
fail-fast: false
matrix:
pattern: [0, 1, 2, 3]
steps:
- uses: actions/checkout@v2.0.0
- name: Cache vcpkg
id: cache-vcpkg
uses: actions/cache@v1.1.2
with:
path: C:/vcpkg/installed
key: windows-2019-vcpkg-v2
- name: Build dependencies
if: steps.cache-vcpkg.outputs.cache-hit != 'true'
shell: powershell
run: |
vcpkg install gtest:x64-windows gtest:x86-windows
vcpkg install zlib:x64-windows zlib:x86-windows
- name: Build and test
shell: powershell
run: |
if (${{ matrix.pattern }} -eq 0) {
$ARCH="x64"
$SHARED="ON"
}
elseif (${{ matrix.pattern }} -eq 1) {
$ARCH="x64"
$SHARED="OFF"
}
elseif (${{ matrix.pattern }} -eq 2) {
$ARCH="Win32"
$SHARED="ON"
}
else {
$ARCH="Win32"
$SHARED="OFF"
}
$CUR=(Get-Location).Path
md build
cd build
cmake -A $ARCH -DBUILD_SHARED_LIBS=$SHARED -DCMAKE_TOOLCHAIN_FILE="C:/vcpkg/scripts/buildsystems/vcpkg.cmake" "-DCMAKE_CXX_FLAGS=/D_VARIADIC_MAX=10 /EHsc /D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING" ..
cmake --build . --config Release
$pathbak="$env:PATH"
$env:PATH="C:\vcpkg\installed\x64-windows\bin;$CUR\build\Release;$pathbak"
ctest -V
$env:PATH=$pathbak

51
.gitignore vendored Normal file
View File

@@ -0,0 +1,51 @@
# Files generated by the bootstrap script.
/INSTALL
/AUTHORS
/ChangeLog
/NEWS
/README
/ac/
/aclocal.m4
/autom4te.cache/
/config.h.in
/configure
/msgpack_vc2008.sln
/msgpack_vc2008.vcproj
Makefile.in
# Files generated by the configure script.
/config.h
/config.log
/config.status
/libtool
/msgpack.pc
/src/msgpack/version.h
/src/msgpack/version.hpp
/stamp-h1
Makefile
.deps
.libs
# Files generated by make.
*.o
*.so
*.lo
*.la
# Files generated by make check.
# TODO: Replace these with something like /test/*_test
/test/buffer
/test/cases
/test/convert
/test/fixint
/test/fixint_c
/test/msgpack_test
/test/msgpackc_test
/test/object
/test/pack_unpack
/test/pack_unpack_c
/test/streaming
/test/streaming_c
/test/version
/test/zone

View File

@@ -1,3 +1,15 @@
# 2021-08-01 version 4.0.0
* Fix and improve alignment logic (#962)
* Fix iovec name conflict (#953)
* Fix empty string print (#942)
* Fix buffer ptr size (#899)
* Fix UB. Check null pointer before using memcpy() (#890)
* Improve CI environment (#885, #899)
## << breaking changes >>
* Separate C part of the msgpack-c from C/C++ mixed msgpack-c (#876, #878)
# 2020-06-05 version 3.3.0
* Add json example for C (#870)
* Add both header and body packing functions for C (#870)

333
CMakeLists.txt Normal file
View File

@@ -0,0 +1,333 @@
CMAKE_MINIMUM_REQUIRED (VERSION 2.8.12)
IF ((CMAKE_VERSION VERSION_GREATER 3.1) OR
(CMAKE_VERSION VERSION_EQUAL 3.1))
CMAKE_POLICY(SET CMP0054 NEW)
ENDIF ()
PROJECT (msgpack)
FILE (READ ${CMAKE_CURRENT_SOURCE_DIR}/include/msgpack/version_master.h contents)
STRING (REGEX MATCH "#define MSGPACK_VERSION_MAJOR *([0-9a-zA-Z_]*)" NULL_OUT ${contents})
SET (VERSION_MAJOR ${CMAKE_MATCH_1})
STRING (REGEX MATCH "#define MSGPACK_VERSION_MINOR *([0-9a-zA-Z_]*)" NULL_OUT ${contents})
SET (VERSION_MINOR ${CMAKE_MATCH_1})
STRING (REGEX MATCH "#define MSGPACK_VERSION_REVISION *([0-9a-zA-Z_]*)" NULL_OUT ${contents})
SET (VERSION_REVISION ${CMAKE_MATCH_1})
SET (VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION})
LIST (APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/")
SET (prefix ${CMAKE_INSTALL_PREFIX})
SET (exec_prefix "\${prefix}")
SET (libdir "\${exec_prefix}/lib")
SET (includedir "\${prefix}/include")
OPTION (MSGPACK_32BIT "32bit compile" OFF)
INCLUDE(TestBigEndian)
TEST_BIG_ENDIAN(BIGENDIAN)
IF (BIGENDIAN)
SET(MSGPACK_ENDIAN_BIG_BYTE 1)
SET(MSGPACK_ENDIAN_LITTLE_BYTE 0)
ELSE ()
SET(MSGPACK_ENDIAN_BIG_BYTE 0)
SET(MSGPACK_ENDIAN_LITTLE_BYTE 1)
ENDIF ()
CONFIGURE_FILE (
cmake/sysdep.h.in
include/msgpack/sysdep.h
@ONLY
)
CONFIGURE_FILE (
cmake/pack_template.h.in
include/msgpack/pack_template.h
@ONLY
)
IF (APPLE)
SET(CMAKE_MACOSX_RPATH ON)
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)
IF ("${isSystemDir}" STREQUAL "-1")
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
ENDIF ()
ENDIF ()
IF (MSGPACK_32BIT)
IF ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
SET (CMAKE_C_FLAGS "-m32 ${CMAKE_C_FLAGS}")
SET (CMAKE_EXE_LINKER_FLAGS "-m32 ${CMAKE_EXE_LINKER_FLAGS}")
ELSEIF ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
SET (CMAKE_C_FLAGS "-m32 ${CMAKE_C_FLAGS}")
SET (CMAKE_EXE_LINKER_FLAGS "-m32 ${CMAKE_EXE_LINKER_FLAGS}")
ENDIF ()
ENDIF ()
OPTION (MSGPACK_BUILD_EXAMPLES "Build msgpack examples." ON)
IF (MSGPACK_CHAR_SIGN)
SET (CMAKE_C_FLAGS "-f${MSGPACK_CHAR_SIGN}-char ${CMAKE_C_FLAGS}")
ENDIF ()
FIND_PACKAGE (GTest)
FIND_PACKAGE (ZLIB)
FIND_PACKAGE (Threads)
IF (GTEST_FOUND AND ZLIB_FOUND AND THREADS_FOUND)
OPTION (MSGPACK_BUILD_TESTS "Build msgpack tests." ON)
OPTION (MSGPACK_GEN_COVERAGE "Enable running gcov to get a test coverage report." OFF)
ENDIF ()
IF (DEFINED BUILD_SHARED_LIBS)
IF (BUILD_SHARED_LIBS)
IF (DEFINED MSGPACK_ENABLE_SHARED AND NOT MSGPACK_ENABLE_SHARED)
MESSAGE(WARNING "MSGPACK_ENABLE_SHARED is overridden to ON by BUILD_SHARED_LIBS")
ENDIF ()
SET (MSGPACK_ENABLE_SHARED ON)
IF (DEFINED MSGPACK_ENABLE_STATIC AND MSGPACK_ENABLE_STATIC)
MESSAGE(WARNING "MSGPACK_ENABLE_STATIC is overridden to OFF by BUILD_SHARED_LIBS")
ENDIF ()
SET (MSGPACK_ENABLE_STATIC OFF)
ELSE ()
IF (DEFINED MSGPACK_ENABLE_SHARED AND MSGPACK_ENABLE_SHARED)
MESSAGE(WARNING "MSGPACK_ENABLE_SHARED is overridden to OFF by BUILD_SHARED_LIBS")
ENDIF ()
SET (MSGPACK_ENABLE_SHARED OFF)
IF (DEFINED MSGPACK_ENABLE_STATIC AND NOT MSGPACK_ENABLE_STATIC)
MESSAGE(WARNING "MSGPACK_ENABLE_STATIC is overridden to ON by BUILD_SHARED_LIBS")
ENDIF ()
SET (MSGPACK_ENABLE_STATIC ON)
ENDIF ()
ELSE ()
IF (NOT DEFINED MSGPACK_ENABLE_SHARED)
SET (MSGPACK_ENABLE_SHARED ON)
ENDIF ()
IF (NOT DEFINED MSGPACK_ENABLE_STATIC)
SET (MSGPACK_ENABLE_STATIC ON)
ENDIF ()
SET (BUILD_SHARED_LIBS ${MSGPACK_ENABLE_SHARED})
ENDIF ()
INCLUDE (Files.cmake)
CONFIGURE_FILE (
msgpack.pc.in
msgpack.pc
@ONLY
)
IF (MSGPACK_ENABLE_SHARED OR MSGPACK_ENABLE_STATIC)
ADD_LIBRARY (msgpackc
${msgpackc_SOURCES}
${msgpackc_HEADERS}
)
SET_TARGET_PROPERTIES (msgpackc PROPERTIES SOVERSION 2 VERSION 2.0.0)
TARGET_INCLUDE_DIRECTORIES (msgpackc
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include/msgpack>
$<INSTALL_INTERFACE:include>
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
ENDIF ()
IF (MSGPACK_ENABLE_SHARED AND MSGPACK_ENABLE_STATIC)
ADD_LIBRARY (msgpackc-static STATIC
${msgpackc_SOURCES}
${msgpackc_HEADERS}
)
TARGET_INCLUDE_DIRECTORIES (msgpackc-static
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include/msgpack>
$<INSTALL_INTERFACE:include>
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
SET_TARGET_PROPERTIES (msgpackc-static PROPERTIES OUTPUT_NAME "msgpackc")
IF (MSGPACK_ENABLE_SHARED)
IF (MSVC)
SET_TARGET_PROPERTIES (msgpackc PROPERTIES IMPORT_SUFFIX "_import.lib")
ELSEIF (MINGW)
SET_TARGET_PROPERTIES (msgpackc PROPERTIES IMPORT_SUFFIX ".dll.a")
ENDIF ()
ENDIF ()
ENDIF ()
IF (MSGPACK_GEN_COVERAGE)
IF (NOT MSGPACK_BUILD_TESTS)
MESSAGE(FATAL_ERROR "Coverage requires -DMSGPACK_BUILD_TESTS=ON")
ENDIF ()
STRING(TOUPPER "${CMAKE_BUILD_TYPE}" UPPER_CMAKE_BUILD_TYPE)
IF (NOT "${UPPER_CMAKE_BUILD_TYPE}" STREQUAL "DEBUG")
MESSAGE(FATAL_ERROR "Coverage requires -DCMAKE_BUILD_TYPE=Debug")
ENDIF ()
INCLUDE(CodeCoverage)
SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_FLAGS}")
SETUP_TARGET_FOR_COVERAGE(coverage make coverage test)
ENDIF ()
IF (MSGPACK_BUILD_TESTS)
ENABLE_TESTING ()
list(APPEND CMAKE_CTEST_ARGUMENTS "--output-on-failure")
# MEMORYCHECK_COMMAND_OPTIONS needs to place prior to CTEST_MEMORYCHECK_COMMAND
SET (MEMORYCHECK_COMMAND_OPTIONS "--leak-check=full --show-leak-kinds=definite,possible --error-exitcode=1")
FIND_PROGRAM(CTEST_MEMORYCHECK_COMMAND NAMES valgrind)
INCLUDE(Dart)
ADD_SUBDIRECTORY (test)
ENDIF ()
IF ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
IF (MSGPACK_ENABLE_SHARED OR MSGPACK_ENABLE_STATIC)
SET_PROPERTY (TARGET msgpackc APPEND_STRING PROPERTY COMPILE_FLAGS " -Wall -Wextra -DPIC")
ENDIF ()
IF (MSGPACK_ENABLE_SHARED AND MSGPACK_ENABLE_STATIC)
SET_PROPERTY (TARGET msgpackc-static APPEND_STRING PROPERTY COMPILE_FLAGS " -Wall -Wextra" )
ENDIF ()
ENDIF ()
IF ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
IF (MSGPACK_ENABLE_SHARED OR MSGPACK_ENABLE_STATIC)
SET_PROPERTY (TARGET msgpackc APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-mismatched-tags")
ENDIF ()
IF (MSGPACK_ENABLE_SHARED AND MSGPACK_ENABLE_STATIC)
SET_PROPERTY (TARGET msgpackc-static APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-mismatched-tags")
ENDIF ()
ENDIF ()
IF ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
IF (CMAKE_C_FLAGS MATCHES "/W[0-4]")
STRING(REGEX REPLACE "/W[0-4]" "/W3 /WX" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
ELSE ()
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3 /WX")
ENDIF ()
ENDIF ()
IF ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
IF (CMAKE_C_FLAGS MATCHES "/W[0-4]")
STRING(REGEX REPLACE "/W[0-4]" "/W3 /WX" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
ELSE ()
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3 /WX")
ENDIF ()
ENDIF ()
IF ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC90" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC10")
SET_SOURCE_FILES_PROPERTIES(${msgpackc_SOURCES} PROPERTIES LANGUAGE C)
ENDIF ()
IF ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "sparc")
SET (CMAKE_C_FLAGS "-DMSGPACK_ZONE_ALIGN=8 ${CMAKE_C_FLAGS}")
ENDIF ()
IF (NOT DEFINED CMAKE_INSTALL_BINDIR)
SET(CMAKE_INSTALL_BINDIR bin)
ENDIF ()
IF (NOT DEFINED CMAKE_INSTALL_LIBDIR)
SET(CMAKE_INSTALL_LIBDIR lib)
ENDIF ()
IF (MSGPACK_BUILD_EXAMPLES)
ADD_SUBDIRECTORY (example)
ENDIF ()
IF (MSGPACK_ENABLE_SHARED OR MSGPACK_ENABLE_STATIC)
SET (MSGPACK_INSTALLTARGETS msgpackc)
ENDIF ()
IF (MSGPACK_ENABLE_SHARED AND MSGPACK_ENABLE_STATIC)
LIST (APPEND MSGPACK_INSTALLTARGETS msgpackc-static)
ENDIF ()
INSTALL (TARGETS ${MSGPACK_INSTALLTARGETS} EXPORT msgpack-targets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
FOREACH (file ${msgpackc_common_HEADERS})
GET_FILENAME_COMPONENT (dir ${file} PATH)
INSTALL (FILES ${file} DESTINATION ${CMAKE_INSTALL_PREFIX}/${dir})
ENDFOREACH ()
FOREACH (file ${msgpackc_configured_HEADERS})
GET_FILENAME_COMPONENT (dir ${file} PATH)
INSTALL (FILES ${CMAKE_CURRENT_BINARY_DIR}/${file} DESTINATION ${CMAKE_INSTALL_PREFIX}/${dir})
ENDFOREACH ()
IF (NOT MSVC)
INSTALL (FILES ${CMAKE_CURRENT_BINARY_DIR}/msgpack.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
ENDIF ()
# Doxygen
FIND_PACKAGE (Doxygen)
IF (DOXYGEN_FOUND)
LIST (APPEND Doxyfile_c_CONTENT
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile_c
COMMAND ${CMAKE_COMMAND} -E echo "FILE_PATTERNS = *.h" >> ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile_c
COMMAND ${CMAKE_COMMAND} -E echo "OUTPUT_DIRECTORY = doc_c" >> ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile_c
COMMAND ${CMAKE_COMMAND} -E echo "INPUT = ${CMAKE_CURRENT_SOURCE_DIR}/include" >> ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile_c
COMMAND ${CMAKE_COMMAND} -E echo "EXTRACT_ALL = YES" >> ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile_c
COMMAND ${CMAKE_COMMAND} -E echo "PROJECT_NAME = \"MessagePack for C\"" >> ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile_c
COMMAND ${CMAKE_COMMAND} -E echo "STRIP_FROM_PATH = ${CMAKE_CURRENT_SOURCE_DIR}/include" >> ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile_c
)
IF (DOXYGEN_DOT_FOUND)
LIST (APPEND Doxyfile_c_CONTENT
COMMAND ${CMAKE_COMMAND} -E echo "HAVE_DOT = YES" >> ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile_c
)
ENDIF ()
ADD_CUSTOM_TARGET (
doxygen
${Doxyfile_c_CONTENT}
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile_c
VERBATIM
)
ENDIF ()
INCLUDE (CMakePackageConfigHelpers)
SET (CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/msgpack")
WRITE_BASIC_PACKAGE_VERSION_FILE (
msgpack-config-version.cmake
VERSION ${VERSION}
COMPATIBILITY SameMajorVersion
)
IF (NOT CMAKE_VERSION VERSION_LESS 3.0)
EXPORT (EXPORT msgpack-targets
FILE "${CMAKE_CURRENT_BINARY_DIR}/msgpack-targets.cmake"
)
ENDIF ()
CONFIGURE_PACKAGE_CONFIG_FILE (msgpack-config.cmake.in
msgpack-config.cmake
INSTALL_DESTINATION "${CMAKE_INSTALL_CMAKEDIR}"
)
INSTALL (EXPORT msgpack-targets
FILE
msgpack-targets.cmake
DESTINATION
"${CMAKE_INSTALL_CMAKEDIR}"
)
INSTALL (
FILES
"${CMAKE_CURRENT_BINARY_DIR}/msgpack-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/msgpack-config-version.cmake"
DESTINATION
"${CMAKE_INSTALL_CMAKEDIR}"
)

1552
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

41
Files.cmake Normal file
View File

@@ -0,0 +1,41 @@
# Source files
SET (msgpackc_SOURCES
src/objectc.c
src/unpack.c
src/version.c
src/vrefbuffer.c
src/zone.c
)
# Header files
SET (msgpackc_common_HEADERS
include/msgpack.h
include/msgpack/fbuffer.h
include/msgpack/gcc_atomic.h
include/msgpack/object.h
include/msgpack/pack.h
include/msgpack/pack_define.h
include/msgpack/sbuffer.h
include/msgpack/timestamp.h
include/msgpack/unpack.h
include/msgpack/unpack_define.h
include/msgpack/unpack_template.h
include/msgpack/util.h
include/msgpack/version.h
include/msgpack/version_master.h
include/msgpack/vrefbuffer.h
include/msgpack/zbuffer.h
include/msgpack/zone.h
)
# Header files will configured
SET (msgpackc_configured_HEADERS
include/msgpack/pack_template.h
include/msgpack/sysdep.h
)
# All header files
LIST (APPEND msgpackc_HEADERS
${msgpackc_common_HEADERS}
${msgpackc_configured_HEADERS}
)

193
QUICKSTART-C.md Normal file
View File

@@ -0,0 +1,193 @@
# Implementation Status
The serialization library is production-ready.
Currently, RPC implementation is not available.
# Install
## Install with package manager
### MacOS with MacPorts
On MacOS, you can install MessagePack for C using MacPorts.
```
$ sudo port install msgpack
```
You might need to run `sudo port selfupdate` before installing to update the package repository.
You can also install via Homebrew.
```
$ brew install msgpack
```
### FreeBSD with Ports Collection
On FreeBSD, you can use Ports Collection. Install [net/msgpack](http://www.freebsd.org/cgi/cvsweb.cgi/ports/devel/msgpack/) package.
### Gentoo Linux with Portage
On Gentoo Linux, you can use emerge. Install [dev-libs/msgpack](http://gentoo-portage.com/dev-libs/msgpack) package.
### Windows with vcpkg
There are several package managers available, and vcpkg is typical.
```
$ vcpkg install msgpack:x64-windows
```
## Install with source code
### Build with cmake
You need to install cmake (2.8.12 or higher) first.
```
$ git clone https://github.com/msgpack/msgpack-c.git
$ cd msgpack-c
$ mkdir build
$ cd build
$ cmake ..
$ cmake --build .
$ cmake --build . --target install
```
### Build with autotools
In versions 1.4.2 and below, you can use `autotools` to build on UNIX-like platforms.
```
$ wget https://github.com/msgpack/msgpack-c/archive/cpp-1.3.0.tar.gz
$ tar zxvf msgpack-1.3.0.tar.gz
$ cd msgpack-1.3.0
$ ./bootstrap # If the 'configure' script already exists, you can omit this step.
$ ./configure
$ make
$ sudo make install
```
# Serialization QuickStart for C
## First program
Include `msgpack.h` header and link `msgpack` library to use MessagePack on your program.
```c
#include <msgpack.h>
#include <stdio.h>
int main(void) {
/* creates buffer and serializer instance. */
msgpack_sbuffer* buffer = msgpack_sbuffer_new();
msgpack_packer* pk = msgpack_packer_new(buffer, msgpack_sbuffer_write);
/* serializes ["Hello", "MessagePack"]. */
msgpack_pack_array(pk, 2);
msgpack_pack_bin(pk, 5);
msgpack_pack_bin_body(pk, "Hello", 5);
msgpack_pack_bin(pk, 11);
msgpack_pack_bin_body(pk, "MessagePack", 11);
/* deserializes it. */
msgpack_unpacked msg;
msgpack_unpacked_init(&msg);
msgpack_unpack_return ret = msgpack_unpack_next(&msg, buffer->data, buffer->size, NULL);
/* prints the deserialized object. */
msgpack_object obj = msg.data;
msgpack_object_print(stdout, obj); /*=> ["Hello", "MessagePack"] */
/* cleaning */
msgpack_unpacked_destroy(&msg);
msgpack_sbuffer_free(buffer);
msgpack_packer_free(pk);
}
```
## Simple program with a loop
```c
#include <msgpack.h>
#include <stdio.h>
int main(void) {
/* creates buffer and serializer instance. */
msgpack_sbuffer* buffer = msgpack_sbuffer_new();
msgpack_packer* pk = msgpack_packer_new(buffer, msgpack_sbuffer_write);
int j;
for(j = 0; j<23; j++) {
/* NB: the buffer needs to be cleared on each iteration */
msgpack_sbuffer_clear(buffer);
/* serializes ["Hello", "MessagePack"]. */
msgpack_pack_array(pk, 3);
msgpack_pack_bin(pk, 5);
msgpack_pack_bin_body(pk, "Hello", 5);
msgpack_pack_bin(pk, 11);
msgpack_pack_bin_body(pk, "MessagePack", 11);
msgpack_pack_int(pk, j);
/* deserializes it. */
msgpack_unpacked msg;
msgpack_unpacked_init(&msg);
msgpack_unpack_return ret = msgpack_unpack_next(&msg, buffer->data, buffer->size, NULL);
/* prints the deserialized object. */
msgpack_object obj = msg.data;
msgpack_object_print(stdout, obj); /*=> ["Hello", "MessagePack"] */
msgpack_unpacked_destroy(&msg);
puts("");
}
/* cleaning */
msgpack_sbuffer_free(buffer);
msgpack_packer_free(pk);
}
```
## Streaming feature
```c
#include <msgpack.h>
#include <stdio.h>
int main(void) {
/* serializes multiple objects using msgpack_packer. */
msgpack_sbuffer* buffer = msgpack_sbuffer_new();
msgpack_packer* pk = msgpack_packer_new(buffer, msgpack_sbuffer_write);
msgpack_pack_int(pk, 1);
msgpack_pack_int(pk, 2);
msgpack_pack_int(pk, 3);
/* deserializes these objects using msgpack_unpacker. */
msgpack_unpacker pac;
msgpack_unpacker_init(&pac, MSGPACK_UNPACKER_INIT_BUFFER_SIZE);
/* feeds the buffer. */
msgpack_unpacker_reserve_buffer(&pac, buffer->size);
memcpy(msgpack_unpacker_buffer(&pac), buffer->data, buffer->size);
msgpack_unpacker_buffer_consumed(&pac, buffer->size);
/* now starts streaming deserialization. */
msgpack_unpacked result;
msgpack_unpacked_init(&result);
while(msgpack_unpacker_next(&pac, &result)) {
msgpack_object_print(stdout, result.data);
puts("");
}
/* results:
* $ gcc stream.cc -lmsgpackc -o stream
* $ ./stream
* 1
* 2
* 3
*/
}
```

108
README.md
View File

@@ -1,6 +1,9 @@
`msgpack` for C/C++
`msgpack` for C
===================
Version 4.0.0 [![Build Status](https://github.com/msgpack/msgpack-c/workflows/CI/badge.svg?branch=c_master)](https://github.com/msgpack/msgpack-c/actions) [![Build status](https://ci.appveyor.com/api/projects/status/8kstcgt79qj123mw/branch/c_master?svg=true)](https://ci.appveyor.com/project/redboltz/msgpack-c/branch/c_master)
[![codecov](https://codecov.io/gh/msgpack/msgpack-c/branch/c_master/graph/badge.svg)](https://codecov.io/gh/msgpack/msgpack-c/branch/c_master)
It's like JSON but smaller and faster.
Overview
@@ -12,13 +15,108 @@ except that it's faster and smaller. Small integers are encoded into a
single byte and short strings require only one extra byte in
addition to the strings themselves.
### C Library
Example
-------
See [c_master](https://github.com/msgpack/msgpack-c/tree/c_master)
```c
#include <msgpack.h>
#include <stdio.h>
### C++ Library
int main(void)
{
/* msgpack::sbuffer is a simple buffer implementation. */
msgpack_sbuffer sbuf;
msgpack_sbuffer_init(&sbuf);
See [cpp_master](https://github.com/msgpack/msgpack-c/tree/cpp_master)
/* serialize values into the buffer using msgpack_sbuffer_write callback function. */
msgpack_packer pk;
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
msgpack_pack_array(&pk, 3);
msgpack_pack_int(&pk, 1);
msgpack_pack_true(&pk);
msgpack_pack_str(&pk, 7);
msgpack_pack_str_body(&pk, "example", 7);
/* deserialize the buffer into msgpack_object instance. */
/* deserialized object is valid during the msgpack_zone instance alive. */
msgpack_zone mempool;
msgpack_zone_init(&mempool, 2048);
msgpack_object deserialized;
msgpack_unpack(sbuf.data, sbuf.size, NULL, &mempool, &deserialized);
/* print the deserialized object. */
msgpack_object_print(stdout, deserialized);
puts("");
msgpack_zone_destroy(&mempool);
msgpack_sbuffer_destroy(&sbuf);
return 0;
}
```
See [`QUICKSTART-C.md`](./QUICKSTART-C.md) for more details.
Usage
-----
### Building and Installing
#### Install from git repository
##### Using the Terminal (CLI)
You will need:
- `gcc >= 4.1.0`
- `cmake >= 2.8.0`
How to build:
$ git clone https://github.com/msgpack/msgpack-c.git
$ cd msgpack-c
$ git checkout c_master
$ cmake .
$ make
$ sudo make install
How to run tests:
In order to run tests you must have the [GoogleTest](https://github.com/google/googletest) framework installed. If you do not currently have it, install it and re-run `cmake`.
Then:
$ make test
When you use the C part of `msgpack-c`, you need to build and link the library. By default, both static/shared libraries are built. If you want to build only static library, set `BUILD_SHARED_LIBS=OFF` to cmake. If you want to build only shared library, set `BUILD_SHARED_LIBS=ON`.
#### GUI on Windows
Clone msgpack-c git repository.
$ git clone https://github.com/msgpack/msgpack-c.git
or using GUI git client.
e.g.) tortoise git https://code.google.com/p/tortoisegit/
1. Checkout to c_master branch
2. Launch [cmake GUI client](http://www.cmake.org/cmake/resources/software.html).
3. Set 'Where is the source code:' text box and 'Where to build
the binaries:' text box.
4. Click 'Configure' button.
5. Choose your Visual Studio version.
6. Click 'Generate' button.
7. Open the created msgpack.sln on Visual Studio.
8. Build all.
### Documentation

43
appveyor.yml Normal file
View File

@@ -0,0 +1,43 @@
version: 4.0.0.{build}
branches:
only:
- c_master
image:
- Visual Studio 2015
environment:
matrix:
- msvc: '"Visual Studio 10 2010"'
- msvc: '"Visual Studio 11 2012"'
- msvc: '"Visual Studio 12 2013"'
- msvc: '"Visual Studio 14 2015"'
build_script:
- appveyor DownloadFile https://github.com/google/googletest/archive/release-1.7.0.zip -FileName googletest-release-1.7.0.zip
- 7z x googletest-release-1.7.0.zip > NUL
- cd googletest-release-1.7.0
- md build
- cd build
- cmake -G %msvc% -DBUILD_SHARED_LIBS=ON -DCMAKE_CXX_FLAGS=/D_VARIADIC_MAX=10 ..
- cmake --build . --config Release
- cd ..
- cd ..
- appveyor DownloadFile http://zlib.net/zlib-1.2.11.tar.gz -FileName zlib-1.2.11.tar.gz
- 7z x zlib-1.2.11.tar.gz > NUL
- 7z x zlib-1.2.11.tar > NUL
- cd zlib-1.2.11
- md build
- cd build
- cmake -G %msvc% ..
- cmake --build . --config Release
- copy zconf.h ..
- cd ..
- cd ..
- md build
- cd build
- cmake -G %msvc% -DGTEST_LIBRARY=%APPVEYOR_BUILD_FOLDER%\googletest-release-1.7.0\build\Release\gtest.lib -DGTEST_MAIN_LIBRARY=%APPVEYOR_BUILD_FOLDER%\googletest-release-1.7.0\build\Release\gtest_main.lib -DGTEST_INCLUDE_DIR=%APPVEYOR_BUILD_FOLDER%\googletest-release-1.7.0\include -DZLIB_LIBRARY=%APPVEYOR_BUILD_FOLDER%\zlib-1.2.11\build\Release\zlib.lib -DZLIB_INCLUDE_DIR=%APPVEYOR_BUILD_FOLDER%\zlib-1.2.11 -DCMAKE_CXX_FLAGS='"/D_VARIADIC_MAX=10 /EHsc"' ..
- cmake --build . --config Release -v
test_script:
- set PATH=%PATH%;%APPVEYOR_BUILD_FOLDER%\googletest-release-1.7.0\build\Release;%APPVEYOR_BUILD_FOLDER%\zlib-1.2.11\build\Release;%APPVEYOR_BUILD_FOLDER%\build\release
- ctest -V

112
ci/build_cmake.sh Executable file
View File

@@ -0,0 +1,112 @@
#!/bin/bash
mkdir build
ret=$?
if [ $ret -ne 0 ]
then
exit $ret
fi
cd build
ret=$?
if [ $ret -ne 0 ]
then
exit $ret
fi
if [ "${ARCH}" == "32" ]
then
export BIT32="ON"
export ARCH_FLAG="-m32"
else
export BIT32="OFF"
export ARCH_FLAG="-m64"
fi
cmake -DMSGPACK_32BIT=${BIT32} -DBUILD_SHARED_LIBS=${SHARED} -DMSGPACK_CHAR_SIGN=${CHAR_SIGN} -DCMAKE_CXX_FLAGS="${ARCH_FLAG} ${CXXFLAGS}" -DCMAKE_C_FLAGS="${CFLAGS}" ..
ret=$?
if [ $ret -ne 0 ]
then
exit $ret
fi
make
ret=$?
if [ $ret -ne 0 ]
then
exit $ret
fi
ctest -VV
ret=$?
if [ $ret -ne 0 ]
then
exit $ret
fi
make install DESTDIR=`pwd`/install
ret=$?
if [ $ret -ne 0 ]
then
exit $ret
fi
if [ "${ARCH}" != "32" ] && [ `uname` = "Linux" ]
then
ctest -T memcheck | tee memcheck.log
ret=${PIPESTATUS[0]}
if [ $ret -ne 0 ]
then
exit $ret
fi
cat memcheck.log | grep "Memory Leak" > /dev/null
ret=$?
if [ $ret -eq 0 ]
then
exit 1
fi
fi
if [ "${ARCH}" != "32" ]
then
mkdir install-test
ret=$?
if [ $ret -ne 0 ]
then
exit $ret
fi
cd install-test
ret=$?
if [ $ret -ne 0 ]
then
exit $ret
fi
cmake -DCMAKE_PREFIX_PATH=`pwd`/../install/usr/local/lib/cmake ../../example/cmake
ret=$?
if [ $ret -ne 0 ]
then
exit $ret
fi
make
ret=$?
if [ $ret -ne 0 ]
then
exit $ret
fi
fi
exit 0

59
ci/build_cmake_embedded.sh Executable file
View File

@@ -0,0 +1,59 @@
#!/bin/bash
cd example/cmake
ret=$?
if [ $ret -ne 0 ]
then
exit $ret
fi
rm -f msgpack-c
ret=$?
if [ $ret -ne 0 ]
then
exit $ret
fi
ln -s ../.. msgpack-c
ret=$?
if [ $ret -ne 0 ]
then
exit $ret
fi
mkdir build
ret=$?
if [ $ret -ne 0 ]
then
exit $ret
fi
cd build
ret=$?
if [ $ret -ne 0 ]
then
exit $ret
fi
cmake -DEXAMPLE_MSGPACK_EMBEDDED=ON ..
ret=$?
if [ $ret -ne 0 ]
then
exit $ret
fi
make example example-static
ret=$?
if [ $ret -ne 0 ]
then
exit $ret
fi
exit 0

55
cmake/CodeCoverage.cmake Normal file
View File

@@ -0,0 +1,55 @@
# Check prereqs
FIND_PROGRAM(GCOV_PATH gcov)
FIND_PROGRAM(LCOV_PATH lcov)
FIND_PROGRAM(GENHTML_PATH genhtml)
IF(NOT GCOV_PATH)
MESSAGE(FATAL_ERROR "gcov not found! Aborting...")
ENDIF()
IF(NOT CMAKE_COMPILER_IS_GNUCC AND NOT CMAKE_COMPILER_IS_GNUCXX)
# Clang version 3.0.0 and greater now supports gcov as well.
MESSAGE(STATUS "Compiler is not GNU gcc! Clang Version 3.0.0 and greater supports gcov as well, but older versions don't.")
IF(NOT "${CMAKE_C_COMPILER_ID}" MATCHES "Clang" AND NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
MESSAGE(FATAL_ERROR "Compiler is not GNU gcc! Aborting...")
ENDIF()
ENDIF()
SET(COVERAGE_FLAGS "-g -O0 --coverage")
FUNCTION(SETUP_TARGET_FOR_COVERAGE _targetname _testrunner _outputname)
IF(NOT LCOV_PATH)
MESSAGE(FATAL_ERROR "lcov not found! Aborting...")
ENDIF()
IF(NOT GENHTML_PATH)
MESSAGE(FATAL_ERROR "genhtml not found! Aborting...")
ENDIF()
# Setup target
ADD_CUSTOM_TARGET(${_targetname}
# Cleanup lcov
${LCOV_PATH} --directory . --zerocounters
# Run tests
COMMAND ${_testrunner} ${ARGV3}
# Capturing lcov counters and generating report
COMMAND ${LCOV_PATH} --directory . --capture --output-file ${_outputname}.info --base-directory ${CMAKE_SOURCE_DIR} --no-external --quiet
COMMAND ${LCOV_PATH} --remove ${_outputname}.info '*/test/*' '*/fuzz/*' --output-file ${_outputname}.info.cleaned --quiet
COMMAND ${GENHTML_PATH} -o ${_outputname} ${_outputname}.info.cleaned --prefix ${CMAKE_SOURCE_DIR}
# COMMAND ${CMAKE_COMMAND} -E remove ${_outputname}.info ${_outputname}.info.cleaned
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
)
# Show info where to find the report
ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD
COMMAND ;
COMMENT "Open ./${_outputname}/index.html in your browser to view the coverage report."
)
ENDFUNCTION()

952
cmake/pack_template.h.in Normal file
View File

@@ -0,0 +1,952 @@
/*
* MessagePack packing routine template
*
* Copyright (C) 2008-2010 FURUHASHI Sadayuki
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef MSGPACK_ENDIAN_BIG_BYTE
#define MSGPACK_ENDIAN_BIG_BYTE @MSGPACK_ENDIAN_BIG_BYTE@
#endif
#ifndef MSGPACK_ENDIAN_LITTLE_BYTE
#define MSGPACK_ENDIAN_LITTLE_BYTE @MSGPACK_ENDIAN_LITTLE_BYTE@
#endif
#if MSGPACK_ENDIAN_LITTLE_BYTE
#define TAKE8_8(d) ((uint8_t*)&d)[0]
#define TAKE8_16(d) ((uint8_t*)&d)[0]
#define TAKE8_32(d) ((uint8_t*)&d)[0]
#define TAKE8_64(d) ((uint8_t*)&d)[0]
#elif MSGPACK_ENDIAN_BIG_BYTE
#define TAKE8_8(d) ((uint8_t*)&d)[0]
#define TAKE8_16(d) ((uint8_t*)&d)[1]
#define TAKE8_32(d) ((uint8_t*)&d)[3]
#define TAKE8_64(d) ((uint8_t*)&d)[7]
#else
#error msgpack-c supports only big endian and little endian
#endif
#ifndef msgpack_pack_inline_func
#error msgpack_pack_inline_func template is not defined
#endif
#ifndef msgpack_pack_user
#error msgpack_pack_user type is not defined
#endif
#ifndef msgpack_pack_append_buffer
#error msgpack_pack_append_buffer callback is not defined
#endif
#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable : 4204) /* nonstandard extension used: non-constant aggregate initializer */
#endif
/*
* Integer
*/
#define msgpack_pack_real_uint8(x, d) \
do { \
if(d < (1<<7)) { \
/* fixnum */ \
msgpack_pack_append_buffer(x, &TAKE8_8(d), 1); \
} else { \
/* unsigned 8 */ \
unsigned char buf[2] = {0xcc, TAKE8_8(d)}; \
msgpack_pack_append_buffer(x, buf, 2); \
} \
} while(0)
#define msgpack_pack_real_uint16(x, d) \
do { \
if(d < (1<<7)) { \
/* fixnum */ \
msgpack_pack_append_buffer(x, &TAKE8_16(d), 1); \
} else if(d < (1<<8)) { \
/* unsigned 8 */ \
unsigned char buf[2] = {0xcc, TAKE8_16(d)}; \
msgpack_pack_append_buffer(x, buf, 2); \
} else { \
/* unsigned 16 */ \
unsigned char buf[3]; \
buf[0] = 0xcd; _msgpack_store16(&buf[1], (uint16_t)d); \
msgpack_pack_append_buffer(x, buf, 3); \
} \
} while(0)
#define msgpack_pack_real_uint32(x, d) \
do { \
if(d < (1<<8)) { \
if(d < (1<<7)) { \
/* fixnum */ \
msgpack_pack_append_buffer(x, &TAKE8_32(d), 1); \
} else { \
/* unsigned 8 */ \
unsigned char buf[2] = {0xcc, TAKE8_32(d)}; \
msgpack_pack_append_buffer(x, buf, 2); \
} \
} else { \
if(d < (1<<16)) { \
/* unsigned 16 */ \
unsigned char buf[3]; \
buf[0] = 0xcd; _msgpack_store16(&buf[1], (uint16_t)d); \
msgpack_pack_append_buffer(x, buf, 3); \
} else { \
/* unsigned 32 */ \
unsigned char buf[5]; \
buf[0] = 0xce; _msgpack_store32(&buf[1], (uint32_t)d); \
msgpack_pack_append_buffer(x, buf, 5); \
} \
} \
} while(0)
#define msgpack_pack_real_uint64(x, d) \
do { \
if(d < (1ULL<<8)) { \
if(d < (1ULL<<7)) { \
/* fixnum */ \
msgpack_pack_append_buffer(x, &TAKE8_64(d), 1); \
} else { \
/* unsigned 8 */ \
unsigned char buf[2] = {0xcc, TAKE8_64(d)}; \
msgpack_pack_append_buffer(x, buf, 2); \
} \
} else { \
if(d < (1ULL<<16)) { \
/* unsigned 16 */ \
unsigned char buf[3]; \
buf[0] = 0xcd; _msgpack_store16(&buf[1], (uint16_t)d); \
msgpack_pack_append_buffer(x, buf, 3); \
} else if(d < (1ULL<<32)) { \
/* unsigned 32 */ \
unsigned char buf[5]; \
buf[0] = 0xce; _msgpack_store32(&buf[1], (uint32_t)d); \
msgpack_pack_append_buffer(x, buf, 5); \
} else { \
/* unsigned 64 */ \
unsigned char buf[9]; \
buf[0] = 0xcf; _msgpack_store64(&buf[1], d); \
msgpack_pack_append_buffer(x, buf, 9); \
} \
} \
} while(0)
#define msgpack_pack_real_int8(x, d) \
do { \
if(d < -(1<<5)) { \
/* signed 8 */ \
unsigned char buf[2] = {0xd0, TAKE8_8(d)}; \
msgpack_pack_append_buffer(x, buf, 2); \
} else { \
/* fixnum */ \
msgpack_pack_append_buffer(x, &TAKE8_8(d), 1); \
} \
} while(0)
#define msgpack_pack_real_int16(x, d) \
do { \
if(d < -(1<<5)) { \
if(d < -(1<<7)) { \
/* signed 16 */ \
unsigned char buf[3]; \
buf[0] = 0xd1; _msgpack_store16(&buf[1], (int16_t)d); \
msgpack_pack_append_buffer(x, buf, 3); \
} else { \
/* signed 8 */ \
unsigned char buf[2] = {0xd0, TAKE8_16(d)}; \
msgpack_pack_append_buffer(x, buf, 2); \
} \
} else if(d < (1<<7)) { \
/* fixnum */ \
msgpack_pack_append_buffer(x, &TAKE8_16(d), 1); \
} else { \
if(d < (1<<8)) { \
/* unsigned 8 */ \
unsigned char buf[2] = {0xcc, TAKE8_16(d)}; \
msgpack_pack_append_buffer(x, buf, 2); \
} else { \
/* unsigned 16 */ \
unsigned char buf[3]; \
buf[0] = 0xcd; _msgpack_store16(&buf[1], (uint16_t)d); \
msgpack_pack_append_buffer(x, buf, 3); \
} \
} \
} while(0)
#define msgpack_pack_real_int32(x, d) \
do { \
if(d < -(1<<5)) { \
if(d < -(1<<15)) { \
/* signed 32 */ \
unsigned char buf[5]; \
buf[0] = 0xd2; _msgpack_store32(&buf[1], (int32_t)d); \
msgpack_pack_append_buffer(x, buf, 5); \
} else if(d < -(1<<7)) { \
/* signed 16 */ \
unsigned char buf[3]; \
buf[0] = 0xd1; _msgpack_store16(&buf[1], (int16_t)d); \
msgpack_pack_append_buffer(x, buf, 3); \
} else { \
/* signed 8 */ \
unsigned char buf[2] = {0xd0, TAKE8_32(d)}; \
msgpack_pack_append_buffer(x, buf, 2); \
} \
} else if(d < (1<<7)) { \
/* fixnum */ \
msgpack_pack_append_buffer(x, &TAKE8_32(d), 1); \
} else { \
if(d < (1<<8)) { \
/* unsigned 8 */ \
unsigned char buf[2] = {0xcc, TAKE8_32(d)}; \
msgpack_pack_append_buffer(x, buf, 2); \
} else if(d < (1<<16)) { \
/* unsigned 16 */ \
unsigned char buf[3]; \
buf[0] = 0xcd; _msgpack_store16(&buf[1], (uint16_t)d); \
msgpack_pack_append_buffer(x, buf, 3); \
} else { \
/* unsigned 32 */ \
unsigned char buf[5]; \
buf[0] = 0xce; _msgpack_store32(&buf[1], (uint32_t)d); \
msgpack_pack_append_buffer(x, buf, 5); \
} \
} \
} while(0)
#define msgpack_pack_real_int64(x, d) \
do { \
if(d < -(1LL<<5)) { \
if(d < -(1LL<<15)) { \
if(d < -(1LL<<31)) { \
/* signed 64 */ \
unsigned char buf[9]; \
buf[0] = 0xd3; _msgpack_store64(&buf[1], d); \
msgpack_pack_append_buffer(x, buf, 9); \
} else { \
/* signed 32 */ \
unsigned char buf[5]; \
buf[0] = 0xd2; _msgpack_store32(&buf[1], (int32_t)d); \
msgpack_pack_append_buffer(x, buf, 5); \
} \
} else { \
if(d < -(1<<7)) { \
/* signed 16 */ \
unsigned char buf[3]; \
buf[0] = 0xd1; _msgpack_store16(&buf[1], (int16_t)d); \
msgpack_pack_append_buffer(x, buf, 3); \
} else { \
/* signed 8 */ \
unsigned char buf[2] = {0xd0, TAKE8_64(d)}; \
msgpack_pack_append_buffer(x, buf, 2); \
} \
} \
} else if(d < (1<<7)) { \
/* fixnum */ \
msgpack_pack_append_buffer(x, &TAKE8_64(d), 1); \
} else { \
if(d < (1LL<<16)) { \
if(d < (1<<8)) { \
/* unsigned 8 */ \
unsigned char buf[2] = {0xcc, TAKE8_64(d)}; \
msgpack_pack_append_buffer(x, buf, 2); \
} else { \
/* unsigned 16 */ \
unsigned char buf[3]; \
buf[0] = 0xcd; _msgpack_store16(&buf[1], (uint16_t)d); \
msgpack_pack_append_buffer(x, buf, 3); \
} \
} else { \
if(d < (1LL<<32)) { \
/* unsigned 32 */ \
unsigned char buf[5]; \
buf[0] = 0xce; _msgpack_store32(&buf[1], (uint32_t)d); \
msgpack_pack_append_buffer(x, buf, 5); \
} else { \
/* unsigned 64 */ \
unsigned char buf[9]; \
buf[0] = 0xcf; _msgpack_store64(&buf[1], d); \
msgpack_pack_append_buffer(x, buf, 9); \
} \
} \
} \
} while(0)
#ifdef msgpack_pack_inline_func_fixint
msgpack_pack_inline_func_fixint(_uint8)(msgpack_pack_user x, uint8_t d)
{
unsigned char buf[2] = {0xcc, TAKE8_8(d)};
msgpack_pack_append_buffer(x, buf, 2);
}
msgpack_pack_inline_func_fixint(_uint16)(msgpack_pack_user x, uint16_t d)
{
unsigned char buf[3];
buf[0] = 0xcd; _msgpack_store16(&buf[1], d);
msgpack_pack_append_buffer(x, buf, 3);
}
msgpack_pack_inline_func_fixint(_uint32)(msgpack_pack_user x, uint32_t d)
{
unsigned char buf[5];
buf[0] = 0xce; _msgpack_store32(&buf[1], d);
msgpack_pack_append_buffer(x, buf, 5);
}
msgpack_pack_inline_func_fixint(_uint64)(msgpack_pack_user x, uint64_t d)
{
unsigned char buf[9];
buf[0] = 0xcf; _msgpack_store64(&buf[1], d);
msgpack_pack_append_buffer(x, buf, 9);
}
msgpack_pack_inline_func_fixint(_int8)(msgpack_pack_user x, int8_t d)
{
unsigned char buf[2] = {0xd0, TAKE8_8(d)};
msgpack_pack_append_buffer(x, buf, 2);
}
msgpack_pack_inline_func_fixint(_int16)(msgpack_pack_user x, int16_t d)
{
unsigned char buf[3];
buf[0] = 0xd1; _msgpack_store16(&buf[1], d);
msgpack_pack_append_buffer(x, buf, 3);
}
msgpack_pack_inline_func_fixint(_int32)(msgpack_pack_user x, int32_t d)
{
unsigned char buf[5];
buf[0] = 0xd2; _msgpack_store32(&buf[1], d);
msgpack_pack_append_buffer(x, buf, 5);
}
msgpack_pack_inline_func_fixint(_int64)(msgpack_pack_user x, int64_t d)
{
unsigned char buf[9];
buf[0] = 0xd3; _msgpack_store64(&buf[1], d);
msgpack_pack_append_buffer(x, buf, 9);
}
#undef msgpack_pack_inline_func_fixint
#endif
msgpack_pack_inline_func(_uint8)(msgpack_pack_user x, uint8_t d)
{
msgpack_pack_real_uint8(x, d);
}
msgpack_pack_inline_func(_uint16)(msgpack_pack_user x, uint16_t d)
{
msgpack_pack_real_uint16(x, d);
}
msgpack_pack_inline_func(_uint32)(msgpack_pack_user x, uint32_t d)
{
msgpack_pack_real_uint32(x, d);
}
msgpack_pack_inline_func(_uint64)(msgpack_pack_user x, uint64_t d)
{
msgpack_pack_real_uint64(x, d);
}
msgpack_pack_inline_func(_int8)(msgpack_pack_user x, int8_t d)
{
msgpack_pack_real_int8(x, d);
}
msgpack_pack_inline_func(_int16)(msgpack_pack_user x, int16_t d)
{
msgpack_pack_real_int16(x, d);
}
msgpack_pack_inline_func(_int32)(msgpack_pack_user x, int32_t d)
{
msgpack_pack_real_int32(x, d);
}
msgpack_pack_inline_func(_int64)(msgpack_pack_user x, int64_t d)
{
msgpack_pack_real_int64(x, d);
}
msgpack_pack_inline_func(_char)(msgpack_pack_user x, char d)
{
#if defined(CHAR_MIN)
#if CHAR_MIN < 0
msgpack_pack_real_int8(x, d);
#else
msgpack_pack_real_uint8(x, d);
#endif
#else
#error CHAR_MIN is not defined
#endif
}
msgpack_pack_inline_func(_signed_char)(msgpack_pack_user x, signed char d)
{
msgpack_pack_real_int8(x, d);
}
msgpack_pack_inline_func(_unsigned_char)(msgpack_pack_user x, unsigned char d)
{
msgpack_pack_real_uint8(x, d);
}
#ifdef msgpack_pack_inline_func_cint
msgpack_pack_inline_func_cint(_short)(msgpack_pack_user x, short d)
{
#if defined(SIZEOF_SHORT)
#if SIZEOF_SHORT == 2
msgpack_pack_real_int16(x, d);
#elif SIZEOF_SHORT == 4
msgpack_pack_real_int32(x, d);
#else
msgpack_pack_real_int64(x, d);
#endif
#elif defined(SHRT_MAX)
#if SHRT_MAX == 0x7fff
msgpack_pack_real_int16(x, d);
#elif SHRT_MAX == 0x7fffffff
msgpack_pack_real_int32(x, d);
#else
msgpack_pack_real_int64(x, d);
#endif
#else
if(sizeof(short) == 2) {
msgpack_pack_real_int16(x, d);
} else if(sizeof(short) == 4) {
msgpack_pack_real_int32(x, d);
} else {
msgpack_pack_real_int64(x, d);
}
#endif
}
msgpack_pack_inline_func_cint(_int)(msgpack_pack_user x, int d)
{
#if defined(SIZEOF_INT)
#if SIZEOF_INT == 2
msgpack_pack_real_int16(x, d);
#elif SIZEOF_INT == 4
msgpack_pack_real_int32(x, d);
#else
msgpack_pack_real_int64(x, d);
#endif
#elif defined(INT_MAX)
#if INT_MAX == 0x7fff
msgpack_pack_real_int16(x, d);
#elif INT_MAX == 0x7fffffff
msgpack_pack_real_int32(x, d);
#else
msgpack_pack_real_int64(x, d);
#endif
#else
if(sizeof(int) == 2) {
msgpack_pack_real_int16(x, d);
} else if(sizeof(int) == 4) {
msgpack_pack_real_int32(x, d);
} else {
msgpack_pack_real_int64(x, d);
}
#endif
}
msgpack_pack_inline_func_cint(_long)(msgpack_pack_user x, long d)
{
#if defined(SIZEOF_LONG)
#if SIZEOF_LONG == 2
msgpack_pack_real_int16(x, d);
#elif SIZEOF_LONG == 4
msgpack_pack_real_int32(x, d);
#else
msgpack_pack_real_int64(x, d);
#endif
#elif defined(LONG_MAX)
#if LONG_MAX == 0x7fffL
msgpack_pack_real_int16(x, d);
#elif LONG_MAX == 0x7fffffffL
msgpack_pack_real_int32(x, d);
#else
msgpack_pack_real_int64(x, d);
#endif
#else
if(sizeof(long) == 2) {
msgpack_pack_real_int16(x, d);
} else if(sizeof(long) == 4) {
msgpack_pack_real_int32(x, d);
} else {
msgpack_pack_real_int64(x, d);
}
#endif
}
msgpack_pack_inline_func_cint(_long_long)(msgpack_pack_user x, long long d)
{
#if defined(SIZEOF_LONG_LONG)
#if SIZEOF_LONG_LONG == 2
msgpack_pack_real_int16(x, d);
#elif SIZEOF_LONG_LONG == 4
msgpack_pack_real_int32(x, d);
#else
msgpack_pack_real_int64(x, d);
#endif
#elif defined(LLONG_MAX)
#if LLONG_MAX == 0x7fffL
msgpack_pack_real_int16(x, d);
#elif LLONG_MAX == 0x7fffffffL
msgpack_pack_real_int32(x, d);
#else
msgpack_pack_real_int64(x, d);
#endif
#else
if(sizeof(long long) == 2) {
msgpack_pack_real_int16(x, d);
} else if(sizeof(long long) == 4) {
msgpack_pack_real_int32(x, d);
} else {
msgpack_pack_real_int64(x, d);
}
#endif
}
msgpack_pack_inline_func_cint(_unsigned_short)(msgpack_pack_user x, unsigned short d)
{
#if defined(SIZEOF_SHORT)
#if SIZEOF_SHORT == 2
msgpack_pack_real_uint16(x, d);
#elif SIZEOF_SHORT == 4
msgpack_pack_real_uint32(x, d);
#else
msgpack_pack_real_uint64(x, d);
#endif
#elif defined(USHRT_MAX)
#if USHRT_MAX == 0xffffU
msgpack_pack_real_uint16(x, d);
#elif USHRT_MAX == 0xffffffffU
msgpack_pack_real_uint32(x, d);
#else
msgpack_pack_real_uint64(x, d);
#endif
#else
if(sizeof(unsigned short) == 2) {
msgpack_pack_real_uint16(x, d);
} else if(sizeof(unsigned short) == 4) {
msgpack_pack_real_uint32(x, d);
} else {
msgpack_pack_real_uint64(x, d);
}
#endif
}
msgpack_pack_inline_func_cint(_unsigned_int)(msgpack_pack_user x, unsigned int d)
{
#if defined(SIZEOF_INT)
#if SIZEOF_INT == 2
msgpack_pack_real_uint16(x, d);
#elif SIZEOF_INT == 4
msgpack_pack_real_uint32(x, d);
#else
msgpack_pack_real_uint64(x, d);
#endif
#elif defined(UINT_MAX)
#if UINT_MAX == 0xffffU
msgpack_pack_real_uint16(x, d);
#elif UINT_MAX == 0xffffffffU
msgpack_pack_real_uint32(x, d);
#else
msgpack_pack_real_uint64(x, d);
#endif
#else
if(sizeof(unsigned int) == 2) {
msgpack_pack_real_uint16(x, d);
} else if(sizeof(unsigned int) == 4) {
msgpack_pack_real_uint32(x, d);
} else {
msgpack_pack_real_uint64(x, d);
}
#endif
}
msgpack_pack_inline_func_cint(_unsigned_long)(msgpack_pack_user x, unsigned long d)
{
#if defined(SIZEOF_LONG)
#if SIZEOF_LONG == 2
msgpack_pack_real_uint16(x, d);
#elif SIZEOF_LONG == 4
msgpack_pack_real_uint32(x, d);
#else
msgpack_pack_real_uint64(x, d);
#endif
#elif defined(ULONG_MAX)
#if ULONG_MAX == 0xffffUL
msgpack_pack_real_uint16(x, d);
#elif ULONG_MAX == 0xffffffffUL
msgpack_pack_real_uint32(x, d);
#else
msgpack_pack_real_uint64(x, d);
#endif
#else
if(sizeof(unsigned long) == 2) {
msgpack_pack_real_uint16(x, d);
} else if(sizeof(unsigned long) == 4) {
msgpack_pack_real_uint32(x, d);
} else {
msgpack_pack_real_uint64(x, d);
}
#endif
}
msgpack_pack_inline_func_cint(_unsigned_long_long)(msgpack_pack_user x, unsigned long long d)
{
#if defined(SIZEOF_LONG_LONG)
#if SIZEOF_LONG_LONG == 2
msgpack_pack_real_uint16(x, d);
#elif SIZEOF_LONG_LONG == 4
msgpack_pack_real_uint32(x, d);
#else
msgpack_pack_real_uint64(x, d);
#endif
#elif defined(ULLONG_MAX)
#if ULLONG_MAX == 0xffffUL
msgpack_pack_real_uint16(x, d);
#elif ULLONG_MAX == 0xffffffffUL
msgpack_pack_real_uint32(x, d);
#else
msgpack_pack_real_uint64(x, d);
#endif
#else
if(sizeof(unsigned long long) == 2) {
msgpack_pack_real_uint16(x, d);
} else if(sizeof(unsigned long long) == 4) {
msgpack_pack_real_uint32(x, d);
} else {
msgpack_pack_real_uint64(x, d);
}
#endif
}
#undef msgpack_pack_inline_func_cint
#endif
/*
* Float
*/
msgpack_pack_inline_func(_float)(msgpack_pack_user x, float d)
{
unsigned char buf[5];
union { float f; uint32_t i; } mem;
mem.f = d;
buf[0] = 0xca; _msgpack_store32(&buf[1], mem.i);
msgpack_pack_append_buffer(x, buf, 5);
}
msgpack_pack_inline_func(_double)(msgpack_pack_user x, double d)
{
unsigned char buf[9];
union { double f; uint64_t i; } mem;
mem.f = d;
buf[0] = 0xcb;
#if defined(TARGET_OS_IPHONE)
// ok
#elif defined(__arm__) && !(__ARM_EABI__) // arm-oabi
// https://github.com/msgpack/msgpack-perl/pull/1
mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
#endif
_msgpack_store64(&buf[1], mem.i);
msgpack_pack_append_buffer(x, buf, 9);
}
/*
* Nil
*/
msgpack_pack_inline_func(_nil)(msgpack_pack_user x)
{
static const unsigned char d = 0xc0;
msgpack_pack_append_buffer(x, &d, 1);
}
/*
* Boolean
*/
msgpack_pack_inline_func(_true)(msgpack_pack_user x)
{
static const unsigned char d = 0xc3;
msgpack_pack_append_buffer(x, &d, 1);
}
msgpack_pack_inline_func(_false)(msgpack_pack_user x)
{
static const unsigned char d = 0xc2;
msgpack_pack_append_buffer(x, &d, 1);
}
/*
* Array
*/
msgpack_pack_inline_func(_array)(msgpack_pack_user x, size_t n)
{
if(n < 16) {
unsigned char d = 0x90 | (uint8_t)n;
msgpack_pack_append_buffer(x, &d, 1);
} else if(n < 65536) {
unsigned char buf[3];
buf[0] = 0xdc; _msgpack_store16(&buf[1], (uint16_t)n);
msgpack_pack_append_buffer(x, buf, 3);
} else {
unsigned char buf[5];
buf[0] = 0xdd; _msgpack_store32(&buf[1], (uint32_t)n);
msgpack_pack_append_buffer(x, buf, 5);
}
}
/*
* Map
*/
msgpack_pack_inline_func(_map)(msgpack_pack_user x, size_t n)
{
if(n < 16) {
unsigned char d = 0x80 | (uint8_t)n;
msgpack_pack_append_buffer(x, &TAKE8_8(d), 1);
} else if(n < 65536) {
unsigned char buf[3];
buf[0] = 0xde; _msgpack_store16(&buf[1], (uint16_t)n);
msgpack_pack_append_buffer(x, buf, 3);
} else {
unsigned char buf[5];
buf[0] = 0xdf; _msgpack_store32(&buf[1], (uint32_t)n);
msgpack_pack_append_buffer(x, buf, 5);
}
}
/*
* Str
*/
msgpack_pack_inline_func(_str)(msgpack_pack_user x, size_t l)
{
if(l < 32) {
unsigned char d = 0xa0 | (uint8_t)l;
msgpack_pack_append_buffer(x, &TAKE8_8(d), 1);
} else if(l < 256) {
unsigned char buf[2];
buf[0] = 0xd9; buf[1] = (uint8_t)l;
msgpack_pack_append_buffer(x, buf, 2);
} else if(l < 65536) {
unsigned char buf[3];
buf[0] = 0xda; _msgpack_store16(&buf[1], (uint16_t)l);
msgpack_pack_append_buffer(x, buf, 3);
} else {
unsigned char buf[5];
buf[0] = 0xdb; _msgpack_store32(&buf[1], (uint32_t)l);
msgpack_pack_append_buffer(x, buf, 5);
}
}
msgpack_pack_inline_func(_str_body)(msgpack_pack_user x, const void* b, size_t l)
{
msgpack_pack_append_buffer(x, (const unsigned char*)b, l);
}
/*
* Raw (V4)
*/
msgpack_pack_inline_func(_v4raw)(msgpack_pack_user x, size_t l)
{
if(l < 32) {
unsigned char d = 0xa0 | (uint8_t)l;
msgpack_pack_append_buffer(x, &TAKE8_8(d), 1);
} else if(l < 65536) {
unsigned char buf[3];
buf[0] = 0xda; _msgpack_store16(&buf[1], (uint16_t)l);
msgpack_pack_append_buffer(x, buf, 3);
} else {
unsigned char buf[5];
buf[0] = 0xdb; _msgpack_store32(&buf[1], (uint32_t)l);
msgpack_pack_append_buffer(x, buf, 5);
}
}
msgpack_pack_inline_func(_v4raw_body)(msgpack_pack_user x, const void* b, size_t l)
{
msgpack_pack_append_buffer(x, (const unsigned char*)b, l);
}
/*
* Bin
*/
msgpack_pack_inline_func(_bin)(msgpack_pack_user x, size_t l)
{
if(l < 256) {
unsigned char buf[2];
buf[0] = 0xc4; buf[1] = (uint8_t)l;
msgpack_pack_append_buffer(x, buf, 2);
} else if(l < 65536) {
unsigned char buf[3];
buf[0] = 0xc5; _msgpack_store16(&buf[1], (uint16_t)l);
msgpack_pack_append_buffer(x, buf, 3);
} else {
unsigned char buf[5];
buf[0] = 0xc6; _msgpack_store32(&buf[1], (uint32_t)l);
msgpack_pack_append_buffer(x, buf, 5);
}
}
msgpack_pack_inline_func(_bin_body)(msgpack_pack_user x, const void* b, size_t l)
{
msgpack_pack_append_buffer(x, (const unsigned char*)b, l);
}
/*
* Ext
*/
msgpack_pack_inline_func(_ext)(msgpack_pack_user x, size_t l, int8_t type)
{
switch(l) {
case 1: {
unsigned char buf[2];
buf[0] = 0xd4;
buf[1] = (unsigned char)type;
msgpack_pack_append_buffer(x, buf, 2);
} break;
case 2: {
unsigned char buf[2];
buf[0] = 0xd5;
buf[1] = (unsigned char)type;
msgpack_pack_append_buffer(x, buf, 2);
} break;
case 4: {
unsigned char buf[2];
buf[0] = 0xd6;
buf[1] = (unsigned char)type;
msgpack_pack_append_buffer(x, buf, 2);
} break;
case 8: {
unsigned char buf[2];
buf[0] = 0xd7;
buf[1] = (unsigned char)type;
msgpack_pack_append_buffer(x, buf, 2);
} break;
case 16: {
unsigned char buf[2];
buf[0] = 0xd8;
buf[1] = (unsigned char)type;
msgpack_pack_append_buffer(x, buf, 2);
} break;
default:
if(l < 256) {
unsigned char buf[3];
buf[0] = 0xc7;
buf[1] = (unsigned char)l;
buf[2] = (unsigned char)type;
msgpack_pack_append_buffer(x, buf, 3);
} else if(l < 65536) {
unsigned char buf[4];
buf[0] = 0xc8;
_msgpack_store16(&buf[1], l);
buf[3] = (unsigned char)type;
msgpack_pack_append_buffer(x, buf, 4);
} else {
unsigned char buf[6];
buf[0] = 0xc9;
_msgpack_store32(&buf[1], l);
buf[5] = (unsigned char)type;
msgpack_pack_append_buffer(x, buf, 6);
}
break;
}
}
msgpack_pack_inline_func(_ext_body)(msgpack_pack_user x, const void* b, size_t l)
{
msgpack_pack_append_buffer(x, (const unsigned char*)b, l);
}
msgpack_pack_inline_func(_timestamp)(msgpack_pack_user x, const msgpack_timestamp* d)
{
if ((((int64_t)d->tv_sec) >> 34) == 0) {
uint64_t data64 = ((uint64_t) d->tv_nsec << 34) | (uint64_t)d->tv_sec;
if ((data64 & 0xffffffff00000000L) == 0) {
// timestamp 32
char buf[4];
uint32_t data32 = (uint32_t)data64;
msgpack_pack_ext(x, 4, -1);
_msgpack_store32(buf, data32);
msgpack_pack_append_buffer(x, buf, 4);
} else {
// timestamp 64
char buf[8];
msgpack_pack_ext(x, 8, -1);
_msgpack_store64(buf, data64);
msgpack_pack_append_buffer(x, buf, 8);
}
} else {
// timestamp 96
char buf[12];
_msgpack_store32(&buf[0], d->tv_nsec);
_msgpack_store64(&buf[4], d->tv_sec);
msgpack_pack_ext(x, 12, -1);
msgpack_pack_append_buffer(x, buf, 12);
}
}
#undef msgpack_pack_inline_func
#undef msgpack_pack_user
#undef msgpack_pack_append_buffer
#undef TAKE8_8
#undef TAKE8_16
#undef TAKE8_32
#undef TAKE8_64
#undef msgpack_pack_real_uint8
#undef msgpack_pack_real_uint16
#undef msgpack_pack_real_uint32
#undef msgpack_pack_real_uint64
#undef msgpack_pack_real_int8
#undef msgpack_pack_real_int16
#undef msgpack_pack_real_int32
#undef msgpack_pack_real_int64
#if defined(_MSC_VER)
# pragma warning(pop)
#endif

228
cmake/sysdep.h.in Normal file
View File

@@ -0,0 +1,228 @@
/*
* MessagePack system dependencies
*
* Copyright (C) 2008-2010 FURUHASHI Sadayuki
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef MSGPACK_SYSDEP_H
#define MSGPACK_SYSDEP_H
#include <stdlib.h>
#include <stddef.h>
#ifndef MSGPACK_ENDIAN_BIG_BYTE
#define MSGPACK_ENDIAN_BIG_BYTE @MSGPACK_ENDIAN_BIG_BYTE@
#endif
#ifndef MSGPACK_ENDIAN_LITTLE_BYTE
#define MSGPACK_ENDIAN_LITTLE_BYTE @MSGPACK_ENDIAN_LITTLE_BYTE@
#endif
#if defined(_MSC_VER) && _MSC_VER <= 1800
# define snprintf(buf, len, format,...) _snprintf_s(buf, len, _TRUNCATE, format, __VA_ARGS__)
#endif
#if defined(_MSC_VER) && _MSC_VER < 1600
typedef signed __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef signed __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef signed __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
# if defined(_WIN64)
typedef signed __int64 intptr_t;
typedef unsigned __int64 uintptr_t;
# else
typedef signed __int32 intptr_t;
typedef unsigned __int32 uintptr_t;
# endif
#elif defined(_MSC_VER) // && _MSC_VER >= 1600
# include <stdint.h>
#else
# include <stdint.h>
# include <stdbool.h>
#endif
#if !defined(MSGPACK_DLLEXPORT)
#if defined(_MSC_VER)
# define MSGPACK_DLLEXPORT __declspec(dllexport)
#else /* _MSC_VER */
# define MSGPACK_DLLEXPORT
#endif /* _MSC_VER */
#endif
#ifdef _WIN32
# if defined(_KERNEL_MODE)
# define _msgpack_atomic_counter_header <ntddk.h>
# else
# define _msgpack_atomic_counter_header <windows.h>
# if !defined(WIN32_LEAN_AND_MEAN)
# define WIN32_LEAN_AND_MEAN
# endif /* WIN32_LEAN_AND_MEAN */
# endif
typedef long _msgpack_atomic_counter_t;
#if defined(_AMD64_) || defined(_M_X64) || defined(_M_ARM64)
# define _msgpack_sync_decr_and_fetch(ptr) _InterlockedDecrement(ptr)
# define _msgpack_sync_incr_and_fetch(ptr) _InterlockedIncrement(ptr)
#else
# define _msgpack_sync_decr_and_fetch(ptr) InterlockedDecrement(ptr)
# define _msgpack_sync_incr_and_fetch(ptr) InterlockedIncrement(ptr)
#endif
#elif defined(__GNUC__) && ((__GNUC__*10 + __GNUC_MINOR__) < 41)
# if defined(__cplusplus)
# define _msgpack_atomic_counter_header "msgpack/gcc_atomic.hpp"
# else
# define _msgpack_atomic_counter_header "msgpack/gcc_atomic.h"
# endif
#else
typedef unsigned int _msgpack_atomic_counter_t;
# define _msgpack_sync_decr_and_fetch(ptr) __sync_sub_and_fetch(ptr, 1)
# define _msgpack_sync_incr_and_fetch(ptr) __sync_add_and_fetch(ptr, 1)
#endif
#ifdef _WIN32
# ifdef __cplusplus
/* numeric_limits<T>::min,max */
# ifdef max
# undef max
# endif
# ifdef min
# undef min
# endif
# endif
#elif defined(unix) || defined(__unix) || defined(__APPLE__) || defined(__OpenBSD__)
#include <arpa/inet.h> /* __BYTE_ORDER */
# if defined(linux)
# include <byteswap.h>
# endif
#endif
#if !defined(MSGPACK_ENDIAN_LITTLE_BYTE) && !defined(MSGPACK_ENDIAN_BIG_BYTE)
#include <msgpack/predef/other/endian.h>
#endif // !defined(MSGPACK_ENDIAN_LITTLE_BYTE) && !defined(MSGPACK_ENDIAN_BIG_BYTE)
#if MSGPACK_ENDIAN_LITTLE_BYTE
# if defined(unix) || defined(__unix) || defined(__APPLE__) || defined(__OpenBSD__)
# define _msgpack_be16(x) ntohs((uint16_t)x)
# else
# if defined(ntohs)
# define _msgpack_be16(x) ntohs(x)
# elif defined(_byteswap_ushort) || (defined(_MSC_VER) && _MSC_VER >= 1400)
# define _msgpack_be16(x) ((uint16_t)_byteswap_ushort((unsigned short)x))
# else
# define _msgpack_be16(x) ( \
((((uint16_t)x) << 8) ) | \
((((uint16_t)x) >> 8) ) )
# endif
# endif
# if defined(unix) || defined(__unix) || defined(__APPLE__) || defined(__OpenBSD__)
# define _msgpack_be32(x) ntohl((uint32_t)x)
# else
# if defined(ntohl)
# define _msgpack_be32(x) ntohl(x)
# elif defined(_byteswap_ulong) || (defined(_MSC_VER) && _MSC_VER >= 1400)
# define _msgpack_be32(x) ((uint32_t)_byteswap_ulong((unsigned long)x))
# else
# define _msgpack_be32(x) \
( ((((uint32_t)x) << 24) ) | \
((((uint32_t)x) << 8) & 0x00ff0000U ) | \
((((uint32_t)x) >> 8) & 0x0000ff00U ) | \
((((uint32_t)x) >> 24) ) )
# endif
# endif
# if defined(_byteswap_uint64) || (defined(_MSC_VER) && _MSC_VER >= 1400)
# define _msgpack_be64(x) (_byteswap_uint64(x))
# elif defined(bswap_64)
# define _msgpack_be64(x) bswap_64(x)
# elif defined(__DARWIN_OSSwapInt64)
# define _msgpack_be64(x) __DARWIN_OSSwapInt64(x)
# else
# define _msgpack_be64(x) \
( ((((uint64_t)x) << 56) ) | \
((((uint64_t)x) << 40) & 0x00ff000000000000ULL ) | \
((((uint64_t)x) << 24) & 0x0000ff0000000000ULL ) | \
((((uint64_t)x) << 8) & 0x000000ff00000000ULL ) | \
((((uint64_t)x) >> 8) & 0x00000000ff000000ULL ) | \
((((uint64_t)x) >> 24) & 0x0000000000ff0000ULL ) | \
((((uint64_t)x) >> 40) & 0x000000000000ff00ULL ) | \
((((uint64_t)x) >> 56) ) )
# endif
#elif MSGPACK_ENDIAN_BIG_BYTE
# define _msgpack_be16(x) (x)
# define _msgpack_be32(x) (x)
# define _msgpack_be64(x) (x)
#else
# error msgpack-c supports only big endian and little endian
#endif /* MSGPACK_ENDIAN_LITTLE_BYTE */
#define _msgpack_load16(cast, from, to) do { \
memcpy((cast*)(to), (from), sizeof(cast)); \
*(to) = (cast)_msgpack_be16(*(to)); \
} while (0);
#define _msgpack_load32(cast, from, to) do { \
memcpy((cast*)(to), (from), sizeof(cast)); \
*(to) = (cast)_msgpack_be32(*(to)); \
} while (0);
#define _msgpack_load64(cast, from, to) do { \
memcpy((cast*)(to), (from), sizeof(cast)); \
*(to) = (cast)_msgpack_be64(*(to)); \
} while (0);
#define _msgpack_store16(to, num) \
do { uint16_t val = _msgpack_be16(num); memcpy(to, &val, 2); } while(0)
#define _msgpack_store32(to, num) \
do { uint32_t val = _msgpack_be32(num); memcpy(to, &val, 4); } while(0)
#define _msgpack_store64(to, num) \
do { uint64_t val = _msgpack_be64(num); memcpy(to, &val, 8); } while(0)
/*
#define _msgpack_load16(cast, from) \
({ cast val; memcpy(&val, (char*)from, 2); _msgpack_be16(val); })
#define _msgpack_load32(cast, from) \
({ cast val; memcpy(&val, (char*)from, 4); _msgpack_be32(val); })
#define _msgpack_load64(cast, from) \
({ cast val; memcpy(&val, (char*)from, 8); _msgpack_be64(val); })
*/
#if !defined(__cplusplus) && defined(_MSC_VER)
# if !defined(_KERNEL_MODE)
# if !defined(FALSE)
# define FALSE (0)
# endif
# if !defined(TRUE)
# define TRUE (!FALSE)
# endif
# endif
# if _MSC_VER >= 1800
# include <stdbool.h>
# else
# define bool int
# define true TRUE
# define false FALSE
# endif
# define inline __inline
#endif
#ifdef __APPLE__
# include <TargetConditionals.h>
#endif
#endif /* msgpack/sysdep.h */

36
codecov.yml Normal file
View File

@@ -0,0 +1,36 @@
codecov:
notify:
require_ci_to_pass: yes
coverage:
precision: 2
round: down
range: "70...100"
status:
project: yes
patch: yes
changes: no
parsers:
gcov:
branch_detection:
conditional: yes
loop: yes
method: no
macro: no
comment:
layout: "header, diff"
behavior: default
require_changes: no
ignore:
- "test"
- "fuzz"
- "erb"
- "ci"
- "cmake"
- "examle"
- "external"
- "usr"

44
example/CMakeLists.txt Normal file
View File

@@ -0,0 +1,44 @@
FIND_PACKAGE (cJSON)
LIST (APPEND exec_PROGRAMS
boundary.c
lib_buffer_unpack.c
simple_c.c
speed_test_uint32_array.c
speed_test_uint64_array.c
user_buffer_unpack.c
)
IF (cJSON_FOUND)
LIST (APPEND exec_PROGRAMS jsonconv.c)
ENDIF ()
FOREACH (source_file ${exec_PROGRAMS})
GET_FILENAME_COMPONENT (source_file_we ${source_file} NAME_WE)
ADD_EXECUTABLE (
${source_file_we}
${source_file}
)
TARGET_LINK_LIBRARIES (${source_file_we}
msgpackc
)
IF ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
SET_PROPERTY (TARGET ${source_file_we} APPEND_STRING PROPERTY COMPILE_FLAGS " -Wall -Wextra")
ENDIF ()
IF ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
SET_PROPERTY (TARGET ${source_file_we} APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-mismatched-tags")
ENDIF ()
IF ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
IF (CMAKE_C_FLAGS MATCHES "/W[0-4]")
STRING(REGEX REPLACE "/W[0-4]" "/W3 /WX" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
ELSE ()
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3 /WX")
ENDIF ()
ENDIF ()
ENDFOREACH ()
IF (cJSON_FOUND)
TARGET_LINK_LIBRARIES (jsonconv ${CJSON_LIBRARIES})
TARGET_INCLUDE_DIRECTORIES(jsonconv PRIVATE ${CJSON_INCLUDE_DIRS})
ENDIF ()

296
example/boundary.c Normal file
View File

@@ -0,0 +1,296 @@
/* gcc boundary.c -o boundary -Wconversion -Wpointer-sign */
#include <msgpack.h>
#include <stdio.h>
#include <assert.h>
static inline unsigned char atohex(char a)
{
int x;
if (a >= 'a') {
x = a - 'a' + 10;
} else if (a >= 'A') {
x = a - 'A' + 10;
} else {
x = a - '0';
}
assert(x >= 0 && x < 16);
return (unsigned char)x;
}
// Return 0 if equal
static inline int bytesncmp(char *data, const char *bytes, size_t len)
{
size_t n = len >> 1;
size_t i = 0;
int diff;
for (; i < n; i++) {
diff = (unsigned char)data[i] - (atohex(bytes[2 * i]) << 4) - atohex(bytes[2 * i + 1]);
if (diff != 0) {
return diff;
}
}
return 0;
}
int main()
{
msgpack_sbuffer sbuf;
msgpack_packer *x;
size_t offset = 0;
char data[65536];
msgpack_timestamp ts[] = {
{ 0xFFFFFFFF, 0 },
{ 0x100000000, 0 },
{ 0x3FFFFFFFF, 0 },
{ 0x400000000, 0 },
{ INT64_MAX, UINT32_MAX }
};
#define check_sbuffer(b) \
do { \
size_t len = strlen(#b); \
assert((sbuf.size - offset) * 2 == len); \
assert(bytesncmp(sbuf.data + offset, #b, len) == 0); \
offset = sbuf.size; \
} while (0)
msgpack_sbuffer_init(&sbuf);
x = msgpack_packer_new(&sbuf, msgpack_sbuffer_write);
msgpack_pack_fix_uint8(x, 0); check_sbuffer(cc00); /* cc 00 */
msgpack_pack_fix_uint8(x, 0xFF); check_sbuffer(ccff); /* cc ff */
msgpack_pack_fix_uint16(x, 0); check_sbuffer(cd0000); /* cd 00 00 */
msgpack_pack_fix_uint16(x, 0xFFFF); check_sbuffer(cdffff); /* cd ff ff */
msgpack_pack_fix_uint32(x, 0); check_sbuffer(ce00000000); /* ce 00 00 00 00 */
msgpack_pack_fix_uint32(x, 0xFFFFFFFF); check_sbuffer(ceffffffff); /* ce ff ff ff ff */
msgpack_pack_fix_uint64(x, 0); check_sbuffer(cf0000000000000000); /* cf 00 00 00 00 00 00 00 00 */
msgpack_pack_fix_uint64(x, 0xFFFFFFFFFFFFFFFF); check_sbuffer(cfffffffffffffffff); /* cf ff ff ff ff ff ff ff ff */
msgpack_pack_uint8(x, 0); check_sbuffer(00); /* 00 */
msgpack_pack_uint8(x, 0x7F); check_sbuffer(7f); /* 7f */
msgpack_pack_uint8(x, 0x80); check_sbuffer(cc80); /* cc 80 */
msgpack_pack_uint8(x, 0xFF); check_sbuffer(ccff); /* cc ff */
msgpack_pack_uint16(x, 0); check_sbuffer(00); /* 00 */
msgpack_pack_uint16(x, 0x7F); check_sbuffer(7f); /* 7f */
msgpack_pack_uint16(x, 0x80); check_sbuffer(cc80); /* cc 80 */
msgpack_pack_uint16(x, 0xFF); check_sbuffer(ccff); /* cc ff */
msgpack_pack_uint16(x, 0x100); check_sbuffer(cd0100); /* cd 01 00 */
msgpack_pack_uint16(x, 0xFFFF); check_sbuffer(cdffff); /* cd ff ff */
msgpack_pack_uint32(x, 0); check_sbuffer(00); /* 00 */
msgpack_pack_uint32(x, 0x7F); check_sbuffer(7f); /* 7f */
msgpack_pack_uint32(x, 0x80); check_sbuffer(cc80); /* cc 80 */
msgpack_pack_uint32(x, 0xFF); check_sbuffer(ccff); /* cc ff */
msgpack_pack_uint32(x, 0x100); check_sbuffer(cd0100); /* cd 01 00 */
msgpack_pack_uint32(x, 0xFFFF); check_sbuffer(cdffff); /* cd ff ff */
msgpack_pack_uint32(x, 0x10000); check_sbuffer(ce00010000); /* ce 00 01 00 00 */
msgpack_pack_uint32(x, 0xFFFFFFFF); check_sbuffer(ceffffffff); /* ce ff ff ff ff */
msgpack_pack_uint64(x, 0); check_sbuffer(00); /* 00 */
msgpack_pack_uint64(x, 0x7F); check_sbuffer(7f); /* 7f */
msgpack_pack_uint64(x, 0x80); check_sbuffer(cc80); /* cc 80 */
msgpack_pack_uint64(x, 0xFF); check_sbuffer(ccff); /* cc ff */
msgpack_pack_uint64(x, 0x100); check_sbuffer(cd0100); /* cd 01 00 */
msgpack_pack_uint64(x, 0xFFFF); check_sbuffer(cdffff); /* cd ff ff */
msgpack_pack_uint64(x, 0x10000); check_sbuffer(ce00010000); /* ce 00 01 00 00 */
msgpack_pack_uint64(x, 0xFFFFFFFF); check_sbuffer(ceffffffff); /* ce ff ff ff ff */
msgpack_pack_uint64(x, 0x100000000); check_sbuffer(cf0000000100000000); /* cf 00 00 00 01 00 00 00 00 */
msgpack_pack_uint64(x, 0xFFFFFFFFFFFFFFFF); check_sbuffer(cfffffffffffffffff); /* cf ff ff ff ff ff ff ff ff */
msgpack_pack_fix_int8(x, 0x7F); check_sbuffer(d07f); /* d0 7f */
msgpack_pack_fix_int8(x, -0x7F-1); check_sbuffer(d080); /* d0 80 */
msgpack_pack_fix_int16(x, 0x7FFF); check_sbuffer(d17fff); /* d1 7f ff */
msgpack_pack_fix_int16(x, -0x7FFF-1); check_sbuffer(d18000); /* d1 80 00 */
msgpack_pack_fix_int32(x, 0x7FFFFFFF); check_sbuffer(d27fffffff); /* d2 7f ff ff ff */
msgpack_pack_fix_int32(x, -0x7FFFFFFF-1); check_sbuffer(d280000000); /* d2 80 00 00 00 */
msgpack_pack_fix_int64(x, 0x7FFFFFFFFFFFFFFF); check_sbuffer(d37fffffffffffffff); /* d3 7f ff ff ff ff ff ff ff */
msgpack_pack_fix_int64(x, -0x7FFFFFFFFFFFFFFF-1); check_sbuffer(d38000000000000000); /* d3 80 00 00 00 00 00 00 00 */
msgpack_pack_int8(x, -0x7F-1); check_sbuffer(d080); /* d0 80 */
msgpack_pack_int8(x, -0x21); check_sbuffer(d0df); /* d0 df */
msgpack_pack_int8(x, -0x20); check_sbuffer(e0); /* e0 */
msgpack_pack_int8(x, -1); check_sbuffer(ff); /* ff */
msgpack_pack_int8(x, 0); check_sbuffer(00); /* 00 */
msgpack_pack_int8(x, 0x7F); check_sbuffer(7f); /* 7f */
msgpack_pack_int16(x, -0x7FFF-1); check_sbuffer(d18000); /* d1 80 00 */
msgpack_pack_int16(x, -0x81); check_sbuffer(d1ff7f); /* d1 ff 7f */
msgpack_pack_int16(x, -0x80); check_sbuffer(d080); /* d0 80 */
msgpack_pack_int16(x, -0x21); check_sbuffer(d0df); /* d0 df */
msgpack_pack_int16(x, -0x20); check_sbuffer(e0); /* e0 */
msgpack_pack_int16(x, -0x1); check_sbuffer(ff); /* ff */
msgpack_pack_int16(x, 0); check_sbuffer(00); /* 00 */
msgpack_pack_int16(x, 0x7F); check_sbuffer(7f); /* 7f */
msgpack_pack_int16(x, 0x80); check_sbuffer(cc80); /* cc 80 */
msgpack_pack_int16(x, 0xFF); check_sbuffer(ccff); /* cc ff */
msgpack_pack_int16(x, 0x100); check_sbuffer(cd0100); /* cd 01 00 */
msgpack_pack_int16(x, 0x7FFF); check_sbuffer(cd7fff); /* cd 7f ff */
msgpack_pack_int32(x, -0x7FFFFFFF-1); check_sbuffer(d280000000); /* d2 80 00 00 00 */
msgpack_pack_int32(x, -0x8001); check_sbuffer(d2ffff7fff); /* d2 ff ff 7f ff */
msgpack_pack_int32(x, -0x8000); check_sbuffer(d18000); /* d1 80 00 */
msgpack_pack_int32(x, -0x81); check_sbuffer(d1ff7f); /* d1 ff 7f */
msgpack_pack_int32(x, -0x80); check_sbuffer(d080); /* d0 80 */
msgpack_pack_int32(x, -0x21); check_sbuffer(d0df); /* d0 df */
msgpack_pack_int32(x, -0x20); check_sbuffer(e0); /* e0 */
msgpack_pack_int32(x, -0x1); check_sbuffer(ff); /* ff */
msgpack_pack_int32(x, 0); check_sbuffer(00); /* 00 */
msgpack_pack_int32(x, 0x7F); check_sbuffer(7f); /* 7f */
msgpack_pack_int32(x, 0x80); check_sbuffer(cc80); /* cc 80 */
msgpack_pack_int32(x, 0xFF); check_sbuffer(ccff); /* cc ff */
msgpack_pack_int32(x, 0x100); check_sbuffer(cd0100); /* cd 01 00 */
msgpack_pack_int32(x, 0xFFFF); check_sbuffer(cdffff); /* cd ff ff */
msgpack_pack_int32(x, 0x10000); check_sbuffer(ce00010000); /* ce 00 01 00 00 */
msgpack_pack_int32(x, 0x7FFFFFFF); check_sbuffer(ce7fffffff); /* ce 7f ff ff ff */
msgpack_pack_int64(x, -0x7FFFFFFFFFFFFFFF-1); check_sbuffer(d38000000000000000); /* d3 80 00 00 00 00 00 00 00 */
msgpack_pack_int64(x, -((1LL<<31)+1)); check_sbuffer(d3ffffffff7fffffff); /* d3 ff ff ff ff 7f ff ff ff */
msgpack_pack_int64(x, -(1LL<<31)); check_sbuffer(d280000000); /* d2 80 00 00 00 */
msgpack_pack_int64(x, -0x8001); check_sbuffer(d2ffff7fff); /* d2 ff ff 7f ff */
msgpack_pack_int64(x, -0x8000); check_sbuffer(d18000); /* d1 80 00 */
msgpack_pack_int64(x, -0x81); check_sbuffer(d1ff7f); /* d1 ff 7f */
msgpack_pack_int64(x, -0x80); check_sbuffer(d080); /* d0 80 */
msgpack_pack_int64(x, -0x21); check_sbuffer(d0df); /* d0 df */
msgpack_pack_int64(x, -0x20); check_sbuffer(e0); /* e0 */
msgpack_pack_int64(x, -0x1); check_sbuffer(ff); /* ff */
msgpack_pack_int64(x, 0); check_sbuffer(00); /* 00 */
msgpack_pack_int64(x, 0x7F); check_sbuffer(7f); /* 7f */
msgpack_pack_int64(x, 0x80); check_sbuffer(cc80); /* cc 80 */
msgpack_pack_int64(x, 0xFF); check_sbuffer(ccff); /* cc ff */
msgpack_pack_int64(x, 0x100); check_sbuffer(cd0100); /* cd 01 00 */
msgpack_pack_int64(x, 0xFFFF); check_sbuffer(cdffff); /* cd ff ff */
msgpack_pack_int64(x, 0x10000); check_sbuffer(ce00010000); /* ce 00 01 00 00 */
msgpack_pack_int64(x, 0xFFFFFFFF); check_sbuffer(ceffffffff); /* ce ff ff ff ff */
msgpack_pack_int64(x, 0x100000000); check_sbuffer(cf0000000100000000); /* cf 00 00 00 01 00 00 00 00 */
msgpack_pack_int64(x, 0x7FFFFFFFFFFFFFFF); check_sbuffer(cf7fffffffffffffff); /* cf 7f ff ff ff ff ff ff ff */
msgpack_pack_nil(x); check_sbuffer(c0); /* c0 */
msgpack_pack_false(x); check_sbuffer(c2); /* c2 */
msgpack_pack_true(x); check_sbuffer(c3); /* c3 */
msgpack_pack_float(x, 1.0); check_sbuffer(ca3f800000); /* ca 3f 80 00 00 */
msgpack_pack_double(x, 1.0); check_sbuffer(cb3ff0000000000000); /* cb 3f f0 00 00 00 00 00 00 */
msgpack_pack_unsigned_char(x, UINT8_MAX); /* same as msgpack_pack_uint8() */
msgpack_pack_unsigned_short(x, (unsigned short)UINT64_MAX);
msgpack_pack_unsigned_int(x, (unsigned int)UINT64_MAX);
msgpack_pack_unsigned_long(x, (unsigned long)UINT64_MAX);
msgpack_pack_unsigned_long_long(x, (unsigned long long)UINT64_MAX);
msgpack_pack_signed_char(x, INT8_MAX); /* same as msgpack_pack_int8() */
#define check_sbuffer_n(b) \
do { \
size_t len = strlen(#b); \
assert(bytesncmp(sbuf.data + offset, #b, len) == 0); \
offset = sbuf.size; \
} while (0)
#define fill_str(n) msgpack_pack_str_body(x, data, n)
offset = sbuf.size;
msgpack_pack_str(x, 0); /* "" */ check_sbuffer(a0); /* a0 */
msgpack_pack_str(x, 31);
fill_str(31); check_sbuffer_n(bf); /* bf ... */
msgpack_pack_str(x, 32);
fill_str(32); check_sbuffer_n(d920); /* d9 20 ... */
msgpack_pack_str(x, 255);
fill_str(255); check_sbuffer_n(d9ff); /* d9 ff ... */
msgpack_pack_str(x, 256);
fill_str(256); check_sbuffer_n(da0100); /* da 01 00 ... */
msgpack_pack_str(x, 65535);
fill_str(65535); check_sbuffer_n(daffff); /* da ff ff ... */
msgpack_pack_str(x, 65536);
fill_str(65536); check_sbuffer_n(db00010000); /* db 00 01 00 00 ... */
#define fill_map(n) \
do { \
size_t i = 0; \
for (; i < n * 2; i++) { msgpack_pack_int8(x, 0x1); } \
} while (0);
msgpack_pack_map(x, 0); /* {} */ check_sbuffer(80); /* 80 */
msgpack_pack_map(x, 1);
fill_map(1); check_sbuffer_n(81); /* 81 ... */
msgpack_pack_map(x, 15);
fill_map(15); check_sbuffer_n(8f); /* 8f ... */
msgpack_pack_map(x, 16);
fill_map(16); check_sbuffer_n(de0010); /* de 00 10 ... */
msgpack_pack_map(x, 65535);
fill_map(65535); check_sbuffer_n(deffff); /* de ff ff ... */
msgpack_pack_map(x, 65536);
fill_map(65536); check_sbuffer_n(df00010000); /* df 00 01 00 00 ... */
#define fill_array(n) \
do { \
size_t i = 0; \
for (; i < n; i++) { msgpack_pack_int8(x, 0x1); } \
} while (0);
msgpack_pack_array(x, 0); /* [] */ check_sbuffer(90); /* 90 */
msgpack_pack_array(x, 1);
fill_array(1); check_sbuffer_n(91); /* 91 ... */
msgpack_pack_array(x, 15);
fill_array(15); check_sbuffer_n(9f); /* 9f ... */
msgpack_pack_array(x, 16);
fill_array(16); check_sbuffer_n(dc0010); /* dc 00 10 ... */
msgpack_pack_array(x, 65535);
fill_array(65535); check_sbuffer_n(dcffff); /* dc ff ff ... */
msgpack_pack_array(x, 65536);
fill_array(65536); check_sbuffer_n(dd00010000); /* dd 00 01 00 00 ... */
#define fill_bin(n) msgpack_pack_bin_body(x, data, n)
msgpack_pack_bin(x, 0); check_sbuffer(c400); /* c4 00 */
msgpack_pack_bin(x, 1);
fill_bin(1); check_sbuffer_n(c401); /* c4 01 ... */
msgpack_pack_bin(x, 255);
fill_bin(255); check_sbuffer_n(c4ff); /* c4 ff ... */
msgpack_pack_bin(x, 256);
fill_bin(256); check_sbuffer_n(c50100); /* c5 01 00 ... */
msgpack_pack_bin(x, 65535);
fill_bin(65535); check_sbuffer_n(c5ffff); /* c5 ff ff ... */
msgpack_pack_bin(x, 65536);
fill_bin(65536); check_sbuffer_n(c600010000); /* c6 00 01 00 00 ... */
#define fill_ext(n) msgpack_pack_ext_body(x, data, n)
msgpack_pack_ext(x, 1, 0x7F);
fill_ext(1); check_sbuffer_n(d47f); /* d4 7f ... */
msgpack_pack_ext(x, 2, 0x7F);
fill_ext(2); check_sbuffer_n(d57f); /* d5 7f ... */
msgpack_pack_ext(x, 4, 0x7F);
fill_ext(4); check_sbuffer_n(d67f); /* d6 7f ... */
msgpack_pack_ext(x, 8, 0x7F);
fill_ext(8); check_sbuffer_n(d77f); /* d7 7f ... */
msgpack_pack_ext(x, 16, 0x7F);
fill_ext(16); check_sbuffer_n(d87f); /* d8 7f ... */
msgpack_pack_ext(x, 0, 0x7F); check_sbuffer(c7007f); /* c7 00 7f */
msgpack_pack_ext(x, 3, 0x7F);
fill_ext(3); check_sbuffer_n(c7037f); /* c7 03 7f */
msgpack_pack_ext(x, 5, 0x7F);
fill_ext(5); check_sbuffer_n(c7057f); /* c7 05 7f */
msgpack_pack_ext(x, 17, 0x7F);
fill_ext(17); check_sbuffer_n(c7117f); /* c7 11 7f */
msgpack_pack_ext(x, 255, 0x7F);
fill_ext(255); check_sbuffer_n(c7ff7f); /* c7 ff 7f ... */
msgpack_pack_ext(x, 256, 0x7F);
fill_ext(256); check_sbuffer_n(c801007f); /* c8 01 00 7f ... */
msgpack_pack_ext(x, 65535, 0x7F);
fill_ext(65535); check_sbuffer_n(c8ffff7f); /* c8 ff ff 7f ... */
msgpack_pack_ext(x, 65536, 0x7F);
fill_ext(65536); check_sbuffer_n(c9000100007f); /* c9 00 01 00 00 7f ... */
msgpack_pack_timestamp(x, ts); check_sbuffer(d6ffffffffff); /* d6 ff ff ff ff ff */
msgpack_pack_timestamp(x, ts + 1); check_sbuffer(d7ff0000000100000000); /* d7 ff 00 00 00 01 00 00 00 00 */
msgpack_pack_timestamp(x, ts + 2); check_sbuffer(d7ff00000003ffffffff); /* d7 ff 00 00 00 03 ff ff ff ff */
msgpack_pack_timestamp(x, ts + 3); check_sbuffer(c70cff000000000000000400000000); /* c7 0c ff 00 00 00 00 00 00 00 04 00 00 00 00 */
msgpack_pack_timestamp(x, ts + 4); check_sbuffer(c70cffffffffff7fffffffffffffff); /* c7 0c ff ff ff ff ff 7f ff ff ff ff ff ff ff */
msgpack_sbuffer_destroy(&sbuf);
msgpack_packer_free(x);
return 0;
}

View File

@@ -0,0 +1,17 @@
cmake_minimum_required (VERSION 3.0)
project (example)
if(EXAMPLE_MSGPACK_EMBEDDED)
add_subdirectory(msgpack-c)
set(msgpack_DIR ${CMAKE_CURRENT_BINARY_DIR}/msgpack-c)
endif()
find_package(msgpack REQUIRED)
add_executable (${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}/../simple_c.c)
target_link_libraries(${PROJECT_NAME} msgpackc)
if(TARGET msgpackc-static)
add_executable (${PROJECT_NAME}-static ${CMAKE_CURRENT_LIST_DIR}/../simple_c.c)
target_link_libraries(${PROJECT_NAME}-static msgpackc-static)
endif()

419
example/jsonconv.c Normal file
View File

@@ -0,0 +1,419 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <msgpack.h>
#include <cjson/cJSON.h>
#if defined(_MSC_VER)
#if _MSC_VER >= 1800
#include <inttypes.h>
#else
#define PRIu64 "I64u"
#define PRIi64 "I64i"
#define PRIi8 "i"
#endif
#else
#include <inttypes.h>
#endif
#if defined(_KERNEL_MODE)
# undef snprintf
# define snprintf _snprintf
#endif
#define DEBUG(...) printf(__VA_ARGS__)
static char *format_string(const char *input)
{
const char *inptr;
char *output;
char *outptr;
size_t output_length = 0;
/* numbers of additional characters*/
size_t escape_characters = 0;
if (input == NULL) {
return NULL;
}
for (inptr = input; *inptr; inptr++) {
switch (*inptr) {
case '\"':
case '\\':
case '\b':
case '\f':
case '\n':
case '\r':
case '\t':
/* one character escape sequence */
escape_characters++;
break;
default:
break;
}
}
output_length = (size_t)(inptr - input) + escape_characters;
output = (char *)malloc(output_length + 1);
if (output == NULL) {
return NULL;
}
/* no add characters*/
if (escape_characters == 0) {
memcpy(output, input, output_length);
output[output_length] = '\0';
return output;
}
outptr = output;
/* copy string */
for (inptr = input; *inptr != '\0'; (void)inptr++, outptr++) {
if ((*inptr > 31) && (*inptr != '\"') && (*inptr != '\\')) {
/* normal character, copy */
*outptr = *inptr;
} else {
/* character needs to be escaped */
*outptr++ = '\\';
switch (*inptr)
{
case '\\':
*outptr = '\\';
break;
case '\"':
*outptr = '\"';
break;
case '\b':
*outptr = 'b';
break;
case '\f':
*outptr = 'f';
break;
case '\n':
*outptr = 'n';
break;
case '\r':
*outptr = 'r';
break;
case '\t':
*outptr = 't';
break;
default:
break;
}
}
}
output[output_length] = '\0';
return output;
}
/*
* Pack cJSON object.
* return 0 success, others failed
*/
static int parse_cjson_object(msgpack_packer *pk, cJSON *node)
{
int ret, sz, i;
cJSON *child;
char *strvalue;
if (node == NULL) {
return -1;
}
switch (node->type & 0xFF) {
case cJSON_Invalid:
return -1;
case cJSON_False:
return msgpack_pack_false(pk);
case cJSON_True:
return msgpack_pack_true(pk);
case cJSON_NULL:
return msgpack_pack_nil(pk);
case cJSON_String:
strvalue = format_string(node->valuestring);
if (strvalue != NULL) {
ret = msgpack_pack_str_with_body(pk, strvalue, strlen(strvalue));
free(strvalue);
return ret;
} else {
return -1;
}
case cJSON_Number:
if (isnan(node->valuedouble) || isinf(node->valuedouble)) {
ret = msgpack_pack_nil(pk);
} else if (node->valuedouble == node->valueint) {
ret = msgpack_pack_int(pk, node->valueint);
} else {
ret = msgpack_pack_double(pk, node->valuedouble);
}
return ret;
case cJSON_Array:
sz = cJSON_GetArraySize(node);
if (msgpack_pack_array(pk, sz) != 0) {
return -1;
}
for (i = 0; i < sz; i++) {
if (parse_cjson_object(pk, cJSON_GetArrayItem(node, i)) != 0) {
return -1;
}
}
return 0;
case cJSON_Object:
sz = cJSON_GetArraySize(node);
if (msgpack_pack_map(pk, sz) != 0) {
return -1;
}
for (i = 0; i < sz; i++) {
child = cJSON_GetArrayItem(node, i);
strvalue = format_string(child->string);
if (strvalue == NULL) {
return -1;
}
if (msgpack_pack_str_with_body(pk, strvalue, strlen(strvalue)) != 0) {
free(strvalue);
return -1;
}
free(strvalue);
if (parse_cjson_object(pk, child) != 0) {
return -1;
}
}
return 0;
default:
DEBUG("unknown type.\n");
return -1;
}
return 0;
}
/*
* Pack json string to msgpack format data.
* return 0 success, -1 failed
*/
int msgpack_pack_jsonstr(msgpack_packer *pk, const char *jsonstr)
{
int status;
cJSON *node;
const char *end = NULL;
if (pk == NULL || jsonstr == NULL) {
return -1;
}
node = cJSON_ParseWithOpts(jsonstr, &end, 1);
if (node == NULL) {
DEBUG("parse error: unexpected string `%s`\n", end);
return -1;
}
status = parse_cjson_object(pk, node);
cJSON_Delete(node);
return status;
}
static int bytes_contain_zero(const msgpack_object_bin *bin)
{
size_t i;
for (i = 0; i < bin->size; i++) {
if (bin->ptr[i] == 0) {
return 1;
}
}
return 0;
}
#define PRINT_JSONSTR_CALL(ret, func, aux_buffer, aux_buffer_size, ...) \
ret = func(aux_buffer, aux_buffer_size, __VA_ARGS__); \
if (ret <= 0) \
return ret; \
if (ret > aux_buffer_size) \
return 0; \
aux_buffer = aux_buffer + ret; \
aux_buffer_size = aux_buffer_size - ret
/*
* Convert msgpack format data to json string.
* return >0: success, 0: length of buffer not enough, -1: failed
*/
size_t msgpack_object_print_jsonstr(char *buffer, size_t length, const msgpack_object o)
{
char *aux_buffer = buffer;
size_t aux_buffer_size = length;
size_t ret;
switch (o.type) {
case MSGPACK_OBJECT_NIL:
PRINT_JSONSTR_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "null");
break;
case MSGPACK_OBJECT_BOOLEAN:
PRINT_JSONSTR_CALL(ret, snprintf, aux_buffer, aux_buffer_size, (o.via.boolean ? "true" : "false"));
break;
case MSGPACK_OBJECT_POSITIVE_INTEGER:
#if defined(PRIu64)
PRINT_JSONSTR_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%" PRIu64, o.via.u64);
#else
if (o.via.u64 > ULONG_MAX) {
PRINT_JSONSTR_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%lu", ULONG_MAX);
} else {
PRINT_JSONSTR_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%lu", (unsigned long)o.via.u64);
}
#endif
break;
case MSGPACK_OBJECT_NEGATIVE_INTEGER:
#if defined(PRIi64)
PRINT_JSONSTR_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%" PRIi64, o.via.i64);
#else
if (o.via.i64 > LONG_MAX) {
PRINT_JSONSTR_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%ld", LONG_MAX);
} else if (o.via.i64 < LONG_MIN) {
PRINT_JSONSTR_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%ld", LONG_MIN);
} else {
PRINT_JSONSTR_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%ld", (signed long)o.via.i64);
}
#endif
break;
case MSGPACK_OBJECT_FLOAT32:
case MSGPACK_OBJECT_FLOAT64:
PRINT_JSONSTR_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%f", o.via.f64);
break;
case MSGPACK_OBJECT_STR:
PRINT_JSONSTR_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\"%.*s\"", (int)o.via.str.size, o.via.str.ptr);
break;
case MSGPACK_OBJECT_BIN:
if (bytes_contain_zero(&o.via.bin)) {
DEBUG("the value contains zero\n");
return -1;
}
PRINT_JSONSTR_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\"%.*s\"", (int)o.via.bin.size, o.via.bin.ptr);
break;
case MSGPACK_OBJECT_EXT:
DEBUG("not support type: MSGPACK_OBJECT_EXT.\n");
return -1;
case MSGPACK_OBJECT_ARRAY:
PRINT_JSONSTR_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "[");
if (o.via.array.size != 0) {
msgpack_object *p = o.via.array.ptr;
msgpack_object *const pend = o.via.array.ptr + o.via.array.size;
PRINT_JSONSTR_CALL(ret, msgpack_object_print_jsonstr, aux_buffer, aux_buffer_size, *p);
++p;
for (; p < pend; ++p) {
PRINT_JSONSTR_CALL(ret, snprintf, aux_buffer, aux_buffer_size, ",");
PRINT_JSONSTR_CALL(ret, msgpack_object_print_jsonstr, aux_buffer, aux_buffer_size, *p);
}
}
PRINT_JSONSTR_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "]");
break;
case MSGPACK_OBJECT_MAP:
PRINT_JSONSTR_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "{");
if (o.via.map.size != 0) {
msgpack_object_kv *p = o.via.map.ptr;
msgpack_object_kv *const pend = o.via.map.ptr + o.via.map.size;
for (; p < pend; ++p) {
if (p->key.type != MSGPACK_OBJECT_STR) {
DEBUG("the key of in a map must be string.\n");
return -1;
}
if (p != o.via.map.ptr) {
PRINT_JSONSTR_CALL(ret, snprintf, aux_buffer, aux_buffer_size, ",");
}
PRINT_JSONSTR_CALL(ret, msgpack_object_print_jsonstr, aux_buffer, aux_buffer_size, p->key);
PRINT_JSONSTR_CALL(ret, snprintf, aux_buffer, aux_buffer_size, ":");
PRINT_JSONSTR_CALL(ret, msgpack_object_print_jsonstr, aux_buffer, aux_buffer_size, p->val);
}
}
PRINT_JSONSTR_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "}");
break;
default:
DEBUG("unknown type.\n");
return -1;
}
return length - aux_buffer_size;
}
#undef PRINT_JSONSTR_CALL
static void test(const char *name, const char *input, const char *expect)
{
msgpack_sbuffer sbuf;
{
// pack
msgpack_packer pk;
msgpack_sbuffer_init(&sbuf);
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
if (msgpack_pack_jsonstr(&pk, input) < 0) {
msgpack_sbuffer_destroy(&sbuf);
printf("%s: invalid json string.\n", name);
return;
}
}
{
// unpack
#define MAX_JSONLEN 1024
msgpack_zone z;
msgpack_object obj;
size_t jsonstrlen = MAX_JSONLEN - 1;
char jsonparsed[MAX_JSONLEN];
msgpack_zone_init(&z, jsonstrlen);
msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj);
jsonstrlen = msgpack_object_print_jsonstr(jsonparsed, jsonstrlen, obj);
jsonparsed[jsonstrlen] = '\0';
//compare input and output
if (expect == NULL) {
expect = input;
}
if (strcmp(expect, jsonparsed) == 0) {
printf("%s: ok\n", name);
} else {
printf("%s: failed\n", name);
}
msgpack_zone_destroy(&z);
}
msgpack_sbuffer_destroy(&sbuf);
}
int main()
{
test("null", "null", NULL);
test("boolean", "false", NULL);
test("single string", "\"frsyuki\"", NULL);
test("single number", "\"100\"", NULL);
test("space", "[{\"valuespace\":\"\",\"\":\"keyspace\"},\"\",[\"\"]]", NULL);
test("quote", "\"My name is Tom (\\\"Bee\\\") Kobe\"", NULL);
test("escape", "\"\\\\b\\f\\n\\r\\t\"", NULL);
test("escape2", "\"\b\f\n\r\t\"", "\"\\b\\f\\n\\r\\t\"");
test("map", "{\"name\":\"Tom (\\\"Bee\\\") Kobe\",\"type\":\"image\",\"data\":{\"width\":360,\"height\":460,\"title\":\"View me\",\"ips\":[116,943,256,711]}}", NULL);
test("array", "[\"Sunday\",\"Monday\",\"Tuesday\",\"Wednesday\",\"Thursday\",\"Friday\",\"Saturday\"]", NULL);
test("number array", "[[101,121,-33],[119,911,171],[0,2,-3]]", NULL);
test("mix array", "[{\"name\":\"Tom\",\"city\":\"London\",\"country\":\"UK\",\"longitude\":23},{\"name\":\"Jack\",\"city\":\"Birmingham\",\"country\":\"UK\",\"longitude\":-22}]", NULL);
test("unicode", "\"\\u5C71\\u5DDD\\u7570\\u57DF\\u98A8\\u6708\\u540C\\u5929\"", "\"山川異域風月同天\"");
test("utf8", "\"山川異域風月同天\"", NULL);
test("double", "12.34", "12.340000");
return 0;
}

127
example/lib_buffer_unpack.c Normal file
View File

@@ -0,0 +1,127 @@
#include <msgpack.h>
#include <stdio.h>
#include <assert.h>
typedef struct receiver {
msgpack_sbuffer sbuf;
size_t rest;
} receiver;
void receiver_init(receiver *r) {
msgpack_packer pk;
msgpack_sbuffer_init(&r->sbuf);
msgpack_packer_init(&pk, &r->sbuf, msgpack_sbuffer_write);
/* 1st object */
msgpack_pack_array(&pk, 3);
msgpack_pack_int(&pk, 1);
msgpack_pack_true(&pk);
msgpack_pack_str(&pk, 7);
msgpack_pack_str_body(&pk, "example", 7);
/* 2nd object */
msgpack_pack_str(&pk, 6);
msgpack_pack_str_body(&pk, "second", 6);
/* 3rd object */
msgpack_pack_array(&pk, 2);
msgpack_pack_int(&pk, 42);
msgpack_pack_false(&pk);
r->rest = r->sbuf.size;
}
size_t receiver_recv(receiver *r, char* buf, size_t try_size) {
size_t off = r->sbuf.size - r->rest;
size_t actual_size = try_size;
if (actual_size > r->rest) actual_size = r->rest;
memcpy(buf, r->sbuf.data + off, actual_size);
r->rest -= actual_size;
return actual_size;
}
size_t receiver_to_unpacker(receiver* r, size_t request_size,
msgpack_unpacker *unpacker)
{
size_t recv_len;
// make sure there's enough room, or expand the unpacker accordingly
if (msgpack_unpacker_buffer_capacity(unpacker) < request_size) {
msgpack_unpacker_reserve_buffer(unpacker, request_size);
assert(msgpack_unpacker_buffer_capacity(unpacker) >= request_size);
}
recv_len = receiver_recv(r, msgpack_unpacker_buffer(unpacker),
request_size);
msgpack_unpacker_buffer_consumed(unpacker, recv_len);
return recv_len;
}
#define EACH_RECV_SIZE 4
void unpack(receiver* r) {
/* buf is allocated by unpacker. */
msgpack_unpacker* unp = msgpack_unpacker_new(100);
msgpack_unpacked result;
msgpack_unpack_return ret;
size_t recv_len;
int recv_count = 0;
int i = 0;
msgpack_unpacked_init(&result);
while (true) {
recv_len = receiver_to_unpacker(r, EACH_RECV_SIZE, unp);
if (recv_len == 0) break; // (reached end of input)
#if defined(_MSC_VER) || defined(__MINGW32__)
printf("receive count: %d %Id bytes received.\n", recv_count++, recv_len);
#else // defined(_MSC_VER) || defined(__MINGW32__)
printf("receive count: %d %zd bytes received.\n", recv_count++, recv_len);
#endif // defined(_MSC_VER) || defined(__MINGW32__)
ret = msgpack_unpacker_next(unp, &result);
while (ret == MSGPACK_UNPACK_SUCCESS) {
msgpack_object obj = result.data;
/* Use obj. */
printf("Object no %d:\n", ++i);
msgpack_object_print(stdout, obj);
printf("\n");
/* If you want to allocate something on the zone, you can use zone. */
/* msgpack_zone* zone = result.zone; */
/* The lifetime of the obj and the zone, */
ret = msgpack_unpacker_next(unp, &result);
}
if (ret == MSGPACK_UNPACK_PARSE_ERROR) {
printf("The data in the buf is invalid format.\n");
msgpack_unpacked_destroy(&result);
return;
}
}
msgpack_unpacked_destroy(&result);
msgpack_unpacker_free(unp);
}
int main(void) {
receiver r;
receiver_init(&r);
unpack(&r);
return 0;
}
/* Output */
/*
receive count: 0 4 bytes received.
receive count: 1 4 bytes received.
receive count: 2 4 bytes received.
Object no 1:
[1, true, "example"]
receive count: 3 4 bytes received.
receive count: 4 4 bytes received.
Object no 2:
"second"
receive count: 5 1 bytes received.
Object no 3:
[42, false]
*/

47
example/simple_c.c Normal file
View File

@@ -0,0 +1,47 @@
#include <msgpack.h>
#include <stdio.h>
void print(char const* buf,size_t len)
{
size_t i = 0;
for(; i < len ; ++i)
printf("%02x ", 0xff & buf[i]);
printf("\n");
}
int main(void)
{
msgpack_sbuffer sbuf;
msgpack_packer pk;
msgpack_zone mempool;
msgpack_object deserialized;
/* msgpack::sbuffer is a simple buffer implementation. */
msgpack_sbuffer_init(&sbuf);
/* serialize values into the buffer using msgpack_sbuffer_write callback function. */
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
msgpack_pack_array(&pk, 3);
msgpack_pack_int(&pk, 1);
msgpack_pack_true(&pk);
msgpack_pack_str(&pk, 7);
msgpack_pack_str_body(&pk, "example", 7);
print(sbuf.data, sbuf.size);
/* deserialize the buffer into msgpack_object instance. */
/* deserialized object is valid during the msgpack_zone instance alive. */
msgpack_zone_init(&mempool, 2048);
msgpack_unpack(sbuf.data, sbuf.size, NULL, &mempool, &deserialized);
/* print the deserialized object. */
msgpack_object_print(stdout, deserialized);
puts("");
msgpack_zone_destroy(&mempool);
msgpack_sbuffer_destroy(&sbuf);
return 0;
}

View File

@@ -0,0 +1,37 @@
#include <msgpack.h>
void test()
{
size_t size = 10000000;
msgpack_sbuffer buf;
msgpack_packer * pk;
size_t upk_pos = 0;
msgpack_unpacked msg;
msgpack_sbuffer_init(&buf);
pk = msgpack_packer_new(&buf, msgpack_sbuffer_write);
msgpack_pack_array(pk, size);
{
size_t idx = 0;
for (; idx < size; ++idx)
msgpack_pack_uint32(pk, 1);
}
msgpack_packer_free(pk);
msgpack_unpacked_init(&msg);
while (msgpack_unpack_next(&msg, buf.data, buf.size, &upk_pos) == MSGPACK_UNPACK_SUCCESS) {
}
msgpack_unpacked_destroy(&msg);
msgpack_sbuffer_destroy(&buf);
}
int main(void)
{
int i = 0;
for (; i < 10; ++i) test();
return 0;
}

View File

@@ -0,0 +1,37 @@
#include <msgpack.h>
void test()
{
uint64_t test_u64 = 0xFFF0000000000001LL;
size_t size = 10000000;
msgpack_sbuffer buf;
msgpack_packer * pk;
size_t upk_pos = 0;
msgpack_unpacked msg;
msgpack_sbuffer_init(&buf);
pk = msgpack_packer_new(&buf, msgpack_sbuffer_write);
msgpack_pack_array(pk, size);
{
size_t idx = 0;
for (; idx < size; ++idx)
msgpack_pack_uint64(pk, test_u64);
}
msgpack_packer_free(pk);
msgpack_unpacked_init(&msg);
while (msgpack_unpack_next(&msg, buf.data, buf.size, &upk_pos) == MSGPACK_UNPACK_SUCCESS) {
}
msgpack_unpacked_destroy(&msg);
msgpack_sbuffer_destroy(&buf);
}
int main(void)
{
int i = 0;
for (; i < 10; ++i) test();
return 0;
}

View File

@@ -0,0 +1,81 @@
#include <msgpack.h>
#include <stdio.h>
#include <assert.h>
#define UNPACKED_BUFFER_SIZE 2048
void prepare(msgpack_sbuffer* sbuf) {
msgpack_packer pk;
msgpack_packer_init(&pk, sbuf, msgpack_sbuffer_write);
/* 1st object */
msgpack_pack_array(&pk, 3);
msgpack_pack_int(&pk, 1);
msgpack_pack_true(&pk);
msgpack_pack_str(&pk, 7);
msgpack_pack_str_body(&pk, "example", 7);
/* 2nd object */
msgpack_pack_str(&pk, 6);
msgpack_pack_str_body(&pk, "second", 6);
/* 3rd object */
msgpack_pack_array(&pk, 2);
msgpack_pack_int(&pk, 42);
msgpack_pack_false(&pk);
}
void unpack(char const* buf, size_t len) {
/* buf is allocated by client. */
msgpack_unpacked result;
size_t off = 0;
msgpack_unpack_return ret;
int i = 0;
char unpacked_buffer[UNPACKED_BUFFER_SIZE];
msgpack_unpacked_init(&result);
ret = msgpack_unpack_next(&result, buf, len, &off);
while (ret == MSGPACK_UNPACK_SUCCESS) {
msgpack_object obj = result.data;
/* Use obj. */
printf("Object no %d:\n", ++i);
msgpack_object_print(stdout, obj);
printf("\n");
msgpack_object_print_buffer(unpacked_buffer, UNPACKED_BUFFER_SIZE, obj);
printf("%s\n", unpacked_buffer);
/* If you want to allocate something on the zone, you can use zone. */
/* msgpack_zone* zone = result.zone; */
/* The lifetime of the obj and the zone, */
ret = msgpack_unpack_next(&result, buf, len, &off);
}
msgpack_unpacked_destroy(&result);
if (ret == MSGPACK_UNPACK_CONTINUE) {
printf("All msgpack_object in the buffer is consumed.\n");
}
else if (ret == MSGPACK_UNPACK_PARSE_ERROR) {
printf("The data in the buf is invalid format.\n");
}
}
int main(void) {
msgpack_sbuffer sbuf;
msgpack_sbuffer_init(&sbuf);
prepare(&sbuf);
unpack(sbuf.data, sbuf.size);
msgpack_sbuffer_destroy(&sbuf);
return 0;
}
/* Output */
/*
Object no 1:
[1, true, "example"]
Object no 2:
"second"
Object no 3:
[42, false]
All msgpack_object in the buffer is consumed.
*/

24
include/msgpack.h Normal file
View File

@@ -0,0 +1,24 @@
/*
* MessagePack for C
*
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/**
* @defgroup msgpack MessagePack C
* @{
* @}
*/
#include "msgpack/util.h"
#include "msgpack/object.h"
#include "msgpack/zone.h"
#include "msgpack/pack.h"
#include "msgpack/unpack.h"
#include "msgpack/sbuffer.h"
#include "msgpack/vrefbuffer.h"
#include "msgpack/version.h"

42
include/msgpack/fbuffer.h Normal file
View File

@@ -0,0 +1,42 @@
/*
* MessagePack for C FILE* buffer adaptor
*
* Copyright (C) 2013 Vladimir Volodko
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef MSGPACK_FBUFFER_H
#define MSGPACK_FBUFFER_H
#include <stdio.h>
#include <assert.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup msgpack_fbuffer FILE* buffer
* @ingroup msgpack_buffer
* @{
*/
static inline int msgpack_fbuffer_write(void* data, const char* buf, size_t len)
{
assert(buf || len == 0);
if(!buf) return 0;
return (1 == fwrite(buf, len, 1, (FILE *)data)) ? 0 : -1;
}
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* msgpack/fbuffer.h */

View File

@@ -0,0 +1,25 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef MSGPACK_GCC_ATOMIC_H
#define MSGPACK_GCC_ATOMIC_H
#if defined(__cplusplus)
extern "C" {
#endif
typedef int _msgpack_atomic_counter_t;
int _msgpack_sync_decr_and_fetch(volatile _msgpack_atomic_counter_t* ptr);
int _msgpack_sync_incr_and_fetch(volatile _msgpack_atomic_counter_t* ptr);
#if defined(__cplusplus)
}
#endif
#endif // MSGPACK_GCC_ATOMIC_H

118
include/msgpack/object.h Normal file
View File

@@ -0,0 +1,118 @@
/*
* MessagePack for C dynamic typing routine
*
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef MSGPACK_OBJECT_H
#define MSGPACK_OBJECT_H
#include "zone.h"
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup msgpack_object Dynamically typed object
* @ingroup msgpack
* @{
*/
typedef enum {
MSGPACK_OBJECT_NIL = 0x00,
MSGPACK_OBJECT_BOOLEAN = 0x01,
MSGPACK_OBJECT_POSITIVE_INTEGER = 0x02,
MSGPACK_OBJECT_NEGATIVE_INTEGER = 0x03,
MSGPACK_OBJECT_FLOAT32 = 0x0a,
MSGPACK_OBJECT_FLOAT64 = 0x04,
MSGPACK_OBJECT_FLOAT = 0x04,
#if defined(MSGPACK_USE_LEGACY_NAME_AS_FLOAT)
MSGPACK_OBJECT_DOUBLE = MSGPACK_OBJECT_FLOAT, /* obsolete */
#endif /* MSGPACK_USE_LEGACY_NAME_AS_FLOAT */
MSGPACK_OBJECT_STR = 0x05,
MSGPACK_OBJECT_ARRAY = 0x06,
MSGPACK_OBJECT_MAP = 0x07,
MSGPACK_OBJECT_BIN = 0x08,
MSGPACK_OBJECT_EXT = 0x09
} msgpack_object_type;
struct msgpack_object;
struct msgpack_object_kv;
typedef struct {
uint32_t size;
struct msgpack_object* ptr;
} msgpack_object_array;
typedef struct {
uint32_t size;
struct msgpack_object_kv* ptr;
} msgpack_object_map;
typedef struct {
uint32_t size;
const char* ptr;
} msgpack_object_str;
typedef struct {
uint32_t size;
const char* ptr;
} msgpack_object_bin;
typedef struct {
int8_t type;
uint32_t size;
const char* ptr;
} msgpack_object_ext;
typedef union {
bool boolean;
uint64_t u64;
int64_t i64;
#if defined(MSGPACK_USE_LEGACY_NAME_AS_FLOAT)
double dec; /* obsolete*/
#endif /* MSGPACK_USE_LEGACY_NAME_AS_FLOAT */
double f64;
msgpack_object_array array;
msgpack_object_map map;
msgpack_object_str str;
msgpack_object_bin bin;
msgpack_object_ext ext;
} msgpack_object_union;
typedef struct msgpack_object {
msgpack_object_type type;
msgpack_object_union via;
} msgpack_object;
typedef struct msgpack_object_kv {
msgpack_object key;
msgpack_object val;
} msgpack_object_kv;
#if !defined(_KERNEL_MODE)
MSGPACK_DLLEXPORT
void msgpack_object_print(FILE* out, msgpack_object o);
#endif
MSGPACK_DLLEXPORT
int msgpack_object_print_buffer(char *buffer, size_t buffer_size, msgpack_object o);
MSGPACK_DLLEXPORT
bool msgpack_object_equal(const msgpack_object x, const msgpack_object y);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* msgpack/object.h */

174
include/msgpack/pack.h Normal file
View File

@@ -0,0 +1,174 @@
/*
* MessagePack for C packing routine
*
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef MSGPACK_PACK_H
#define MSGPACK_PACK_H
#include "pack_define.h"
#include "object.h"
#include "timestamp.h"
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup msgpack_buffer Buffers
* @ingroup msgpack
* @{
* @}
*/
/**
* @defgroup msgpack_pack Serializer
* @ingroup msgpack
* @{
*/
typedef int (*msgpack_packer_write)(void* data, const char* buf, size_t len);
typedef struct msgpack_packer {
void* data;
msgpack_packer_write callback;
} msgpack_packer;
static void msgpack_packer_init(msgpack_packer* pk, void* data, msgpack_packer_write callback);
static msgpack_packer* msgpack_packer_new(void* data, msgpack_packer_write callback);
static void msgpack_packer_free(msgpack_packer* pk);
static int msgpack_pack_char(msgpack_packer* pk, char d);
static int msgpack_pack_signed_char(msgpack_packer* pk, signed char d);
static int msgpack_pack_short(msgpack_packer* pk, short d);
static int msgpack_pack_int(msgpack_packer* pk, int d);
static int msgpack_pack_long(msgpack_packer* pk, long d);
static int msgpack_pack_long_long(msgpack_packer* pk, long long d);
static int msgpack_pack_unsigned_char(msgpack_packer* pk, unsigned char d);
static int msgpack_pack_unsigned_short(msgpack_packer* pk, unsigned short d);
static int msgpack_pack_unsigned_int(msgpack_packer* pk, unsigned int d);
static int msgpack_pack_unsigned_long(msgpack_packer* pk, unsigned long d);
static int msgpack_pack_unsigned_long_long(msgpack_packer* pk, unsigned long long d);
static int msgpack_pack_uint8(msgpack_packer* pk, uint8_t d);
static int msgpack_pack_uint16(msgpack_packer* pk, uint16_t d);
static int msgpack_pack_uint32(msgpack_packer* pk, uint32_t d);
static int msgpack_pack_uint64(msgpack_packer* pk, uint64_t d);
static int msgpack_pack_int8(msgpack_packer* pk, int8_t d);
static int msgpack_pack_int16(msgpack_packer* pk, int16_t d);
static int msgpack_pack_int32(msgpack_packer* pk, int32_t d);
static int msgpack_pack_int64(msgpack_packer* pk, int64_t d);
static int msgpack_pack_fix_uint8(msgpack_packer* pk, uint8_t d);
static int msgpack_pack_fix_uint16(msgpack_packer* pk, uint16_t d);
static int msgpack_pack_fix_uint32(msgpack_packer* pk, uint32_t d);
static int msgpack_pack_fix_uint64(msgpack_packer* pk, uint64_t d);
static int msgpack_pack_fix_int8(msgpack_packer* pk, int8_t d);
static int msgpack_pack_fix_int16(msgpack_packer* pk, int16_t d);
static int msgpack_pack_fix_int32(msgpack_packer* pk, int32_t d);
static int msgpack_pack_fix_int64(msgpack_packer* pk, int64_t d);
static int msgpack_pack_float(msgpack_packer* pk, float d);
static int msgpack_pack_double(msgpack_packer* pk, double d);
static int msgpack_pack_nil(msgpack_packer* pk);
static int msgpack_pack_true(msgpack_packer* pk);
static int msgpack_pack_false(msgpack_packer* pk);
static int msgpack_pack_array(msgpack_packer* pk, size_t n);
static int msgpack_pack_map(msgpack_packer* pk, size_t n);
static int msgpack_pack_str(msgpack_packer* pk, size_t l);
static int msgpack_pack_str_body(msgpack_packer* pk, const void* b, size_t l);
static int msgpack_pack_str_with_body(msgpack_packer* pk, const void* b, size_t l);
static int msgpack_pack_v4raw(msgpack_packer* pk, size_t l);
static int msgpack_pack_v4raw_body(msgpack_packer* pk, const void* b, size_t l);
static int msgpack_pack_bin(msgpack_packer* pk, size_t l);
static int msgpack_pack_bin_body(msgpack_packer* pk, const void* b, size_t l);
static int msgpack_pack_bin_with_body(msgpack_packer* pk, const void* b, size_t l);
static int msgpack_pack_ext(msgpack_packer* pk, size_t l, int8_t type);
static int msgpack_pack_ext_body(msgpack_packer* pk, const void* b, size_t l);
static int msgpack_pack_ext_with_body(msgpack_packer* pk, const void* b, size_t l, int8_t type);
static int msgpack_pack_timestamp(msgpack_packer* pk, const msgpack_timestamp* d);
MSGPACK_DLLEXPORT
int msgpack_pack_object(msgpack_packer* pk, msgpack_object d);
/** @} */
#define msgpack_pack_inline_func(name) \
inline int msgpack_pack ## name
#define msgpack_pack_inline_func_cint(name) \
inline int msgpack_pack ## name
#define msgpack_pack_inline_func_fixint(name) \
inline int msgpack_pack_fix ## name
#define msgpack_pack_user msgpack_packer*
#define msgpack_pack_append_buffer(user, buf, len) \
return (*(user)->callback)((user)->data, (const char*)buf, len)
#include "pack_template.h"
inline void msgpack_packer_init(msgpack_packer* pk, void* data, msgpack_packer_write callback)
{
pk->data = data;
pk->callback = callback;
}
inline msgpack_packer* msgpack_packer_new(void* data, msgpack_packer_write callback)
{
msgpack_packer* pk = (msgpack_packer*)calloc(1, sizeof(msgpack_packer));
if(!pk) { return NULL; }
msgpack_packer_init(pk, data, callback);
return pk;
}
inline void msgpack_packer_free(msgpack_packer* pk)
{
free(pk);
}
inline int msgpack_pack_str_with_body(msgpack_packer* pk, const void* b, size_t l)
{
int ret = msgpack_pack_str(pk, l);
if (ret != 0) { return ret; }
return msgpack_pack_str_body(pk, b, l);
}
inline int msgpack_pack_bin_with_body(msgpack_packer* pk, const void* b, size_t l)
{
int ret = msgpack_pack_bin(pk, l);
if (ret != 0) { return ret; }
return msgpack_pack_bin_body(pk, b, l);
}
inline int msgpack_pack_ext_with_body(msgpack_packer* pk, const void* b, size_t l, int8_t type)
{
int ret = msgpack_pack_ext(pk, l, type);
if (ret != 0) { return ret; }
return msgpack_pack_ext_body(pk, b, l);
}
#ifdef __cplusplus
}
#endif
#endif /* msgpack/pack.h */

View File

@@ -0,0 +1,18 @@
/*
* MessagePack unpacking routine template
*
* Copyright (C) 2008-2010 FURUHASHI Sadayuki
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef MSGPACK_PACK_DEFINE_H
#define MSGPACK_PACK_DEFINE_H
#include "msgpack/sysdep.h"
#include <limits.h>
#include <string.h>
#endif /* msgpack/pack_define.h */

115
include/msgpack/sbuffer.h Normal file
View File

@@ -0,0 +1,115 @@
/*
* MessagePack for C simple buffer implementation
*
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef MSGPACK_SBUFFER_H
#define MSGPACK_SBUFFER_H
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup msgpack_sbuffer Simple buffer
* @ingroup msgpack_buffer
* @{
*/
typedef struct msgpack_sbuffer {
size_t size;
char* data;
size_t alloc;
} msgpack_sbuffer;
static inline void msgpack_sbuffer_init(msgpack_sbuffer* sbuf)
{
memset(sbuf, 0, sizeof(msgpack_sbuffer));
}
static inline void msgpack_sbuffer_destroy(msgpack_sbuffer* sbuf)
{
free(sbuf->data);
}
static inline msgpack_sbuffer* msgpack_sbuffer_new(void)
{
return (msgpack_sbuffer*)calloc(1, sizeof(msgpack_sbuffer));
}
static inline void msgpack_sbuffer_free(msgpack_sbuffer* sbuf)
{
if(sbuf == NULL) { return; }
msgpack_sbuffer_destroy(sbuf);
free(sbuf);
}
#ifndef MSGPACK_SBUFFER_INIT_SIZE
#define MSGPACK_SBUFFER_INIT_SIZE 8192
#endif
static inline int msgpack_sbuffer_write(void* data, const char* buf, size_t len)
{
msgpack_sbuffer* sbuf = (msgpack_sbuffer*)data;
assert(buf || len == 0);
if(!buf) return 0;
if(sbuf->alloc - sbuf->size < len) {
void* tmp;
size_t nsize = (sbuf->alloc) ?
sbuf->alloc * 2 : MSGPACK_SBUFFER_INIT_SIZE;
while(nsize < sbuf->size + len) {
size_t tmp_nsize = nsize * 2;
if (tmp_nsize <= nsize) {
nsize = sbuf->size + len;
break;
}
nsize = tmp_nsize;
}
tmp = realloc(sbuf->data, nsize);
if(!tmp) { return -1; }
sbuf->data = (char*)tmp;
sbuf->alloc = nsize;
}
memcpy(sbuf->data + sbuf->size, buf, len);
sbuf->size += len;
return 0;
}
static inline char* msgpack_sbuffer_release(msgpack_sbuffer* sbuf)
{
char* tmp = sbuf->data;
sbuf->size = 0;
sbuf->data = NULL;
sbuf->alloc = 0;
return tmp;
}
static inline void msgpack_sbuffer_clear(msgpack_sbuffer* sbuf)
{
sbuf->size = 0;
}
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* msgpack/sbuffer.h */

View File

@@ -0,0 +1,58 @@
/*
* MessagePack for C TimeStamp
*
* Copyright (C) 2018 KONDO Takatoshi
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef MSGPACK_TIMESTAMP_H
#define MSGPACK_TIMESTAMP_H
#include <msgpack/object.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct msgpack_timestamp {
int64_t tv_sec;
uint32_t tv_nsec;
} msgpack_timestamp;
static inline bool msgpack_object_to_timestamp(const msgpack_object* obj, msgpack_timestamp* ts) {
if (obj->type != MSGPACK_OBJECT_EXT) return false;
if (obj->via.ext.type != -1) return false;
switch (obj->via.ext.size) {
case 4:
ts->tv_nsec = 0;
{
uint32_t v;
_msgpack_load32(uint32_t, obj->via.ext.ptr, &v);
ts->tv_sec = v;
}
return true;
case 8: {
uint64_t value;
_msgpack_load64(uint64_t, obj->via.ext.ptr, &value);
ts->tv_nsec = (uint32_t)(value >> 34);
ts->tv_sec = value & 0x00000003ffffffffLL;
return true;
}
case 12:
_msgpack_load32(uint32_t, obj->via.ext.ptr, &ts->tv_nsec);
_msgpack_load64(int64_t, obj->via.ext.ptr + 4, &ts->tv_sec);
return true;
default:
return false;
}
}
#ifdef __cplusplus
}
#endif
#endif /* msgpack/timestamp.h */

281
include/msgpack/unpack.h Normal file
View File

@@ -0,0 +1,281 @@
/*
* MessagePack for C unpacking routine
*
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef MSGPACK_UNPACKER_H
#define MSGPACK_UNPACKER_H
#include "zone.h"
#include "object.h"
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup msgpack_unpack Deserializer
* @ingroup msgpack
* @{
*/
typedef struct msgpack_unpacked {
msgpack_zone* zone;
msgpack_object data;
} msgpack_unpacked;
typedef enum {
MSGPACK_UNPACK_SUCCESS = 2,
MSGPACK_UNPACK_EXTRA_BYTES = 1,
MSGPACK_UNPACK_CONTINUE = 0,
MSGPACK_UNPACK_PARSE_ERROR = -1,
MSGPACK_UNPACK_NOMEM_ERROR = -2
} msgpack_unpack_return;
MSGPACK_DLLEXPORT
msgpack_unpack_return
msgpack_unpack_next(msgpack_unpacked* result,
const char* data, size_t len, size_t* off);
/** @} */
/**
* @defgroup msgpack_unpacker Streaming deserializer
* @ingroup msgpack
* @{
*/
typedef struct msgpack_unpacker {
char* buffer;
size_t used;
size_t free;
size_t off;
size_t parsed;
msgpack_zone* z;
size_t initial_buffer_size;
void* ctx;
} msgpack_unpacker;
#ifndef MSGPACK_UNPACKER_INIT_BUFFER_SIZE
#define MSGPACK_UNPACKER_INIT_BUFFER_SIZE (64*1024)
#endif
/**
* Initializes a streaming deserializer.
* The initialized deserializer must be destroyed by msgpack_unpacker_destroy(msgpack_unpacker*).
*/
MSGPACK_DLLEXPORT
bool msgpack_unpacker_init(msgpack_unpacker* mpac, size_t initial_buffer_size);
/**
* Destroys a streaming deserializer initialized by msgpack_unpacker_init(msgpack_unpacker*, size_t).
*/
MSGPACK_DLLEXPORT
void msgpack_unpacker_destroy(msgpack_unpacker* mpac);
/**
* Creates a streaming deserializer.
* The created deserializer must be destroyed by msgpack_unpacker_free(msgpack_unpacker*).
*/
MSGPACK_DLLEXPORT
msgpack_unpacker* msgpack_unpacker_new(size_t initial_buffer_size);
/**
* Frees a streaming deserializer created by msgpack_unpacker_new(size_t).
*/
MSGPACK_DLLEXPORT
void msgpack_unpacker_free(msgpack_unpacker* mpac);
#ifndef MSGPACK_UNPACKER_RESERVE_SIZE
#define MSGPACK_UNPACKER_RESERVE_SIZE (32*1024)
#endif
/**
* Reserves free space of the internal buffer.
* Use this function to fill the internal buffer with
* msgpack_unpacker_buffer(msgpack_unpacker*),
* msgpack_unpacker_buffer_capacity(const msgpack_unpacker*) and
* msgpack_unpacker_buffer_consumed(msgpack_unpacker*).
*/
static inline bool msgpack_unpacker_reserve_buffer(msgpack_unpacker* mpac, size_t size);
/**
* Gets pointer to the free space of the internal buffer.
* Use this function to fill the internal buffer with
* msgpack_unpacker_reserve_buffer(msgpack_unpacker*, size_t),
* msgpack_unpacker_buffer_capacity(const msgpack_unpacker*) and
* msgpack_unpacker_buffer_consumed(msgpack_unpacker*).
*/
static inline char* msgpack_unpacker_buffer(msgpack_unpacker* mpac);
/**
* Gets size of the free space of the internal buffer.
* Use this function to fill the internal buffer with
* msgpack_unpacker_reserve_buffer(msgpack_unpacker*, size_t),
* msgpack_unpacker_buffer(const msgpack_unpacker*) and
* msgpack_unpacker_buffer_consumed(msgpack_unpacker*).
*/
static inline size_t msgpack_unpacker_buffer_capacity(const msgpack_unpacker* mpac);
/**
* Notifies the deserializer that the internal buffer filled.
* Use this function to fill the internal buffer with
* msgpack_unpacker_reserve_buffer(msgpack_unpacker*, size_t),
* msgpack_unpacker_buffer(msgpack_unpacker*) and
* msgpack_unpacker_buffer_capacity(const msgpack_unpacker*).
*/
static inline void msgpack_unpacker_buffer_consumed(msgpack_unpacker* mpac, size_t size);
/**
* Deserializes one object.
* Returns true if it successes. Otherwise false is returned.
* @param pac pointer to an initialized msgpack_unpacked object.
*/
MSGPACK_DLLEXPORT
msgpack_unpack_return msgpack_unpacker_next(msgpack_unpacker* mpac, msgpack_unpacked* pac);
/**
* Deserializes one object and set the number of parsed bytes involved.
* Returns true if it successes. Otherwise false is returned.
* @param mpac pointer to an initialized msgpack_unpacker object.
* @param result pointer to an initialized msgpack_unpacked object.
* @param p_bytes pointer to variable that will be set with the number of parsed bytes.
*/
MSGPACK_DLLEXPORT
msgpack_unpack_return msgpack_unpacker_next_with_size(msgpack_unpacker* mpac,
msgpack_unpacked* result,
size_t *p_bytes);
/**
* Initializes a msgpack_unpacked object.
* The initialized object must be destroyed by msgpack_unpacked_destroy(msgpack_unpacker*).
* Use the object with msgpack_unpacker_next(msgpack_unpacker*, msgpack_unpacked*) or
* msgpack_unpack_next(msgpack_unpacked*, const char*, size_t, size_t*).
*/
static inline void msgpack_unpacked_init(msgpack_unpacked* result);
/**
* Destroys a streaming deserializer initialized by msgpack_unpacked().
*/
static inline void msgpack_unpacked_destroy(msgpack_unpacked* result);
/**
* Releases the memory zone from msgpack_unpacked object.
* The released zone must be freed by msgpack_zone_free(msgpack_zone*).
*/
static inline msgpack_zone* msgpack_unpacked_release_zone(msgpack_unpacked* result);
MSGPACK_DLLEXPORT
int msgpack_unpacker_execute(msgpack_unpacker* mpac);
MSGPACK_DLLEXPORT
msgpack_object msgpack_unpacker_data(msgpack_unpacker* mpac);
MSGPACK_DLLEXPORT
msgpack_zone* msgpack_unpacker_release_zone(msgpack_unpacker* mpac);
MSGPACK_DLLEXPORT
void msgpack_unpacker_reset_zone(msgpack_unpacker* mpac);
MSGPACK_DLLEXPORT
void msgpack_unpacker_reset(msgpack_unpacker* mpac);
static inline size_t msgpack_unpacker_message_size(const msgpack_unpacker* mpac);
/** @} */
// obsolete
MSGPACK_DLLEXPORT
msgpack_unpack_return
msgpack_unpack(const char* data, size_t len, size_t* off,
msgpack_zone* result_zone, msgpack_object* result);
static inline size_t msgpack_unpacker_parsed_size(const msgpack_unpacker* mpac);
MSGPACK_DLLEXPORT
bool msgpack_unpacker_flush_zone(msgpack_unpacker* mpac);
MSGPACK_DLLEXPORT
bool msgpack_unpacker_expand_buffer(msgpack_unpacker* mpac, size_t size);
static inline bool msgpack_unpacker_reserve_buffer(msgpack_unpacker* mpac, size_t size)
{
if(mpac->free >= size) { return true; }
return msgpack_unpacker_expand_buffer(mpac, size);
}
static inline char* msgpack_unpacker_buffer(msgpack_unpacker* mpac)
{
return mpac->buffer + mpac->used;
}
static inline size_t msgpack_unpacker_buffer_capacity(const msgpack_unpacker* mpac)
{
return mpac->free;
}
static inline void msgpack_unpacker_buffer_consumed(msgpack_unpacker* mpac, size_t size)
{
mpac->used += size;
mpac->free -= size;
}
static inline size_t msgpack_unpacker_message_size(const msgpack_unpacker* mpac)
{
return mpac->parsed - mpac->off + mpac->used;
}
static inline size_t msgpack_unpacker_parsed_size(const msgpack_unpacker* mpac)
{
return mpac->parsed;
}
static inline void msgpack_unpacked_init(msgpack_unpacked* result)
{
memset(result, 0, sizeof(msgpack_unpacked));
}
static inline void msgpack_unpacked_destroy(msgpack_unpacked* result)
{
if(result->zone != NULL) {
msgpack_zone_free(result->zone);
result->zone = NULL;
memset(&result->data, 0, sizeof(msgpack_object));
}
}
static inline msgpack_zone* msgpack_unpacked_release_zone(msgpack_unpacked* result)
{
if(result->zone != NULL) {
msgpack_zone* z = result->zone;
result->zone = NULL;
return z;
}
return NULL;
}
#ifdef __cplusplus
}
#endif
#endif /* msgpack/unpack.h */

View File

@@ -0,0 +1,89 @@
/*
* MessagePack unpacking routine template
*
* Copyright (C) 2008-2010 FURUHASHI Sadayuki
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef MSGPACK_UNPACK_DEFINE_H
#define MSGPACK_UNPACK_DEFINE_H
#include "msgpack/sysdep.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef MSGPACK_EMBED_STACK_SIZE
#define MSGPACK_EMBED_STACK_SIZE 32
#endif
typedef enum {
MSGPACK_CS_HEADER = 0x00, // nil
//MSGPACK_CS_ = 0x01,
//MSGPACK_CS_ = 0x02, // false
//MSGPACK_CS_ = 0x03, // true
MSGPACK_CS_BIN_8 = 0x04,
MSGPACK_CS_BIN_16 = 0x05,
MSGPACK_CS_BIN_32 = 0x06,
MSGPACK_CS_EXT_8 = 0x07,
MSGPACK_CS_EXT_16 = 0x08,
MSGPACK_CS_EXT_32 = 0x09,
MSGPACK_CS_FLOAT = 0x0a,
MSGPACK_CS_DOUBLE = 0x0b,
MSGPACK_CS_UINT_8 = 0x0c,
MSGPACK_CS_UINT_16 = 0x0d,
MSGPACK_CS_UINT_32 = 0x0e,
MSGPACK_CS_UINT_64 = 0x0f,
MSGPACK_CS_INT_8 = 0x10,
MSGPACK_CS_INT_16 = 0x11,
MSGPACK_CS_INT_32 = 0x12,
MSGPACK_CS_INT_64 = 0x13,
MSGPACK_CS_FIXEXT_1 = 0x14,
MSGPACK_CS_FIXEXT_2 = 0x15,
MSGPACK_CS_FIXEXT_4 = 0x16,
MSGPACK_CS_FIXEXT_8 = 0x17,
MSGPACK_CS_FIXEXT_16 = 0x18,
MSGPACK_CS_STR_8 = 0x19, // str8
MSGPACK_CS_STR_16 = 0x1a, // str16
MSGPACK_CS_STR_32 = 0x1b, // str32
MSGPACK_CS_ARRAY_16 = 0x1c,
MSGPACK_CS_ARRAY_32 = 0x1d,
MSGPACK_CS_MAP_16 = 0x1e,
MSGPACK_CS_MAP_32 = 0x1f,
//MSGPACK_ACS_BIG_INT_VALUE,
//MSGPACK_ACS_BIG_FLOAT_VALUE,
MSGPACK_ACS_STR_VALUE,
MSGPACK_ACS_BIN_VALUE,
MSGPACK_ACS_EXT_VALUE
} msgpack_unpack_state;
typedef enum {
MSGPACK_CT_ARRAY_ITEM,
MSGPACK_CT_MAP_KEY,
MSGPACK_CT_MAP_VALUE
} msgpack_container_type;
#ifdef __cplusplus
}
#endif
#endif /* msgpack/unpack_define.h */

View File

@@ -0,0 +1,471 @@
/*
* MessagePack unpacking routine template
*
* Copyright (C) 2008-2010 FURUHASHI Sadayuki
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef msgpack_unpack_func
#error msgpack_unpack_func template is not defined
#endif
#ifndef msgpack_unpack_callback
#error msgpack_unpack_callback template is not defined
#endif
#ifndef msgpack_unpack_struct
#error msgpack_unpack_struct template is not defined
#endif
#ifndef msgpack_unpack_struct_decl
#define msgpack_unpack_struct_decl(name) msgpack_unpack_struct(name)
#endif
#ifndef msgpack_unpack_object
#error msgpack_unpack_object type is not defined
#endif
#ifndef msgpack_unpack_user
#error msgpack_unpack_user type is not defined
#endif
#ifndef USE_CASE_RANGE
#if !defined(_MSC_VER)
#define USE_CASE_RANGE
#endif
#endif
#if defined(_KERNEL_MODE)
#undef assert
#define assert NT_ASSERT
#endif
msgpack_unpack_struct_decl(_stack) {
msgpack_unpack_object obj;
size_t count;
unsigned int ct;
msgpack_unpack_object map_key;
};
msgpack_unpack_struct_decl(_context) {
msgpack_unpack_user user;
unsigned int cs;
unsigned int trail;
unsigned int top;
/*
msgpack_unpack_struct(_stack)* stack;
unsigned int stack_size;
msgpack_unpack_struct(_stack) embed_stack[MSGPACK_EMBED_STACK_SIZE];
*/
msgpack_unpack_struct(_stack) stack[MSGPACK_EMBED_STACK_SIZE];
};
msgpack_unpack_func(void, _init)(msgpack_unpack_struct(_context)* ctx)
{
ctx->cs = MSGPACK_CS_HEADER;
ctx->trail = 0;
ctx->top = 0;
/*
ctx->stack = ctx->embed_stack;
ctx->stack_size = MSGPACK_EMBED_STACK_SIZE;
*/
ctx->stack[0].obj = msgpack_unpack_callback(_root)(&ctx->user);
}
/*
msgpack_unpack_func(void, _destroy)(msgpack_unpack_struct(_context)* ctx)
{
if(ctx->stack_size != MSGPACK_EMBED_STACK_SIZE) {
free(ctx->stack);
}
}
*/
msgpack_unpack_func(msgpack_unpack_object, _data)(msgpack_unpack_struct(_context)* ctx)
{
return (ctx)->stack[0].obj;
}
msgpack_unpack_func(int, _execute)(msgpack_unpack_struct(_context)* ctx, const char* data, size_t len, size_t* off)
{
assert(len >= *off);
{
const unsigned char* p = (unsigned char*)data + *off;
const unsigned char* const pe = (unsigned char*)data + len;
const void* n = NULL;
unsigned int trail = ctx->trail;
unsigned int cs = ctx->cs;
unsigned int top = ctx->top;
msgpack_unpack_struct(_stack)* stack = ctx->stack;
/*
unsigned int stack_size = ctx->stack_size;
*/
msgpack_unpack_user* user = &ctx->user;
msgpack_unpack_object obj;
msgpack_unpack_struct(_stack)* c = NULL;
int ret;
#define push_simple_value(func) \
ret = msgpack_unpack_callback(func)(user, &obj); \
if(ret < 0) { goto _failed; } \
goto _push
#define push_fixed_value(func, arg) \
ret = msgpack_unpack_callback(func)(user, arg, &obj); \
if(ret < 0) { goto _failed; } \
goto _push
#define push_variable_value(func, base, pos, len) \
ret = msgpack_unpack_callback(func)(user, \
(const char*)base, (const char*)pos, len, &obj); \
if(ret < 0) { goto _failed; } \
goto _push
#define again_fixed_trail(_cs, trail_len) \
trail = trail_len; \
cs = _cs; \
goto _fixed_trail_again
#define again_fixed_trail_if_zero(_cs, trail_len, ifzero) \
trail = trail_len; \
if(trail == 0) { goto ifzero; } \
cs = _cs; \
goto _fixed_trail_again
#define start_container(func, count_, ct_) \
if(top >= MSGPACK_EMBED_STACK_SIZE) { \
ret = MSGPACK_UNPACK_NOMEM_ERROR; \
goto _failed; \
} /* FIXME */ \
ret = msgpack_unpack_callback(func)(user, count_, &stack[top].obj); \
if(ret < 0) { goto _failed; } \
if((count_) == 0) { obj = stack[top].obj; goto _push; } \
stack[top].ct = ct_; \
stack[top].count = count_; \
++top; \
goto _header_again
#define NEXT_CS(p) \
((unsigned int)*p & 0x1f)
#ifdef USE_CASE_RANGE
#define SWITCH_RANGE_BEGIN switch(*p) {
#define SWITCH_RANGE(FROM, TO) case FROM ... TO:
#define SWITCH_RANGE_DEFAULT default:
#define SWITCH_RANGE_END }
#else
#define SWITCH_RANGE_BEGIN { if(0) {
#define SWITCH_RANGE(FROM, TO) } else if(FROM <= *p && *p <= TO) {
#define SWITCH_RANGE_DEFAULT } else {
#define SWITCH_RANGE_END } }
#endif
if(p == pe) { goto _out; }
do {
switch(cs) {
case MSGPACK_CS_HEADER:
SWITCH_RANGE_BEGIN
SWITCH_RANGE(0x00, 0x7f) // Positive Fixnum
push_fixed_value(_uint8, *(uint8_t*)p);
SWITCH_RANGE(0xe0, 0xff) // Negative Fixnum
push_fixed_value(_int8, *(int8_t*)p);
SWITCH_RANGE(0xc0, 0xdf) // Variable
switch(*p) {
case 0xc0: // nil
push_simple_value(_nil);
//case 0xc1: // string
// again_terminal_trail(NEXT_CS(p), p+1);
case 0xc2: // false
push_simple_value(_false);
case 0xc3: // true
push_simple_value(_true);
case 0xc4: // bin 8
case 0xc5: // bin 16
case 0xc6: // bin 32
again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03));
case 0xc7: // ext 8
case 0xc8: // ext 16
case 0xc9: // ext 32
again_fixed_trail(NEXT_CS(p), 1 << ((((unsigned int)*p) + 1) & 0x03));
case 0xca: // float
case 0xcb: // double
case 0xcc: // unsigned int 8
case 0xcd: // unsigned int 16
case 0xce: // unsigned int 32
case 0xcf: // unsigned int 64
case 0xd0: // signed int 8
case 0xd1: // signed int 16
case 0xd2: // signed int 32
case 0xd3: // signed int 64
again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03));
case 0xd4: // fixext 1
case 0xd5: // fixext 2
case 0xd6: // fixext 4
case 0xd7: // fixext 8
again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE,
(1 << (((unsigned int)*p) & 0x03)) + 1, _ext_zero);
case 0xd8: // fixext 16
again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 16+1, _ext_zero);
case 0xd9: // str 8
case 0xda: // str 16
case 0xdb: // str 32
again_fixed_trail(NEXT_CS(p), 1 << ((((unsigned int)*p) & 0x03) - 1));
case 0xdc: // array 16
case 0xdd: // array 32
case 0xde: // map 16
case 0xdf: // map 32
again_fixed_trail(NEXT_CS(p), 2u << (((unsigned int)*p) & 0x01));
default:
ret = MSGPACK_UNPACK_PARSE_ERROR;
goto _failed;
}
SWITCH_RANGE(0xa0, 0xbf) // FixStr
again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, ((unsigned int)*p & 0x1f), _str_zero);
SWITCH_RANGE(0x90, 0x9f) // FixArray
start_container(_array, ((unsigned int)*p) & 0x0f, MSGPACK_CT_ARRAY_ITEM);
SWITCH_RANGE(0x80, 0x8f) // FixMap
start_container(_map, ((unsigned int)*p) & 0x0f, MSGPACK_CT_MAP_KEY);
SWITCH_RANGE_DEFAULT
ret = MSGPACK_UNPACK_PARSE_ERROR;
goto _failed;
SWITCH_RANGE_END
// end MSGPACK_CS_HEADER
_fixed_trail_again:
++p;
// fallthrough
default:
if((size_t)(pe - p) < trail) { goto _out; }
n = p; p += trail - 1;
switch(cs) {
//case MSGPACK_CS_
//case MSGPACK_CS_
case MSGPACK_CS_FLOAT: {
union { uint32_t i; float f; } mem;
_msgpack_load32(uint32_t, n, &mem.i);
push_fixed_value(_float, mem.f); }
case MSGPACK_CS_DOUBLE: {
union { uint64_t i; double f; } mem;
_msgpack_load64(uint64_t, n, &mem.i);
#if defined(TARGET_OS_IPHONE)
// ok
#elif defined(__arm__) && !(__ARM_EABI__) // arm-oabi
// https://github.com/msgpack/msgpack-perl/pull/1
mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
#endif
push_fixed_value(_double, mem.f); }
case MSGPACK_CS_UINT_8:
push_fixed_value(_uint8, *(uint8_t*)n);
case MSGPACK_CS_UINT_16:{
uint16_t tmp;
_msgpack_load16(uint16_t,n,&tmp);
push_fixed_value(_uint16, tmp);
}
case MSGPACK_CS_UINT_32:{
uint32_t tmp;
_msgpack_load32(uint32_t,n,&tmp);
push_fixed_value(_uint32, tmp);
}
case MSGPACK_CS_UINT_64:{
uint64_t tmp;
_msgpack_load64(uint64_t,n,&tmp);
push_fixed_value(_uint64, tmp);
}
case MSGPACK_CS_INT_8:
push_fixed_value(_int8, *(int8_t*)n);
case MSGPACK_CS_INT_16:{
int16_t tmp;
_msgpack_load16(int16_t,n,&tmp);
push_fixed_value(_int16, tmp);
}
case MSGPACK_CS_INT_32:{
int32_t tmp;
_msgpack_load32(int32_t,n,&tmp);
push_fixed_value(_int32, tmp);
}
case MSGPACK_CS_INT_64:{
int64_t tmp;
_msgpack_load64(int64_t,n,&tmp);
push_fixed_value(_int64, tmp);
}
case MSGPACK_CS_FIXEXT_1:
again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 1+1, _ext_zero);
case MSGPACK_CS_FIXEXT_2:
again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 2+1, _ext_zero);
case MSGPACK_CS_FIXEXT_4:
again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 4+1, _ext_zero);
case MSGPACK_CS_FIXEXT_8:
again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 8+1, _ext_zero);
case MSGPACK_CS_FIXEXT_16:
again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 16+1, _ext_zero);
case MSGPACK_CS_STR_8:
again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, *(uint8_t*)n, _str_zero);
case MSGPACK_CS_BIN_8:
again_fixed_trail_if_zero(MSGPACK_ACS_BIN_VALUE, *(uint8_t*)n, _bin_zero);
case MSGPACK_CS_EXT_8:
again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, (*(uint8_t*)n) + 1, _ext_zero);
case MSGPACK_CS_STR_16:{
uint16_t tmp;
_msgpack_load16(uint16_t,n,&tmp);
again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, tmp, _str_zero);
}
case MSGPACK_CS_BIN_16:{
uint16_t tmp;
_msgpack_load16(uint16_t,n,&tmp);
again_fixed_trail_if_zero(MSGPACK_ACS_BIN_VALUE, tmp, _bin_zero);
}
case MSGPACK_CS_EXT_16:{
uint16_t tmp;
_msgpack_load16(uint16_t,n,&tmp);
again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, tmp + 1, _ext_zero);
}
case MSGPACK_CS_STR_32:{
uint32_t tmp;
_msgpack_load32(uint32_t,n,&tmp);
again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, tmp, _str_zero);
}
case MSGPACK_CS_BIN_32:{
uint32_t tmp;
_msgpack_load32(uint32_t,n,&tmp);
again_fixed_trail_if_zero(MSGPACK_ACS_BIN_VALUE, tmp, _bin_zero);
}
case MSGPACK_CS_EXT_32:{
uint32_t tmp;
_msgpack_load32(uint32_t,n,&tmp);
again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, tmp + 1, _ext_zero);
}
case MSGPACK_ACS_STR_VALUE:
_str_zero:
push_variable_value(_str, data, n, trail);
case MSGPACK_ACS_BIN_VALUE:
_bin_zero:
push_variable_value(_bin, data, n, trail);
case MSGPACK_ACS_EXT_VALUE:
_ext_zero:
push_variable_value(_ext, data, n, trail);
case MSGPACK_CS_ARRAY_16:{
uint16_t tmp;
_msgpack_load16(uint16_t,n,&tmp);
start_container(_array, tmp, MSGPACK_CT_ARRAY_ITEM);
}
case MSGPACK_CS_ARRAY_32:{
/* FIXME security guard */
uint32_t tmp;
_msgpack_load32(uint32_t,n,&tmp);
start_container(_array, tmp, MSGPACK_CT_ARRAY_ITEM);
}
case MSGPACK_CS_MAP_16:{
uint16_t tmp;
_msgpack_load16(uint16_t,n,&tmp);
start_container(_map, tmp, MSGPACK_CT_MAP_KEY);
}
case MSGPACK_CS_MAP_32:{
/* FIXME security guard */
uint32_t tmp;
_msgpack_load32(uint32_t,n,&tmp);
start_container(_map, tmp, MSGPACK_CT_MAP_KEY);
}
default:
ret = MSGPACK_UNPACK_PARSE_ERROR;
goto _failed;
}
}
_push:
if(top == 0) { goto _finish; }
c = &stack[top-1];
switch(c->ct) {
case MSGPACK_CT_ARRAY_ITEM:
ret = msgpack_unpack_callback(_array_item)(user, &c->obj, obj); \
if(ret < 0) { goto _failed; }
if(--c->count == 0) {
obj = c->obj;
--top;
/*printf("stack pop %d\n", top);*/
goto _push;
}
goto _header_again;
case MSGPACK_CT_MAP_KEY:
c->map_key = obj;
c->ct = MSGPACK_CT_MAP_VALUE;
goto _header_again;
case MSGPACK_CT_MAP_VALUE:
ret = msgpack_unpack_callback(_map_item)(user, &c->obj, c->map_key, obj); \
if(ret < 0) { goto _failed; }
if(--c->count == 0) {
obj = c->obj;
--top;
/*printf("stack pop %d\n", top);*/
goto _push;
}
c->ct = MSGPACK_CT_MAP_KEY;
goto _header_again;
default:
ret = MSGPACK_UNPACK_PARSE_ERROR;
goto _failed;
}
_header_again:
cs = MSGPACK_CS_HEADER;
++p;
} while(p != pe);
goto _out;
_finish:
stack[0].obj = obj;
++p;
ret = 1;
/*printf("-- finish --\n"); */
goto _end;
_failed:
/*printf("** FAILED **\n"); */
goto _end;
_out:
ret = 0;
goto _end;
_end:
ctx->cs = cs;
ctx->trail = trail;
ctx->top = top;
*off = (size_t)(p - (const unsigned char*)data);
return ret;
}
}
#undef msgpack_unpack_func
#undef msgpack_unpack_callback
#undef msgpack_unpack_struct
#undef msgpack_unpack_object
#undef msgpack_unpack_user
#undef push_simple_value
#undef push_fixed_value
#undef push_variable_value
#undef again_fixed_trail
#undef again_fixed_trail_if_zero
#undef start_container
#undef NEXT_CS
#undef SWITCH_RANGE_BEGIN
#undef SWITCH_RANGE
#undef SWITCH_RANGE_DEFAULT
#undef SWITCH_RANGE_END

15
include/msgpack/util.h Normal file
View File

@@ -0,0 +1,15 @@
/*
* MessagePack for C utilities
*
* Copyright (C) 2014 FURUHASHI Sadayuki
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef MSGPACK_UTIL_H
#define MSGPACK_UTIL_H
#define MSGPACK_UNUSED(a) (void)(a)
#endif /* MSGPACK_UTIL_H */

38
include/msgpack/version.h Normal file
View File

@@ -0,0 +1,38 @@
/*
* MessagePack for C version information
*
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef MSGPACK_VERSION_H
#define MSGPACK_VERSION_H
#ifdef __cplusplus
extern "C" {
#endif
MSGPACK_DLLEXPORT
const char* msgpack_version(void);
MSGPACK_DLLEXPORT
int msgpack_version_major(void);
MSGPACK_DLLEXPORT
int msgpack_version_minor(void);
MSGPACK_DLLEXPORT
int msgpack_version_revision(void);
#include "version_master.h"
#define MSGPACK_STR(v) #v
#define MSGPACK_VERSION_I(maj, min, rev) MSGPACK_STR(maj) "." MSGPACK_STR(min) "." MSGPACK_STR(rev)
#define MSGPACK_VERSION MSGPACK_VERSION_I(MSGPACK_VERSION_MAJOR, MSGPACK_VERSION_MINOR, MSGPACK_VERSION_REVISION)
#ifdef __cplusplus
}
#endif
#endif /* msgpack/version.h */

View File

@@ -0,0 +1,3 @@
#define MSGPACK_VERSION_MAJOR 4
#define MSGPACK_VERSION_MINOR 0
#define MSGPACK_VERSION_REVISION 0

View File

@@ -0,0 +1,146 @@
/*
* MessagePack for C zero-copy buffer implementation
*
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef MSGPACK_VREFBUFFER_H
#define MSGPACK_VREFBUFFER_H
#include "zone.h"
#include <stdlib.h>
#include <assert.h>
#if defined(unix) || defined(__unix) || defined(__linux__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__QNX__) || defined(__QNXTO__) || defined(__HAIKU__)
#include <sys/uio.h>
typedef struct iovec msgpack_iovec;
#else
struct msgpack_iovec {
void *iov_base;
size_t iov_len;
};
typedef struct msgpack_iovec msgpack_iovec;
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup msgpack_vrefbuffer Vectored Referencing buffer
* @ingroup msgpack_buffer
* @{
*/
struct msgpack_vrefbuffer_chunk;
typedef struct msgpack_vrefbuffer_chunk msgpack_vrefbuffer_chunk;
typedef struct msgpack_vrefbuffer_inner_buffer {
size_t free;
char* ptr;
msgpack_vrefbuffer_chunk* head;
} msgpack_vrefbuffer_inner_buffer;
typedef struct msgpack_vrefbuffer {
msgpack_iovec* tail;
msgpack_iovec* end;
msgpack_iovec* array;
size_t chunk_size;
size_t ref_size;
msgpack_vrefbuffer_inner_buffer inner_buffer;
} msgpack_vrefbuffer;
#ifndef MSGPACK_VREFBUFFER_REF_SIZE
#define MSGPACK_VREFBUFFER_REF_SIZE 32
#endif
#ifndef MSGPACK_VREFBUFFER_CHUNK_SIZE
#define MSGPACK_VREFBUFFER_CHUNK_SIZE 8192
#endif
MSGPACK_DLLEXPORT
bool msgpack_vrefbuffer_init(msgpack_vrefbuffer* vbuf,
size_t ref_size, size_t chunk_size);
MSGPACK_DLLEXPORT
void msgpack_vrefbuffer_destroy(msgpack_vrefbuffer* vbuf);
static inline msgpack_vrefbuffer* msgpack_vrefbuffer_new(size_t ref_size, size_t chunk_size);
static inline void msgpack_vrefbuffer_free(msgpack_vrefbuffer* vbuf);
static inline int msgpack_vrefbuffer_write(void* data, const char* buf, size_t len);
static inline const msgpack_iovec* msgpack_vrefbuffer_vec(const msgpack_vrefbuffer* vref);
static inline size_t msgpack_vrefbuffer_veclen(const msgpack_vrefbuffer* vref);
MSGPACK_DLLEXPORT
int msgpack_vrefbuffer_append_copy(msgpack_vrefbuffer* vbuf,
const char* buf, size_t len);
MSGPACK_DLLEXPORT
int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf,
const char* buf, size_t len);
MSGPACK_DLLEXPORT
int msgpack_vrefbuffer_migrate(msgpack_vrefbuffer* vbuf, msgpack_vrefbuffer* to);
MSGPACK_DLLEXPORT
void msgpack_vrefbuffer_clear(msgpack_vrefbuffer* vref);
/** @} */
static inline msgpack_vrefbuffer* msgpack_vrefbuffer_new(size_t ref_size, size_t chunk_size)
{
msgpack_vrefbuffer* vbuf = (msgpack_vrefbuffer*)malloc(sizeof(msgpack_vrefbuffer));
if (vbuf == NULL) return NULL;
if(!msgpack_vrefbuffer_init(vbuf, ref_size, chunk_size)) {
free(vbuf);
return NULL;
}
return vbuf;
}
static inline void msgpack_vrefbuffer_free(msgpack_vrefbuffer* vbuf)
{
if(vbuf == NULL) { return; }
msgpack_vrefbuffer_destroy(vbuf);
free(vbuf);
}
static inline int msgpack_vrefbuffer_write(void* data, const char* buf, size_t len)
{
msgpack_vrefbuffer* vbuf = (msgpack_vrefbuffer*)data;
assert(buf || len == 0);
if(!buf) return 0;
if(len < vbuf->ref_size) {
return msgpack_vrefbuffer_append_copy(vbuf, buf, len);
} else {
return msgpack_vrefbuffer_append_ref(vbuf, buf, len);
}
}
static inline const msgpack_iovec* msgpack_vrefbuffer_vec(const msgpack_vrefbuffer* vref)
{
return vref->array;
}
static inline size_t msgpack_vrefbuffer_veclen(const msgpack_vrefbuffer* vref)
{
return (size_t)(vref->tail - vref->array);
}
#ifdef __cplusplus
}
#endif
#endif /* msgpack/vrefbuffer.h */

205
include/msgpack/zbuffer.h Normal file
View File

@@ -0,0 +1,205 @@
/*
* MessagePack for C deflate buffer implementation
*
* Copyright (C) 2010 FURUHASHI Sadayuki
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef MSGPACK_ZBUFFER_H
#define MSGPACK_ZBUFFER_H
#include "sysdep.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <zlib.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup msgpack_zbuffer Compressed buffer
* @ingroup msgpack_buffer
* @{
*/
typedef struct msgpack_zbuffer {
z_stream stream;
char* data;
size_t init_size;
} msgpack_zbuffer;
#ifndef MSGPACK_ZBUFFER_INIT_SIZE
#define MSGPACK_ZBUFFER_INIT_SIZE 8192
#endif
static inline bool msgpack_zbuffer_init(
msgpack_zbuffer* zbuf, int level, size_t init_size);
static inline void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf);
static inline msgpack_zbuffer* msgpack_zbuffer_new(int level, size_t init_size);
static inline void msgpack_zbuffer_free(msgpack_zbuffer* zbuf);
static inline char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf);
static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf);
static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf);
static inline bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf);
static inline void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf);
static inline char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf);
#ifndef MSGPACK_ZBUFFER_RESERVE_SIZE
#define MSGPACK_ZBUFFER_RESERVE_SIZE 512
#endif
static inline int msgpack_zbuffer_write(void* data, const char* buf, size_t len);
static inline bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf);
static inline bool msgpack_zbuffer_init(msgpack_zbuffer* zbuf,
int level, size_t init_size)
{
memset(zbuf, 0, sizeof(msgpack_zbuffer));
zbuf->init_size = init_size;
if(deflateInit(&zbuf->stream, level) != Z_OK) {
free(zbuf->data);
return false;
}
return true;
}
static inline void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf)
{
deflateEnd(&zbuf->stream);
free(zbuf->data);
}
static inline msgpack_zbuffer* msgpack_zbuffer_new(int level, size_t init_size)
{
msgpack_zbuffer* zbuf = (msgpack_zbuffer*)malloc(sizeof(msgpack_zbuffer));
if (zbuf == NULL) return NULL;
if(!msgpack_zbuffer_init(zbuf, level, init_size)) {
free(zbuf);
return NULL;
}
return zbuf;
}
static inline void msgpack_zbuffer_free(msgpack_zbuffer* zbuf)
{
if(zbuf == NULL) { return; }
msgpack_zbuffer_destroy(zbuf);
free(zbuf);
}
static inline bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf)
{
size_t used = (size_t)((char *)(zbuf->stream.next_out) - zbuf->data);
size_t csize = used + zbuf->stream.avail_out;
size_t nsize = (csize == 0) ? zbuf->init_size : csize * 2;
char* tmp = (char*)realloc(zbuf->data, nsize);
if(tmp == NULL) {
return false;
}
zbuf->data = tmp;
zbuf->stream.next_out = (Bytef*)(tmp + used);
zbuf->stream.avail_out = (uInt)(nsize - used);
return true;
}
static inline int msgpack_zbuffer_write(void* data, const char* buf, size_t len)
{
msgpack_zbuffer* zbuf = (msgpack_zbuffer*)data;
assert(buf || len == 0);
if(!buf) return 0;
zbuf->stream.next_in = (Bytef*)buf;
zbuf->stream.avail_in = (uInt)len;
while(zbuf->stream.avail_in > 0) {
if(zbuf->stream.avail_out < MSGPACK_ZBUFFER_RESERVE_SIZE) {
if(!msgpack_zbuffer_expand(zbuf)) {
return -1;
}
}
if(deflate(&zbuf->stream, Z_NO_FLUSH) != Z_OK) {
return -1;
}
}
return 0;
}
static inline char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf)
{
while(true) {
switch(deflate(&zbuf->stream, Z_FINISH)) {
case Z_STREAM_END:
return zbuf->data;
case Z_OK:
case Z_BUF_ERROR:
if(!msgpack_zbuffer_expand(zbuf)) {
return NULL;
}
break;
default:
return NULL;
}
}
}
static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf)
{
return zbuf->data;
}
static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf)
{
return (size_t)((char *)(zbuf->stream.next_out) - zbuf->data);
}
static inline void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf)
{
zbuf->stream.avail_out += (uInt)((char*)zbuf->stream.next_out - zbuf->data);
zbuf->stream.next_out = (Bytef*)zbuf->data;
}
static inline bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf)
{
if(deflateReset(&zbuf->stream) != Z_OK) {
return false;
}
msgpack_zbuffer_reset_buffer(zbuf);
return true;
}
static inline char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf)
{
char* tmp = zbuf->data;
zbuf->data = NULL;
zbuf->stream.next_out = NULL;
zbuf->stream.avail_out = 0;
return tmp;
}
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* msgpack/zbuffer.h */

163
include/msgpack/zone.h Normal file
View File

@@ -0,0 +1,163 @@
/*
* MessagePack for C memory pool implementation
*
* Copyright (C) 2008-2010 FURUHASHI Sadayuki
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef MSGPACK_ZONE_H
#define MSGPACK_ZONE_H
#include "sysdep.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup msgpack_zone Memory zone
* @ingroup msgpack
* @{
*/
typedef struct msgpack_zone_finalizer {
void (*func)(void* data);
void* data;
} msgpack_zone_finalizer;
typedef struct msgpack_zone_finalizer_array {
msgpack_zone_finalizer* tail;
msgpack_zone_finalizer* end;
msgpack_zone_finalizer* array;
} msgpack_zone_finalizer_array;
struct msgpack_zone_chunk;
typedef struct msgpack_zone_chunk msgpack_zone_chunk;
typedef struct msgpack_zone_chunk_list {
size_t free;
char* ptr;
msgpack_zone_chunk* head;
} msgpack_zone_chunk_list;
typedef struct msgpack_zone {
msgpack_zone_chunk_list chunk_list;
msgpack_zone_finalizer_array finalizer_array;
size_t chunk_size;
} msgpack_zone;
#ifndef MSGPACK_ZONE_CHUNK_SIZE
#define MSGPACK_ZONE_CHUNK_SIZE 8192
#endif
MSGPACK_DLLEXPORT
bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size);
MSGPACK_DLLEXPORT
void msgpack_zone_destroy(msgpack_zone* zone);
MSGPACK_DLLEXPORT
msgpack_zone* msgpack_zone_new(size_t chunk_size);
MSGPACK_DLLEXPORT
void msgpack_zone_free(msgpack_zone* zone);
static inline void* msgpack_zone_malloc(msgpack_zone* zone, size_t size);
static inline void* msgpack_zone_malloc_no_align(msgpack_zone* zone, size_t size);
static inline bool msgpack_zone_push_finalizer(msgpack_zone* zone,
void (*func)(void* data), void* data);
static inline void msgpack_zone_swap(msgpack_zone* a, msgpack_zone* b);
MSGPACK_DLLEXPORT
bool msgpack_zone_is_empty(msgpack_zone* zone);
MSGPACK_DLLEXPORT
void msgpack_zone_clear(msgpack_zone* zone);
/** @} */
#ifndef MSGPACK_ZONE_ALIGN
#define MSGPACK_ZONE_ALIGN sizeof(void*)
#endif
MSGPACK_DLLEXPORT
void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size);
static inline void* msgpack_zone_malloc_no_align(msgpack_zone* zone, size_t size)
{
char* ptr;
msgpack_zone_chunk_list* cl = &zone->chunk_list;
if(zone->chunk_list.free < size) {
return msgpack_zone_malloc_expand(zone, size);
}
ptr = cl->ptr;
cl->free -= size;
cl->ptr += size;
return ptr;
}
static inline void* msgpack_zone_malloc(msgpack_zone* zone, size_t size)
{
char* aligned =
(char*)(
(uintptr_t)(
zone->chunk_list.ptr + (MSGPACK_ZONE_ALIGN - 1)
) & ~(uintptr_t)(MSGPACK_ZONE_ALIGN - 1)
);
size_t adjusted_size = size + (size_t)(aligned - zone->chunk_list.ptr);
if(zone->chunk_list.free >= adjusted_size) {
zone->chunk_list.free -= adjusted_size;
zone->chunk_list.ptr += adjusted_size;
return aligned;
}
{
void* ptr = msgpack_zone_malloc_expand(zone, size + (MSGPACK_ZONE_ALIGN - 1));
if (ptr) {
return (char*)((uintptr_t)(ptr) & ~(uintptr_t)(MSGPACK_ZONE_ALIGN - 1));
}
}
return NULL;
}
bool msgpack_zone_push_finalizer_expand(msgpack_zone* zone,
void (*func)(void* data), void* data);
static inline bool msgpack_zone_push_finalizer(msgpack_zone* zone,
void (*func)(void* data), void* data)
{
msgpack_zone_finalizer_array* const fa = &zone->finalizer_array;
msgpack_zone_finalizer* fin = fa->tail;
if(fin == fa->end) {
return msgpack_zone_push_finalizer_expand(zone, func, data);
}
fin->func = func;
fin->data = data;
++fa->tail;
return true;
}
static inline void msgpack_zone_swap(msgpack_zone* a, msgpack_zone* b)
{
msgpack_zone tmp = *a;
*a = *b;
*b = tmp;
}
#ifdef __cplusplus
}
#endif
#endif /* msgpack/zone.h */

39
makedist.sh Executable file
View File

@@ -0,0 +1,39 @@
#!/bin/sh
ver=`cat include/msgpack/version_master.h | tr -d "\n" | sed -e 's/#define MSGPACK_VERSION_MAJOR[[:space:]]*\([[:alnum:]]*\)/\1./g' -e 's/#define MSGPACK_VERSION_MINOR[[:space:]]*\([[:alnum:]]*\)/\1./g' -e 's/#define MSGPACK_VERSION_REVISION[[:space:]]*\([[:alnum:]]*\)/\1/g'`
prefix=msgpack-c-$ver
filename=$prefix.tar
ln -s . $prefix
test -f AUTHORS || touch AUTHORS
test -f COPYING || touch COPYING
test -f ChangeLog || cp -f CHANGELOG.md ChangeLog
test -f NEWS || touch NEWS
test -f NOTICE || touch NOTICE
test -f README || cp -f README.md README
tar cf $filename $prefix/example
tar --append --file=$filename $prefix/test
tar --append --file=$filename $prefix/include
tar --append --file=$filename $prefix/src
tar --append --file=$filename $prefix/cmake
tar --append --file=$filename $prefix/CMakeLists.txt
tar --append --file=$filename $prefix/Files.cmake
tar --append --file=$filename $prefix/NOTICE
tar --append --file=$filename $prefix/Doxyfile
tar --append --file=$filename $prefix/msgpack.pc.in
tar --append --file=$filename $prefix/AUTHORS
tar --append --file=$filename $prefix/README.md
tar --append --file=$filename $prefix/LICENSE_1_0.txt
tar --append --file=$filename $prefix/ChangeLog
tar --append --file=$filename $prefix/NEWS
tar --append --file=$filename $prefix/COPYING
tar --append --file=$filename $prefix/README
tar --append --file=$filename $prefix/msgpack-config.cmake.in
rm -f $prefix
gzip -f $filename

19
msgpack-config.cmake.in Normal file
View File

@@ -0,0 +1,19 @@
#.rst:
# msgpack
# -------
#
# The following import targets are created
#
# ::
#
# msgpackc
# msgpackc-static (optional)
#
@PACKAGE_INIT@
include(CMakeFindDependencyMacro)
if(NOT TARGET msgpackc AND NOT TARGET msgpackc-static)
include("${CMAKE_CURRENT_LIST_DIR}/msgpack-targets.cmake")
endif()

10
msgpack.pc.in Normal file
View File

@@ -0,0 +1,10 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: MessagePack
Description: Binary-based efficient object serialization library
Version: @VERSION@
Libs: -L${libdir} -lmsgpackc
Cflags: -I${includedir}

484
src/objectc.c Normal file
View File

@@ -0,0 +1,484 @@
/*
* MessagePack for C dynamic typing routine
*
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#if defined(_KERNEL_MODE)
# undef _NO_CRT_STDIO_INLINE
# define _NO_CRT_STDIO_INLINE
#endif
#include "msgpack/object.h"
#include "msgpack/pack.h"
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#if defined(_MSC_VER)
#if _MSC_VER >= 1800
#include <inttypes.h>
#else
#define PRIu64 "I64u"
#define PRIi64 "I64i"
#define PRIi8 "i"
#endif
#else
#include <inttypes.h>
#endif
#if defined(_KERNEL_MODE)
# undef snprintf
# define snprintf _snprintf
#endif
int msgpack_pack_object(msgpack_packer* pk, msgpack_object d)
{
switch(d.type) {
case MSGPACK_OBJECT_NIL:
return msgpack_pack_nil(pk);
case MSGPACK_OBJECT_BOOLEAN:
if(d.via.boolean) {
return msgpack_pack_true(pk);
} else {
return msgpack_pack_false(pk);
}
case MSGPACK_OBJECT_POSITIVE_INTEGER:
return msgpack_pack_uint64(pk, d.via.u64);
case MSGPACK_OBJECT_NEGATIVE_INTEGER:
return msgpack_pack_int64(pk, d.via.i64);
case MSGPACK_OBJECT_FLOAT32:
return msgpack_pack_float(pk, (float)d.via.f64);
case MSGPACK_OBJECT_FLOAT64:
return msgpack_pack_double(pk, d.via.f64);
case MSGPACK_OBJECT_STR:
{
int ret = msgpack_pack_str(pk, d.via.str.size);
if(ret < 0) { return ret; }
return msgpack_pack_str_body(pk, d.via.str.ptr, d.via.str.size);
}
case MSGPACK_OBJECT_BIN:
{
int ret = msgpack_pack_bin(pk, d.via.bin.size);
if(ret < 0) { return ret; }
return msgpack_pack_bin_body(pk, d.via.bin.ptr, d.via.bin.size);
}
case MSGPACK_OBJECT_EXT:
{
int ret = msgpack_pack_ext(pk, d.via.ext.size, d.via.ext.type);
if(ret < 0) { return ret; }
return msgpack_pack_ext_body(pk, d.via.ext.ptr, d.via.ext.size);
}
case MSGPACK_OBJECT_ARRAY:
{
int ret = msgpack_pack_array(pk, d.via.array.size);
if(ret < 0) {
return ret;
}
else {
msgpack_object* o = d.via.array.ptr;
msgpack_object* const oend = d.via.array.ptr + d.via.array.size;
for(; o != oend; ++o) {
ret = msgpack_pack_object(pk, *o);
if(ret < 0) { return ret; }
}
return 0;
}
}
case MSGPACK_OBJECT_MAP:
{
int ret = msgpack_pack_map(pk, d.via.map.size);
if(ret < 0) {
return ret;
}
else {
msgpack_object_kv* kv = d.via.map.ptr;
msgpack_object_kv* const kvend = d.via.map.ptr + d.via.map.size;
for(; kv != kvend; ++kv) {
ret = msgpack_pack_object(pk, kv->key);
if(ret < 0) { return ret; }
ret = msgpack_pack_object(pk, kv->val);
if(ret < 0) { return ret; }
}
return 0;
}
}
default:
return -1;
}
}
#if !defined(_KERNEL_MODE)
static void msgpack_object_bin_print(FILE* out, const char *ptr, size_t size)
{
size_t i;
for (i = 0; i < size; ++i) {
if (ptr[i] == '"') {
fputs("\\\"", out);
} else if (isprint((unsigned char)ptr[i])) {
fputc(ptr[i], out);
} else {
fprintf(out, "\\x%02x", (unsigned char)ptr[i]);
}
}
}
void msgpack_object_print(FILE* out, msgpack_object o)
{
switch(o.type) {
case MSGPACK_OBJECT_NIL:
fprintf(out, "nil");
break;
case MSGPACK_OBJECT_BOOLEAN:
fprintf(out, (o.via.boolean ? "true" : "false"));
break;
case MSGPACK_OBJECT_POSITIVE_INTEGER:
#if defined(PRIu64)
fprintf(out, "%" PRIu64, o.via.u64);
#else
if (o.via.u64 > ULONG_MAX)
fprintf(out, "over 4294967295");
else
fprintf(out, "%lu", (unsigned long)o.via.u64);
#endif
break;
case MSGPACK_OBJECT_NEGATIVE_INTEGER:
#if defined(PRIi64)
fprintf(out, "%" PRIi64, o.via.i64);
#else
if (o.via.i64 > LONG_MAX)
fprintf(out, "over +2147483647");
else if (o.via.i64 < LONG_MIN)
fprintf(out, "under -2147483648");
else
fprintf(out, "%ld", (signed long)o.via.i64);
#endif
break;
case MSGPACK_OBJECT_FLOAT32:
case MSGPACK_OBJECT_FLOAT64:
fprintf(out, "%f", o.via.f64);
break;
case MSGPACK_OBJECT_STR:
fprintf(out, "\"");
fwrite(o.via.str.ptr, o.via.str.size, 1, out);
fprintf(out, "\"");
break;
case MSGPACK_OBJECT_BIN:
fprintf(out, "\"");
msgpack_object_bin_print(out, o.via.bin.ptr, o.via.bin.size);
fprintf(out, "\"");
break;
case MSGPACK_OBJECT_EXT:
#if defined(PRIi8)
fprintf(out, "(ext: %" PRIi8 ")", o.via.ext.type);
#else
fprintf(out, "(ext: %d)", (int)o.via.ext.type);
#endif
fprintf(out, "\"");
msgpack_object_bin_print(out, o.via.ext.ptr, o.via.ext.size);
fprintf(out, "\"");
break;
case MSGPACK_OBJECT_ARRAY:
fprintf(out, "[");
if(o.via.array.size != 0) {
msgpack_object* p = o.via.array.ptr;
msgpack_object* const pend = o.via.array.ptr + o.via.array.size;
msgpack_object_print(out, *p);
++p;
for(; p < pend; ++p) {
fprintf(out, ", ");
msgpack_object_print(out, *p);
}
}
fprintf(out, "]");
break;
case MSGPACK_OBJECT_MAP:
fprintf(out, "{");
if(o.via.map.size != 0) {
msgpack_object_kv* p = o.via.map.ptr;
msgpack_object_kv* const pend = o.via.map.ptr + o.via.map.size;
msgpack_object_print(out, p->key);
fprintf(out, "=>");
msgpack_object_print(out, p->val);
++p;
for(; p < pend; ++p) {
fprintf(out, ", ");
msgpack_object_print(out, p->key);
fprintf(out, "=>");
msgpack_object_print(out, p->val);
}
}
fprintf(out, "}");
break;
default:
// FIXME
#if defined(PRIu64)
fprintf(out, "#<UNKNOWN %i %" PRIu64 ">", o.type, o.via.u64);
#else
if (o.via.u64 > ULONG_MAX)
fprintf(out, "#<UNKNOWN %i over 4294967295>", o.type);
else
fprintf(out, "#<UNKNOWN %i %lu>", o.type, (unsigned long)o.via.u64);
#endif
}
}
#endif
#define MSGPACK_CHECKED_CALL(ret, func, aux_buffer, aux_buffer_size, ...) \
ret = func(aux_buffer, aux_buffer_size, __VA_ARGS__); \
if (ret <= 0 || ret >= (int)aux_buffer_size) return 0; \
aux_buffer = aux_buffer + ret; \
aux_buffer_size = aux_buffer_size - ret \
static int msgpack_object_bin_print_buffer(char *buffer, size_t buffer_size, const char *ptr, size_t size)
{
size_t i;
char *aux_buffer = buffer;
size_t aux_buffer_size = buffer_size;
int ret;
for (i = 0; i < size; ++i) {
if (ptr[i] == '"') {
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\\\"");
} else if (isprint((unsigned char)ptr[i])) {
if (aux_buffer_size > 0) {
memcpy(aux_buffer, ptr + i, 1);
aux_buffer = aux_buffer + 1;
aux_buffer_size = aux_buffer_size - 1;
}
} else {
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\\x%02x", (unsigned char)ptr[i]);
}
}
return (int)(buffer_size - aux_buffer_size);
}
int msgpack_object_print_buffer(char *buffer, size_t buffer_size, msgpack_object o)
{
char *aux_buffer = buffer;
size_t aux_buffer_size = buffer_size;
int ret;
switch(o.type) {
case MSGPACK_OBJECT_NIL:
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "nil");
break;
case MSGPACK_OBJECT_BOOLEAN:
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, (o.via.boolean ? "true" : "false"));
break;
case MSGPACK_OBJECT_POSITIVE_INTEGER:
#if defined(PRIu64)
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%" PRIu64, o.via.u64);
#else
if (o.via.u64 > ULONG_MAX) {
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "over 4294967295");
} else {
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%lu", (unsigned long)o.via.u64);
}
#endif
break;
case MSGPACK_OBJECT_NEGATIVE_INTEGER:
#if defined(PRIi64)
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%" PRIi64, o.via.i64);
#else
if (o.via.i64 > LONG_MAX) {
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "over +2147483647");
} else if (o.via.i64 < LONG_MIN) {
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "under -2147483648");
} else {
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%ld", (signed long)o.via.i64);
}
#endif
break;
case MSGPACK_OBJECT_FLOAT32:
case MSGPACK_OBJECT_FLOAT64:
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%f", o.via.f64);
break;
case MSGPACK_OBJECT_STR:
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\"");
if (o.via.str.size > 0) {
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%.*s", (int)o.via.str.size, o.via.str.ptr);
}
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\"");
break;
case MSGPACK_OBJECT_BIN:
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\"");
MSGPACK_CHECKED_CALL(ret, msgpack_object_bin_print_buffer, aux_buffer, aux_buffer_size, o.via.bin.ptr, o.via.bin.size);
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\"");
break;
case MSGPACK_OBJECT_EXT:
#if defined(PRIi8)
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "(ext: %" PRIi8 ")", o.via.ext.type);
#else
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "(ext: %d)", (int)o.via.ext.type);
#endif
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\"");
MSGPACK_CHECKED_CALL(ret, msgpack_object_bin_print_buffer, aux_buffer, aux_buffer_size, o.via.ext.ptr, o.via.ext.size);
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\"");
break;
case MSGPACK_OBJECT_ARRAY:
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "[");
if(o.via.array.size != 0) {
msgpack_object* p = o.via.array.ptr;
msgpack_object* const pend = o.via.array.ptr + o.via.array.size;
MSGPACK_CHECKED_CALL(ret, msgpack_object_print_buffer, aux_buffer, aux_buffer_size, *p);
++p;
for(; p < pend; ++p) {
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, ", ");
MSGPACK_CHECKED_CALL(ret, msgpack_object_print_buffer, aux_buffer, aux_buffer_size, *p);
}
}
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "]");
break;
case MSGPACK_OBJECT_MAP:
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "{");
if(o.via.map.size != 0) {
msgpack_object_kv* p = o.via.map.ptr;
msgpack_object_kv* const pend = o.via.map.ptr + o.via.map.size;
MSGPACK_CHECKED_CALL(ret, msgpack_object_print_buffer, aux_buffer, aux_buffer_size, p->key);
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "=>");
MSGPACK_CHECKED_CALL(ret, msgpack_object_print_buffer, aux_buffer, aux_buffer_size, p->val);
++p;
for(; p < pend; ++p) {
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, ", ");
MSGPACK_CHECKED_CALL(ret, msgpack_object_print_buffer, aux_buffer, aux_buffer_size, p->key);
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "=>");
MSGPACK_CHECKED_CALL(ret, msgpack_object_print_buffer, aux_buffer, aux_buffer_size, p->val);
}
}
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "}");
break;
default:
// FIXME
#if defined(PRIu64)
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "#<UNKNOWN %i %" PRIu64 ">", o.type, o.via.u64);
#else
if (o.via.u64 > ULONG_MAX) {
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "#<UNKNOWN %i over 4294967295>", o.type);
} else {
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "#<UNKNOWN %i %lu>", o.type, (unsigned long)o.via.u64);
}
#endif
}
return (int)(buffer_size - aux_buffer_size);
}
#undef MSGPACK_CHECKED_CALL
bool msgpack_object_equal(const msgpack_object x, const msgpack_object y)
{
if(x.type != y.type) { return false; }
switch(x.type) {
case MSGPACK_OBJECT_NIL:
return true;
case MSGPACK_OBJECT_BOOLEAN:
return x.via.boolean == y.via.boolean;
case MSGPACK_OBJECT_POSITIVE_INTEGER:
return x.via.u64 == y.via.u64;
case MSGPACK_OBJECT_NEGATIVE_INTEGER:
return x.via.i64 == y.via.i64;
case MSGPACK_OBJECT_FLOAT32:
case MSGPACK_OBJECT_FLOAT64:
return x.via.f64 == y.via.f64;
case MSGPACK_OBJECT_STR:
return x.via.str.size == y.via.str.size &&
memcmp(x.via.str.ptr, y.via.str.ptr, x.via.str.size) == 0;
case MSGPACK_OBJECT_BIN:
return x.via.bin.size == y.via.bin.size &&
memcmp(x.via.bin.ptr, y.via.bin.ptr, x.via.bin.size) == 0;
case MSGPACK_OBJECT_EXT:
return x.via.ext.size == y.via.ext.size &&
x.via.ext.type == y.via.ext.type &&
memcmp(x.via.ext.ptr, y.via.ext.ptr, x.via.ext.size) == 0;
case MSGPACK_OBJECT_ARRAY:
if(x.via.array.size != y.via.array.size) {
return false;
} else if(x.via.array.size == 0) {
return true;
} else {
msgpack_object* px = x.via.array.ptr;
msgpack_object* const pxend = x.via.array.ptr + x.via.array.size;
msgpack_object* py = y.via.array.ptr;
do {
if(!msgpack_object_equal(*px, *py)) {
return false;
}
++px;
++py;
} while(px < pxend);
return true;
}
case MSGPACK_OBJECT_MAP:
if(x.via.map.size != y.via.map.size) {
return false;
} else if(x.via.map.size == 0) {
return true;
} else {
msgpack_object_kv* px = x.via.map.ptr;
msgpack_object_kv* const pxend = x.via.map.ptr + x.via.map.size;
msgpack_object_kv* py = y.via.map.ptr;
do {
if(!msgpack_object_equal(px->key, py->key) || !msgpack_object_equal(px->val, py->val)) {
return false;
}
++px;
++py;
} while(px < pxend);
return true;
}
default:
return false;
}
}

702
src/unpack.c Normal file
View File

@@ -0,0 +1,702 @@
/*
* MessagePack for C unpacking routine
*
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#include "msgpack/unpack.h"
#include "msgpack/unpack_define.h"
#include "msgpack/util.h"
#include <stdlib.h>
#ifdef _msgpack_atomic_counter_header
#include _msgpack_atomic_counter_header
#endif
typedef struct {
msgpack_zone** z;
bool referenced;
} unpack_user;
#define msgpack_unpack_struct(name) \
struct template ## name
#define msgpack_unpack_func(ret, name) \
ret template ## name
#define msgpack_unpack_callback(name) \
template_callback ## name
#define msgpack_unpack_object msgpack_object
#define msgpack_unpack_user unpack_user
struct template_context;
typedef struct template_context template_context;
static void template_init(template_context* ctx);
static msgpack_object template_data(template_context* ctx);
static int template_execute(
template_context* ctx, const char* data, size_t len, size_t* off);
static inline msgpack_object template_callback_root(unpack_user* u)
{
msgpack_object o;
MSGPACK_UNUSED(u);
o.type = MSGPACK_OBJECT_NIL;
return o;
}
static inline int template_callback_uint8(unpack_user* u, uint8_t d, msgpack_object* o)
{
MSGPACK_UNUSED(u);
o->type = MSGPACK_OBJECT_POSITIVE_INTEGER;
o->via.u64 = d;
return 0;
}
static inline int template_callback_uint16(unpack_user* u, uint16_t d, msgpack_object* o)
{
MSGPACK_UNUSED(u);
o->type = MSGPACK_OBJECT_POSITIVE_INTEGER;
o->via.u64 = d;
return 0;
}
static inline int template_callback_uint32(unpack_user* u, uint32_t d, msgpack_object* o)
{
MSGPACK_UNUSED(u);
o->type = MSGPACK_OBJECT_POSITIVE_INTEGER;
o->via.u64 = d;
return 0;
}
static inline int template_callback_uint64(unpack_user* u, uint64_t d, msgpack_object* o)
{
MSGPACK_UNUSED(u);
o->type = MSGPACK_OBJECT_POSITIVE_INTEGER;
o->via.u64 = d;
return 0;
}
static inline int template_callback_int8(unpack_user* u, int8_t d, msgpack_object* o)
{
MSGPACK_UNUSED(u);
if(d >= 0) {
o->type = MSGPACK_OBJECT_POSITIVE_INTEGER;
o->via.u64 = (uint64_t)d;
return 0;
}
else {
o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER;
o->via.i64 = d;
return 0;
}
}
static inline int template_callback_int16(unpack_user* u, int16_t d, msgpack_object* o)
{
MSGPACK_UNUSED(u);
if(d >= 0) {
o->type = MSGPACK_OBJECT_POSITIVE_INTEGER;
o->via.u64 = (uint64_t)d;
return 0;
}
else {
o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER;
o->via.i64 = d;
return 0;
}
}
static inline int template_callback_int32(unpack_user* u, int32_t d, msgpack_object* o)
{
MSGPACK_UNUSED(u);
if(d >= 0) {
o->type = MSGPACK_OBJECT_POSITIVE_INTEGER;
o->via.u64 = (uint64_t)d;
return 0;
}
else {
o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER;
o->via.i64 = d;
return 0;
}
}
static inline int template_callback_int64(unpack_user* u, int64_t d, msgpack_object* o)
{
MSGPACK_UNUSED(u);
if(d >= 0) {
o->type = MSGPACK_OBJECT_POSITIVE_INTEGER;
o->via.u64 = (uint64_t)d;
return 0;
}
else {
o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER;
o->via.i64 = d;
return 0;
}
}
static inline int template_callback_float(unpack_user* u, float d, msgpack_object* o)
{
MSGPACK_UNUSED(u);
o->type = MSGPACK_OBJECT_FLOAT32;
o->via.f64 = d;
return 0;
}
static inline int template_callback_double(unpack_user* u, double d, msgpack_object* o)
{
MSGPACK_UNUSED(u);
o->type = MSGPACK_OBJECT_FLOAT64;
o->via.f64 = d;
return 0;
}
static inline int template_callback_nil(unpack_user* u, msgpack_object* o)
{
MSGPACK_UNUSED(u);
o->type = MSGPACK_OBJECT_NIL;
return 0;
}
static inline int template_callback_true(unpack_user* u, msgpack_object* o)
{
MSGPACK_UNUSED(u);
o->type = MSGPACK_OBJECT_BOOLEAN;
o->via.boolean = true;
return 0;
}
static inline int template_callback_false(unpack_user* u, msgpack_object* o)
{
MSGPACK_UNUSED(u);
o->type = MSGPACK_OBJECT_BOOLEAN;
o->via.boolean = false;
return 0;
}
static inline int template_callback_array(unpack_user* u, unsigned int n, msgpack_object* o)
{
size_t size;
// Let's leverage the fact that sizeof(msgpack_object) is a compile time constant
// to check for int overflows.
// Note - while n is constrained to 32-bit, the product of n * sizeof(msgpack_object)
// might not be constrained to 4GB on 64-bit systems
#if SIZE_MAX == UINT_MAX
if (n > SIZE_MAX/sizeof(msgpack_object))
return MSGPACK_UNPACK_NOMEM_ERROR;
#endif
o->type = MSGPACK_OBJECT_ARRAY;
o->via.array.size = 0;
size = n * sizeof(msgpack_object);
if (*u->z == NULL) {
*u->z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
if(*u->z == NULL) {
return MSGPACK_UNPACK_NOMEM_ERROR;
}
}
// Unsure whether size = 0 should be an error, and if so, what to return
o->via.array.ptr = (msgpack_object*)msgpack_zone_malloc(*u->z, size);
if(o->via.array.ptr == NULL) { return MSGPACK_UNPACK_NOMEM_ERROR; }
return 0;
}
static inline int template_callback_array_item(unpack_user* u, msgpack_object* c, msgpack_object o)
{
MSGPACK_UNUSED(u);
#if defined(__GNUC__) && !defined(__clang__)
memcpy(&c->via.array.ptr[c->via.array.size], &o, sizeof(msgpack_object));
#else /* __GNUC__ && !__clang__ */
c->via.array.ptr[c->via.array.size] = o;
#endif /* __GNUC__ && !__clang__ */
++c->via.array.size;
return 0;
}
static inline int template_callback_map(unpack_user* u, unsigned int n, msgpack_object* o)
{
size_t size;
// Let's leverage the fact that sizeof(msgpack_object_kv) is a compile time constant
// to check for int overflows
// Note - while n is constrained to 32-bit, the product of n * sizeof(msgpack_object)
// might not be constrained to 4GB on 64-bit systems
// Note - this will always be false on 64-bit systems
#if SIZE_MAX == UINT_MAX
if (n > SIZE_MAX/sizeof(msgpack_object_kv))
return MSGPACK_UNPACK_NOMEM_ERROR;
#endif
o->type = MSGPACK_OBJECT_MAP;
o->via.map.size = 0;
size = n * sizeof(msgpack_object_kv);
if (*u->z == NULL) {
*u->z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
if(*u->z == NULL) {
return MSGPACK_UNPACK_NOMEM_ERROR;
}
}
// Should size = 0 be an error? If so, what error to return?
o->via.map.ptr = (msgpack_object_kv*)msgpack_zone_malloc(*u->z, size);
if(o->via.map.ptr == NULL) { return MSGPACK_UNPACK_NOMEM_ERROR; }
return 0;
}
static inline int template_callback_map_item(unpack_user* u, msgpack_object* c, msgpack_object k, msgpack_object v)
{
MSGPACK_UNUSED(u);
#if defined(__GNUC__) && !defined(__clang__)
memcpy(&c->via.map.ptr[c->via.map.size].key, &k, sizeof(msgpack_object));
memcpy(&c->via.map.ptr[c->via.map.size].val, &v, sizeof(msgpack_object));
#else /* __GNUC__ && !__clang__ */
c->via.map.ptr[c->via.map.size].key = k;
c->via.map.ptr[c->via.map.size].val = v;
#endif /* __GNUC__ && !__clang__ */
++c->via.map.size;
return 0;
}
static inline int template_callback_str(unpack_user* u, const char* b, const char* p, unsigned int l, msgpack_object* o)
{
MSGPACK_UNUSED(b);
if (*u->z == NULL) {
*u->z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
if(*u->z == NULL) {
return MSGPACK_UNPACK_NOMEM_ERROR;
}
}
o->type = MSGPACK_OBJECT_STR;
o->via.str.ptr = p;
o->via.str.size = l;
u->referenced = true;
return 0;
}
static inline int template_callback_bin(unpack_user* u, const char* b, const char* p, unsigned int l, msgpack_object* o)
{
MSGPACK_UNUSED(b);
if (*u->z == NULL) {
*u->z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
if(*u->z == NULL) {
return MSGPACK_UNPACK_NOMEM_ERROR;
}
}
o->type = MSGPACK_OBJECT_BIN;
o->via.bin.ptr = p;
o->via.bin.size = l;
u->referenced = true;
return 0;
}
static inline int template_callback_ext(unpack_user* u, const char* b, const char* p, unsigned int l, msgpack_object* o)
{
MSGPACK_UNUSED(b);
if (l == 0) {
return MSGPACK_UNPACK_PARSE_ERROR;
}
if (*u->z == NULL) {
*u->z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
if(*u->z == NULL) {
return MSGPACK_UNPACK_NOMEM_ERROR;
}
}
o->type = MSGPACK_OBJECT_EXT;
o->via.ext.type = *p;
o->via.ext.ptr = p + 1;
o->via.ext.size = l - 1;
u->referenced = true;
return 0;
}
#include "msgpack/unpack_template.h"
#define CTX_CAST(m) ((template_context*)(m))
#define CTX_REFERENCED(mpac) CTX_CAST((mpac)->ctx)->user.referenced
#define COUNTER_SIZE (sizeof(_msgpack_atomic_counter_t))
static inline void init_count(void* buffer)
{
*(volatile _msgpack_atomic_counter_t*)buffer = 1;
}
static inline void decr_count(void* buffer)
{
// atomic if(--*(_msgpack_atomic_counter_t*)buffer == 0) { free(buffer); }
if(_msgpack_sync_decr_and_fetch((volatile _msgpack_atomic_counter_t*)buffer) == 0) {
free(buffer);
}
}
static inline void incr_count(void* buffer)
{
// atomic ++*(_msgpack_atomic_counter_t*)buffer;
_msgpack_sync_incr_and_fetch((volatile _msgpack_atomic_counter_t*)buffer);
}
static inline _msgpack_atomic_counter_t get_count(void* buffer)
{
return *(volatile _msgpack_atomic_counter_t*)buffer;
}
bool msgpack_unpacker_init(msgpack_unpacker* mpac, size_t initial_buffer_size)
{
char* buffer;
void* ctx;
if(initial_buffer_size < COUNTER_SIZE) {
initial_buffer_size = COUNTER_SIZE;
}
buffer = (char*)malloc(initial_buffer_size);
if(buffer == NULL) {
return false;
}
ctx = malloc(sizeof(template_context));
if(ctx == NULL) {
free(buffer);
return false;
}
mpac->buffer = buffer;
mpac->used = COUNTER_SIZE;
mpac->free = initial_buffer_size - mpac->used;
mpac->off = COUNTER_SIZE;
mpac->parsed = 0;
mpac->initial_buffer_size = initial_buffer_size;
mpac->z = NULL;
mpac->ctx = ctx;
init_count(mpac->buffer);
template_init(CTX_CAST(mpac->ctx));
CTX_CAST(mpac->ctx)->user.z = &mpac->z;
CTX_CAST(mpac->ctx)->user.referenced = false;
return true;
}
void msgpack_unpacker_destroy(msgpack_unpacker* mpac)
{
msgpack_zone_free(mpac->z);
free(mpac->ctx);
decr_count(mpac->buffer);
}
msgpack_unpacker* msgpack_unpacker_new(size_t initial_buffer_size)
{
msgpack_unpacker* mpac = (msgpack_unpacker*)malloc(sizeof(msgpack_unpacker));
if(mpac == NULL) {
return NULL;
}
if(!msgpack_unpacker_init(mpac, initial_buffer_size)) {
free(mpac);
return NULL;
}
return mpac;
}
void msgpack_unpacker_free(msgpack_unpacker* mpac)
{
msgpack_unpacker_destroy(mpac);
free(mpac);
}
bool msgpack_unpacker_expand_buffer(msgpack_unpacker* mpac, size_t size)
{
if(mpac->used == mpac->off && get_count(mpac->buffer) == 1
&& !CTX_REFERENCED(mpac)) {
// rewind buffer
mpac->free += mpac->used - COUNTER_SIZE;
mpac->used = COUNTER_SIZE;
mpac->off = COUNTER_SIZE;
if(mpac->free >= size) {
return true;
}
}
if(mpac->off == COUNTER_SIZE) {
char* tmp;
size_t next_size = (mpac->used + mpac->free) * 2; // include COUNTER_SIZE
while(next_size < size + mpac->used) {
size_t tmp_next_size = next_size * 2;
if (tmp_next_size <= next_size) {
next_size = size + mpac->used;
break;
}
next_size = tmp_next_size;
}
tmp = (char*)realloc(mpac->buffer, next_size);
if(tmp == NULL) {
return false;
}
mpac->buffer = tmp;
mpac->free = next_size - mpac->used;
} else {
char* tmp;
size_t next_size = mpac->initial_buffer_size; // include COUNTER_SIZE
size_t not_parsed = mpac->used - mpac->off;
while(next_size < size + not_parsed + COUNTER_SIZE) {
size_t tmp_next_size = next_size * 2;
if (tmp_next_size <= next_size) {
next_size = size + not_parsed + COUNTER_SIZE;
break;
}
next_size = tmp_next_size;
}
tmp = (char*)malloc(next_size);
if(tmp == NULL) {
return false;
}
init_count(tmp);
memcpy(tmp+COUNTER_SIZE, mpac->buffer+mpac->off, not_parsed);
if(CTX_REFERENCED(mpac)) {
if(!msgpack_zone_push_finalizer(mpac->z, decr_count, mpac->buffer)) {
free(tmp);
return false;
}
CTX_REFERENCED(mpac) = false;
} else {
decr_count(mpac->buffer);
}
mpac->buffer = tmp;
mpac->used = not_parsed + COUNTER_SIZE;
mpac->free = next_size - mpac->used;
mpac->off = COUNTER_SIZE;
}
return true;
}
int msgpack_unpacker_execute(msgpack_unpacker* mpac)
{
size_t off = mpac->off;
int ret = template_execute(CTX_CAST(mpac->ctx),
mpac->buffer, mpac->used, &mpac->off);
if(mpac->off > off) {
mpac->parsed += mpac->off - off;
}
return ret;
}
msgpack_object msgpack_unpacker_data(msgpack_unpacker* mpac)
{
return template_data(CTX_CAST(mpac->ctx));
}
msgpack_zone* msgpack_unpacker_release_zone(msgpack_unpacker* mpac)
{
msgpack_zone* old = mpac->z;
if (old == NULL) return NULL;
if(!msgpack_unpacker_flush_zone(mpac)) {
return NULL;
}
mpac->z = NULL;
CTX_CAST(mpac->ctx)->user.z = &mpac->z;
return old;
}
void msgpack_unpacker_reset_zone(msgpack_unpacker* mpac)
{
msgpack_zone_clear(mpac->z);
}
bool msgpack_unpacker_flush_zone(msgpack_unpacker* mpac)
{
if(CTX_REFERENCED(mpac)) {
if(!msgpack_zone_push_finalizer(mpac->z, decr_count, mpac->buffer)) {
return false;
}
CTX_REFERENCED(mpac) = false;
incr_count(mpac->buffer);
}
return true;
}
void msgpack_unpacker_reset(msgpack_unpacker* mpac)
{
template_init(CTX_CAST(mpac->ctx));
// don't reset referenced flag
mpac->parsed = 0;
}
static inline msgpack_unpack_return unpacker_next(msgpack_unpacker* mpac,
msgpack_unpacked* result)
{
int ret;
msgpack_unpacked_destroy(result);
ret = msgpack_unpacker_execute(mpac);
if(ret < 0) {
result->zone = NULL;
memset(&result->data, 0, sizeof(msgpack_object));
return (msgpack_unpack_return)ret;
}
if(ret == 0) {
return MSGPACK_UNPACK_CONTINUE;
}
result->zone = msgpack_unpacker_release_zone(mpac);
result->data = msgpack_unpacker_data(mpac);
return MSGPACK_UNPACK_SUCCESS;
}
msgpack_unpack_return msgpack_unpacker_next(msgpack_unpacker* mpac,
msgpack_unpacked* result)
{
msgpack_unpack_return ret;
ret = unpacker_next(mpac, result);
if (ret == MSGPACK_UNPACK_SUCCESS) {
msgpack_unpacker_reset(mpac);
}
return ret;
}
msgpack_unpack_return
msgpack_unpacker_next_with_size(msgpack_unpacker* mpac,
msgpack_unpacked* result, size_t *p_bytes)
{
msgpack_unpack_return ret;
ret = unpacker_next(mpac, result);
if (ret == MSGPACK_UNPACK_SUCCESS || ret == MSGPACK_UNPACK_CONTINUE) {
*p_bytes = mpac->parsed;
}
if (ret == MSGPACK_UNPACK_SUCCESS) {
msgpack_unpacker_reset(mpac);
}
return ret;
}
msgpack_unpack_return
msgpack_unpack(const char* data, size_t len, size_t* off,
msgpack_zone* result_zone, msgpack_object* result)
{
size_t noff = 0;
if(off != NULL) { noff = *off; }
if(len <= noff) {
// FIXME
return MSGPACK_UNPACK_CONTINUE;
}
else {
int e;
template_context ctx;
template_init(&ctx);
ctx.user.z = &result_zone;
ctx.user.referenced = false;
e = template_execute(&ctx, data, len, &noff);
if(e < 0) {
return (msgpack_unpack_return)e;
}
if(off != NULL) { *off = noff; }
if(e == 0) {
return MSGPACK_UNPACK_CONTINUE;
}
*result = template_data(&ctx);
if(noff < len) {
return MSGPACK_UNPACK_EXTRA_BYTES;
}
return MSGPACK_UNPACK_SUCCESS;
}
}
msgpack_unpack_return
msgpack_unpack_next(msgpack_unpacked* result,
const char* data, size_t len, size_t* off)
{
size_t noff = 0;
msgpack_unpacked_destroy(result);
if(off != NULL) { noff = *off; }
if(len <= noff) {
return MSGPACK_UNPACK_CONTINUE;
}
{
int e;
template_context ctx;
template_init(&ctx);
ctx.user.z = &result->zone;
ctx.user.referenced = false;
e = template_execute(&ctx, data, len, &noff);
if(off != NULL) { *off = noff; }
if(e < 0) {
msgpack_zone_free(result->zone);
result->zone = NULL;
return (msgpack_unpack_return)e;
}
if(e == 0) {
return MSGPACK_UNPACK_CONTINUE;
}
result->data = template_data(&ctx);
return MSGPACK_UNPACK_SUCCESS;
}
}
#if defined(MSGPACK_OLD_COMPILER_BUS_ERROR_WORKAROUND)
// FIXME: Dirty hack to avoid a bus error caused by OS X's old gcc.
static void dummy_function_to_avoid_bus_error()
{
}
#endif

22
src/version.c Normal file
View File

@@ -0,0 +1,22 @@
#include "msgpack.h"
const char* msgpack_version(void)
{
return MSGPACK_VERSION;
}
int msgpack_version_major(void)
{
return MSGPACK_VERSION_MAJOR;
}
int msgpack_version_minor(void)
{
return MSGPACK_VERSION_MINOR;
}
int msgpack_version_revision(void)
{
return MSGPACK_VERSION_REVISION;
}

250
src/vrefbuffer.c Normal file
View File

@@ -0,0 +1,250 @@
/*
* MessagePack for C zero-copy buffer implementation
*
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#include "msgpack/vrefbuffer.h"
#include <stdlib.h>
#include <string.h>
#define MSGPACK_PACKER_MAX_BUFFER_SIZE 9
struct msgpack_vrefbuffer_chunk {
struct msgpack_vrefbuffer_chunk* next;
/* data ... */
};
bool msgpack_vrefbuffer_init(msgpack_vrefbuffer* vbuf,
size_t ref_size, size_t chunk_size)
{
size_t nfirst;
msgpack_iovec* array;
msgpack_vrefbuffer_chunk* chunk;
if (ref_size == 0) {
ref_size = MSGPACK_VREFBUFFER_REF_SIZE;
}
if(chunk_size == 0) {
chunk_size = MSGPACK_VREFBUFFER_CHUNK_SIZE;
}
vbuf->chunk_size = chunk_size;
vbuf->ref_size =
ref_size > MSGPACK_PACKER_MAX_BUFFER_SIZE + 1 ?
ref_size : MSGPACK_PACKER_MAX_BUFFER_SIZE + 1 ;
if((sizeof(msgpack_vrefbuffer_chunk) + chunk_size) < chunk_size) {
return false;
}
nfirst = (sizeof(msgpack_iovec) < 72/2) ?
72 / sizeof(msgpack_iovec) : 8;
array = (msgpack_iovec*)malloc(
sizeof(msgpack_iovec) * nfirst);
if(array == NULL) {
return false;
}
vbuf->tail = array;
vbuf->end = array + nfirst;
vbuf->array = array;
chunk = (msgpack_vrefbuffer_chunk*)malloc(
sizeof(msgpack_vrefbuffer_chunk) + chunk_size);
if(chunk == NULL) {
free(array);
return false;
}
else {
msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
ib->free = chunk_size;
ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
ib->head = chunk;
chunk->next = NULL;
return true;
}
}
void msgpack_vrefbuffer_destroy(msgpack_vrefbuffer* vbuf)
{
msgpack_vrefbuffer_chunk* c = vbuf->inner_buffer.head;
while(true) {
msgpack_vrefbuffer_chunk* n = c->next;
free(c);
if(n != NULL) {
c = n;
} else {
break;
}
}
free(vbuf->array);
}
void msgpack_vrefbuffer_clear(msgpack_vrefbuffer* vbuf)
{
msgpack_vrefbuffer_chunk* c = vbuf->inner_buffer.head->next;
msgpack_vrefbuffer_chunk* n;
while(c != NULL) {
n = c->next;
free(c);
c = n;
}
{
msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
msgpack_vrefbuffer_chunk* chunk = ib->head;
chunk->next = NULL;
ib->free = vbuf->chunk_size;
ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
vbuf->tail = vbuf->array;
}
}
int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf,
const char* buf, size_t len)
{
if(vbuf->tail == vbuf->end) {
const size_t nused = (size_t)(vbuf->tail - vbuf->array);
const size_t nnext = nused * 2;
msgpack_iovec* nvec = (msgpack_iovec*)realloc(
vbuf->array, sizeof(msgpack_iovec)*nnext);
if(nvec == NULL) {
return -1;
}
vbuf->array = nvec;
vbuf->end = nvec + nnext;
vbuf->tail = nvec + nused;
}
vbuf->tail->iov_base = (char*)buf;
vbuf->tail->iov_len = len;
++vbuf->tail;
return 0;
}
int msgpack_vrefbuffer_append_copy(msgpack_vrefbuffer* vbuf,
const char* buf, size_t len)
{
msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
char* m;
if(ib->free < len) {
msgpack_vrefbuffer_chunk* chunk;
size_t sz = vbuf->chunk_size;
if(sz < len) {
sz = len;
}
if((sizeof(msgpack_vrefbuffer_chunk) + sz) < sz){
return -1;
}
chunk = (msgpack_vrefbuffer_chunk*)malloc(
sizeof(msgpack_vrefbuffer_chunk) + sz);
if(chunk == NULL) {
return -1;
}
chunk->next = ib->head;
ib->head = chunk;
ib->free = sz;
ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
}
m = ib->ptr;
memcpy(m, buf, len);
ib->free -= len;
ib->ptr += len;
if(vbuf->tail != vbuf->array && m ==
(const char*)((vbuf->tail-1)->iov_base) + (vbuf->tail-1)->iov_len) {
(vbuf->tail-1)->iov_len += len;
return 0;
} else {
return msgpack_vrefbuffer_append_ref(vbuf, m, len);
}
}
int msgpack_vrefbuffer_migrate(msgpack_vrefbuffer* vbuf, msgpack_vrefbuffer* to)
{
size_t sz = vbuf->chunk_size;
msgpack_vrefbuffer_chunk* empty;
if((sizeof(msgpack_vrefbuffer_chunk) + sz) < sz){
return -1;
}
empty = (msgpack_vrefbuffer_chunk*)malloc(
sizeof(msgpack_vrefbuffer_chunk) + sz);
if(empty == NULL) {
return -1;
}
empty->next = NULL;
{
const size_t nused = (size_t)(vbuf->tail - vbuf->array);
if(to->tail + nused < vbuf->end) {
msgpack_iovec* nvec;
const size_t tosize = (size_t)(to->tail - to->array);
const size_t reqsize = nused + tosize;
size_t nnext = (size_t)(to->end - to->array) * 2;
while(nnext < reqsize) {
size_t tmp_nnext = nnext * 2;
if (tmp_nnext <= nnext) {
nnext = reqsize;
break;
}
nnext = tmp_nnext;
}
nvec = (msgpack_iovec*)realloc(
to->array, sizeof(msgpack_iovec)*nnext);
if(nvec == NULL) {
free(empty);
return -1;
}
to->array = nvec;
to->end = nvec + nnext;
to->tail = nvec + tosize;
}
memcpy(to->tail, vbuf->array, sizeof(msgpack_iovec)*nused);
to->tail += nused;
vbuf->tail = vbuf->array;
{
msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
msgpack_vrefbuffer_inner_buffer* const toib = &to->inner_buffer;
msgpack_vrefbuffer_chunk* last = ib->head;
while(last->next != NULL) {
last = last->next;
}
last->next = toib->head;
toib->head = ib->head;
if(toib->free < ib->free) {
toib->free = ib->free;
toib->ptr = ib->ptr;
}
ib->head = empty;
ib->free = sz;
ib->ptr = ((char*)empty) + sizeof(msgpack_vrefbuffer_chunk);
}
}
return 0;
}

222
src/zone.c Normal file
View File

@@ -0,0 +1,222 @@
/*
* MessagePack for C memory pool implementation
*
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#include "msgpack/zone.h"
#include <stdlib.h>
#include <string.h>
struct msgpack_zone_chunk {
struct msgpack_zone_chunk* next;
/* data ... */
};
static inline bool init_chunk_list(msgpack_zone_chunk_list* cl, size_t chunk_size)
{
msgpack_zone_chunk* chunk = (msgpack_zone_chunk*)malloc(
sizeof(msgpack_zone_chunk) + chunk_size);
if(chunk == NULL) {
return false;
}
cl->head = chunk;
cl->free = chunk_size;
cl->ptr = ((char*)chunk) + sizeof(msgpack_zone_chunk);
chunk->next = NULL;
return true;
}
static inline void destroy_chunk_list(msgpack_zone_chunk_list* cl)
{
msgpack_zone_chunk* c = cl->head;
while(true) {
msgpack_zone_chunk* n = c->next;
free(c);
if(n != NULL) {
c = n;
} else {
break;
}
}
}
static inline void clear_chunk_list(msgpack_zone_chunk_list* cl, size_t chunk_size)
{
msgpack_zone_chunk* c = cl->head;
while(true) {
msgpack_zone_chunk* n = c->next;
if(n != NULL) {
free(c);
c = n;
} else {
cl->head = c;
break;
}
}
cl->head->next = NULL;
cl->free = chunk_size;
cl->ptr = ((char*)cl->head) + sizeof(msgpack_zone_chunk);
}
void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size)
{
msgpack_zone_chunk_list* const cl = &zone->chunk_list;
msgpack_zone_chunk* chunk;
size_t sz = zone->chunk_size;
while(sz < size) {
size_t tmp_sz = sz * 2;
if (tmp_sz <= sz) {
sz = size;
break;
}
sz = tmp_sz;
}
chunk = (msgpack_zone_chunk*)malloc(
sizeof(msgpack_zone_chunk) + sz);
if (chunk == NULL) {
return NULL;
}
else {
char* ptr = ((char*)chunk) + sizeof(msgpack_zone_chunk);
chunk->next = cl->head;
cl->head = chunk;
cl->free = sz - size;
cl->ptr = ptr + size;
return ptr;
}
}
static inline void init_finalizer_array(msgpack_zone_finalizer_array* fa)
{
fa->tail = NULL;
fa->end = NULL;
fa->array = NULL;
}
static inline void call_finalizer_array(msgpack_zone_finalizer_array* fa)
{
msgpack_zone_finalizer* fin = fa->tail;
for(; fin != fa->array; --fin) {
(*(fin-1)->func)((fin-1)->data);
}
}
static inline void destroy_finalizer_array(msgpack_zone_finalizer_array* fa)
{
call_finalizer_array(fa);
free(fa->array);
}
static inline void clear_finalizer_array(msgpack_zone_finalizer_array* fa)
{
call_finalizer_array(fa);
fa->tail = fa->array;
}
bool msgpack_zone_push_finalizer_expand(msgpack_zone* zone,
void (*func)(void* data), void* data)
{
msgpack_zone_finalizer_array* const fa = &zone->finalizer_array;
msgpack_zone_finalizer* tmp;
const size_t nused = (size_t)(fa->end - fa->array);
size_t nnext;
if(nused == 0) {
nnext = (sizeof(msgpack_zone_finalizer) < 72/2) ?
72 / sizeof(msgpack_zone_finalizer) : 8;
} else {
nnext = nused * 2;
}
tmp = (msgpack_zone_finalizer*)realloc(fa->array,
sizeof(msgpack_zone_finalizer) * nnext);
if(tmp == NULL) {
return false;
}
fa->array = tmp;
fa->end = tmp + nnext;
fa->tail = tmp + nused;
fa->tail->func = func;
fa->tail->data = data;
++fa->tail;
return true;
}
bool msgpack_zone_is_empty(msgpack_zone* zone)
{
msgpack_zone_chunk_list* const cl = &zone->chunk_list;
msgpack_zone_finalizer_array* const fa = &zone->finalizer_array;
return cl->free == zone->chunk_size && cl->head->next == NULL &&
fa->tail == fa->array;
}
void msgpack_zone_destroy(msgpack_zone* zone)
{
destroy_finalizer_array(&zone->finalizer_array);
destroy_chunk_list(&zone->chunk_list);
}
void msgpack_zone_clear(msgpack_zone* zone)
{
clear_finalizer_array(&zone->finalizer_array);
clear_chunk_list(&zone->chunk_list, zone->chunk_size);
}
bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size)
{
zone->chunk_size = chunk_size;
if(!init_chunk_list(&zone->chunk_list, chunk_size)) {
return false;
}
init_finalizer_array(&zone->finalizer_array);
return true;
}
msgpack_zone* msgpack_zone_new(size_t chunk_size)
{
msgpack_zone* zone = (msgpack_zone*)malloc(
sizeof(msgpack_zone));
if(zone == NULL) {
return NULL;
}
zone->chunk_size = chunk_size;
if(!init_chunk_list(&zone->chunk_list, chunk_size)) {
free(zone);
return NULL;
}
init_finalizer_array(&zone->finalizer_array);
return zone;
}
void msgpack_zone_free(msgpack_zone* zone)
{
if(zone == NULL) { return; }
msgpack_zone_destroy(zone);
free(zone);
}

46
test/CMakeLists.txt Normal file
View File

@@ -0,0 +1,46 @@
FIND_PACKAGE (GTest REQUIRED)
FIND_PACKAGE (ZLIB REQUIRED)
FIND_PACKAGE (Threads REQUIRED)
INCLUDE_DIRECTORIES (
${GTEST_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIRS}
)
SET (check_PROGRAMS
buffer_c.cpp
fixint_c.cpp
msgpack_c.cpp
pack_unpack_c.cpp
streaming_c.cpp
)
FOREACH (source_file ${check_PROGRAMS})
GET_FILENAME_COMPONENT (source_file_we ${source_file} NAME_WE)
ADD_EXECUTABLE (
${source_file_we}
${source_file}
)
TARGET_LINK_LIBRARIES (${source_file_we}
msgpackc
${GTEST_BOTH_LIBRARIES}
${ZLIB_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
)
ADD_TEST (${source_file_we} ${source_file_we})
IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
SET_PROPERTY (TARGET ${source_file_we} APPEND_STRING PROPERTY COMPILE_FLAGS " -Wall -Wextra -Wconversion")
ENDIF ()
IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
SET_PROPERTY (TARGET ${source_file_we} APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-mismatched-tags")
ENDIF ()
IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
IF (CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
STRING(REGEX REPLACE "/W[0-4]" "/W3 /WX" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
ELSE ()
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /WX")
ENDIF ()
ENDIF ()
ENDFOREACH ()

148
test/buffer_c.cpp Normal file
View File

@@ -0,0 +1,148 @@
#include <msgpack/fbuffer.h>
#include <msgpack/zbuffer.h>
#include <msgpack/sbuffer.h>
#include <msgpack/vrefbuffer.h>
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif //defined(__GNUC__)
#include <gtest/gtest.h>
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif //defined(__GNUC__)
#include <string.h>
#if defined(unix) || defined(__unix) || defined(__linux__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__QNX__) || defined(__QNXTO__) || defined(__HAIKU__)
#define HAVE_SYS_UIO_H 1
#else
#define HAVE_SYS_UIO_H 0
#endif
TEST(buffer, zbuffer_c)
{
msgpack_zbuffer zbuf;
EXPECT_TRUE(msgpack_zbuffer_init(&zbuf, 1, MSGPACK_ZBUFFER_INIT_SIZE));
EXPECT_EQ(0, msgpack_zbuffer_write(&zbuf, "a", 1));
EXPECT_EQ(0, msgpack_zbuffer_write(&zbuf, "a", 1));
EXPECT_EQ(0, msgpack_zbuffer_write(&zbuf, "a", 1));
EXPECT_EQ(0, msgpack_zbuffer_write(&zbuf, "", 0));
EXPECT_TRUE(msgpack_zbuffer_flush(&zbuf) != NULL);
msgpack_zbuffer_destroy(&zbuf);
}
TEST(buffer, fbuffer_c)
{
#if defined(_MSC_VER)
FILE* file;
tmpfile_s(&file);
#else // defined(_MSC_VER)
FILE* file = tmpfile();
#endif // defined(_MSC_VER)
void* fbuf = (void*)file;
EXPECT_TRUE( file != NULL );
EXPECT_EQ(0, msgpack_fbuffer_write(fbuf, "a", 1));
EXPECT_EQ(0, msgpack_fbuffer_write(fbuf, "a", 1));
EXPECT_EQ(0, msgpack_fbuffer_write(fbuf, "a", 1));
fflush(file);
rewind(file);
for (size_t i=0; i < 3; ++i) {
int ch = fgetc(file);
EXPECT_TRUE(ch != EOF);
EXPECT_EQ('a', (char) ch);
}
EXPECT_EQ(EOF, fgetc(file));
fclose(file);
}
TEST(buffer, sbuffer_c)
{
msgpack_sbuffer *sbuf;
char *data;
sbuf = msgpack_sbuffer_new();
EXPECT_TRUE(sbuf != NULL);
EXPECT_EQ(0, msgpack_sbuffer_write(sbuf, "a", 1));
EXPECT_EQ(0, msgpack_sbuffer_write(sbuf, "b", 1));
EXPECT_EQ(0, msgpack_sbuffer_write(sbuf, "c", 1));
EXPECT_EQ(0, msgpack_sbuffer_write(sbuf, "", 0));
EXPECT_EQ(3U, sbuf->size);
EXPECT_EQ(0, memcmp(sbuf->data, "abc", 3));
data = msgpack_sbuffer_release(sbuf);
EXPECT_EQ(0, memcmp(data, "abc", 3));
EXPECT_EQ(0U, sbuf->size);
EXPECT_TRUE(sbuf->data == NULL);
free(data);
msgpack_sbuffer_free(sbuf);
}
TEST(buffer, vrefbuffer_c)
{
const char *raw = "I was about to sail away in a junk,"
"When suddenly I heard"
"The sound of stamping and singing on the bank--"
"It was you and your friends come to bid me farewell."
"The Peach Flower Lake is a thousand fathoms deep,"
"But it cannot compare, O Wang Lun,"
"With the depth of your love for me.";
const size_t rawlen = strlen(raw);
msgpack_vrefbuffer *vbuf;
const int ref_size = 24, chunk_size = 128;
size_t slices[] = {0, 9, 10,
MSGPACK_VREFBUFFER_REF_SIZE,
MSGPACK_VREFBUFFER_REF_SIZE + 1,
ref_size, chunk_size + 1};
size_t iovcnt;
const msgpack_iovec *iov;
size_t len = 0, i;
char *buf;
vbuf = msgpack_vrefbuffer_new(ref_size, 0);
for (i = 0; i < sizeof(slices) / sizeof(slices[0]); i++) {
msgpack_vrefbuffer_write(vbuf, raw + len, slices[i]);
len += slices[i];
}
EXPECT_LT(len, rawlen);
iov = msgpack_vrefbuffer_vec(vbuf);
iovcnt = msgpack_vrefbuffer_veclen(vbuf);
buf = (char *)malloc(rawlen);
#if HAVE_SYS_UIO_H
{
int fd;
char filename[] = "/tmp/mp.XXXXXX";
fd = mkstemp(filename);
EXPECT_LT(0, fd);
writev(fd, iov, (int)iovcnt);
len = (size_t)lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
read(fd, buf, len);
EXPECT_EQ(0, memcmp(buf, raw, len));
close(fd);
unlink(filename);
}
#else
{
len = 0;
for (i = 0; i < iovcnt; i++)
{
EXPECT_LT(len, rawlen);
memcpy(buf + len, iov[i].iov_base, iov[i].iov_len);
len += iov[i].iov_len;
}
EXPECT_EQ(0, memcmp(buf, raw, len));
}
#endif
free(buf);
msgpack_vrefbuffer_free(vbuf);
}

41
test/fixint_c.cpp Normal file
View File

@@ -0,0 +1,41 @@
#include <msgpack.h>
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif //defined(__GNUC__)
#include <gtest/gtest.h>
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif //defined(__GNUC__)
TEST(fixint, size)
{
msgpack_sbuffer* sbuf = msgpack_sbuffer_new();
msgpack_packer* pk = msgpack_packer_new(sbuf, msgpack_sbuffer_write);
size_t sum = 0;
EXPECT_EQ(0, msgpack_pack_fix_int8(pk, 0));
EXPECT_EQ(sum+=2, sbuf->size);
EXPECT_EQ(0, msgpack_pack_fix_int16(pk, 0));
EXPECT_EQ(sum+=3, sbuf->size);
EXPECT_EQ(0, msgpack_pack_fix_int32(pk, 0));
EXPECT_EQ(sum+=5, sbuf->size);
EXPECT_EQ(0, msgpack_pack_fix_int64(pk, 0));
EXPECT_EQ(sum+=9, sbuf->size);
EXPECT_EQ(0, msgpack_pack_fix_uint8(pk, 0));
EXPECT_EQ(sum+=2, sbuf->size);
EXPECT_EQ(0, msgpack_pack_fix_uint16(pk, 0));
EXPECT_EQ(sum+=3, sbuf->size);
EXPECT_EQ(0, msgpack_pack_fix_uint32(pk, 0));
EXPECT_EQ(sum+=5, sbuf->size);
EXPECT_EQ(0, msgpack_pack_fix_uint64(pk, 0));
EXPECT_EQ(sum+=9, sbuf->size);
msgpack_sbuffer_free(sbuf);
msgpack_packer_free(pk);
}

1768
test/msgpack_c.cpp Normal file

File diff suppressed because it is too large Load Diff

103
test/pack_unpack_c.cpp Normal file
View File

@@ -0,0 +1,103 @@
#include <msgpack.h>
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif //defined(__GNUC__)
#include <gtest/gtest.h>
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif //defined(__GNUC__)
#include <stdio.h>
TEST(pack, num)
{
msgpack_sbuffer* sbuf = msgpack_sbuffer_new();
msgpack_packer* pk = msgpack_packer_new(sbuf, msgpack_sbuffer_write);
EXPECT_EQ(0, msgpack_pack_int(pk, 1));
msgpack_sbuffer_free(sbuf);
msgpack_packer_free(pk);
}
TEST(pack, array)
{
msgpack_sbuffer* sbuf = msgpack_sbuffer_new();
msgpack_packer* pk = msgpack_packer_new(sbuf, msgpack_sbuffer_write);
EXPECT_EQ(0, msgpack_pack_array(pk, 3));
EXPECT_EQ(0, msgpack_pack_int(pk, 1));
EXPECT_EQ(0, msgpack_pack_int(pk, 2));
EXPECT_EQ(0, msgpack_pack_int(pk, 3));
msgpack_sbuffer_free(sbuf);
msgpack_packer_free(pk);
}
TEST(unpack, sequence)
{
msgpack_sbuffer* sbuf = msgpack_sbuffer_new();
msgpack_packer* pk = msgpack_packer_new(sbuf, msgpack_sbuffer_write);
EXPECT_EQ(0, msgpack_pack_int(pk, 1));
EXPECT_EQ(0, msgpack_pack_int(pk, 2));
EXPECT_EQ(0, msgpack_pack_int(pk, 3));
msgpack_packer_free(pk);
msgpack_unpack_return success;
size_t offset = 0;
msgpack_unpacked msg;
msgpack_unpacked_init(&msg);
success = msgpack_unpack_next(&msg, sbuf->data, sbuf->size, &offset);
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, success);
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, msg.data.type);
EXPECT_EQ(1u, msg.data.via.u64);
success = msgpack_unpack_next(&msg, sbuf->data, sbuf->size, &offset);
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, success);
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, msg.data.type);
EXPECT_EQ(2u, msg.data.via.u64);
success = msgpack_unpack_next(&msg, sbuf->data, sbuf->size, &offset);
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, success);
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, msg.data.type);
EXPECT_EQ(3u, msg.data.via.u64);
success = msgpack_unpack_next(&msg, sbuf->data, sbuf->size, &offset);
EXPECT_EQ(MSGPACK_UNPACK_CONTINUE, success);
msgpack_sbuffer_free(sbuf);
msgpack_unpacked_destroy(&msg);
}
TEST(pack, insufficient)
{
msgpack_sbuffer* sbuf = msgpack_sbuffer_new();
msgpack_packer* pk = msgpack_packer_new(sbuf, msgpack_sbuffer_write);
EXPECT_EQ(0, msgpack_pack_int(pk, 255)); // uint8 (2bytes)
msgpack_unpack_return success;
size_t offset = 0;
msgpack_unpacked msg;
msgpack_unpacked_init(&msg);
success = msgpack_unpack_next(&msg, sbuf->data, 1, &offset);
EXPECT_EQ(MSGPACK_UNPACK_CONTINUE, success);
EXPECT_EQ(1u, offset);
msgpack_unpacked_destroy(&msg);
msgpack_sbuffer_free(sbuf);
msgpack_packer_free(pk);
}

194
test/streaming_c.cpp Normal file
View File

@@ -0,0 +1,194 @@
#include <msgpack.h>
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif //defined(__GNUC__)
#include <gtest/gtest.h>
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif //defined(__GNUC__)
#include <stdio.h>
TEST(streaming, basic)
{
msgpack_sbuffer* buffer = msgpack_sbuffer_new();
msgpack_packer* pk = msgpack_packer_new(buffer, msgpack_sbuffer_write);
// 1, 2, 3, "str", ["str_data"], "bin", ["bin_data"], {0.3: 0.4}
EXPECT_EQ(0, msgpack_pack_int(pk, 1));
EXPECT_EQ(0, msgpack_pack_int(pk, 2));
EXPECT_EQ(0, msgpack_pack_int(pk, 3));
EXPECT_EQ(0, msgpack_pack_str(pk, 3));
EXPECT_EQ(0, msgpack_pack_str_body(pk, "str", 3));
EXPECT_EQ(0, msgpack_pack_array(pk, 1));
EXPECT_EQ(0, msgpack_pack_str(pk, 8));
EXPECT_EQ(0, msgpack_pack_str_body(pk, "str_data", 8));
EXPECT_EQ(0, msgpack_pack_bin(pk, 3));
EXPECT_EQ(0, msgpack_pack_bin_body(pk, "bin", 3));
EXPECT_EQ(0, msgpack_pack_array(pk, 1));
EXPECT_EQ(0, msgpack_pack_bin(pk, 8));
EXPECT_EQ(0, msgpack_pack_bin_body(pk, "bin_data", 8));
EXPECT_EQ(0, msgpack_pack_map(pk, 1));
EXPECT_EQ(0, msgpack_pack_float(pk, 0.4f));
EXPECT_EQ(0, msgpack_pack_double(pk, 0.8));
int max_count = 6;
msgpack_packer_free(pk);
const char* input = buffer->data;
const char* const eof = input + buffer->size;
msgpack_unpacker pac;
msgpack_unpacker_init(&pac, MSGPACK_UNPACKER_INIT_BUFFER_SIZE);
msgpack_unpacked result;
msgpack_unpacked_init(&result);
int count = 0;
while(count < max_count) {
bool unpacked = false;
msgpack_unpacker_reserve_buffer(&pac, 32*1024);
while(!unpacked) {
/* read buffer into msgpack_unapcker_buffer(&pac) upto
* msgpack_unpacker_buffer_capacity(&pac) bytes. */
memcpy(msgpack_unpacker_buffer(&pac), input, 1);
input += 1;
EXPECT_TRUE(input <= eof);
msgpack_unpacker_buffer_consumed(&pac, 1);
while(msgpack_unpacker_next(&pac, &result) == MSGPACK_UNPACK_SUCCESS) {
unpacked = 1;
msgpack_object obj = result.data;
msgpack_object e;
switch(count++) {
case 0:
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, obj.type);
EXPECT_EQ(1u, obj.via.u64);
break;
case 1:
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, obj.type);
EXPECT_EQ(2u, obj.via.u64);
break;
case 2:
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, obj.type);
EXPECT_EQ(3u, obj.via.u64);
break;
case 3:
EXPECT_EQ(MSGPACK_OBJECT_STR, obj.type);
EXPECT_EQ(std::string("str",3), std::string(obj.via.str.ptr, obj.via.str.size));
break;
case 4:
EXPECT_EQ(MSGPACK_OBJECT_ARRAY, obj.type);
EXPECT_EQ(1u, obj.via.array.size);
e = obj.via.array.ptr[0];
EXPECT_EQ(MSGPACK_OBJECT_STR, e.type);
EXPECT_EQ(std::string("str_data",8), std::string(e.via.str.ptr, e.via.str.size));
break;
case 5:
EXPECT_EQ(MSGPACK_OBJECT_BIN, obj.type);
EXPECT_EQ(std::string("bin",3), std::string(obj.via.bin.ptr, obj.via.bin.size));
break;
case 6:
EXPECT_EQ(MSGPACK_OBJECT_ARRAY, obj.type);
EXPECT_EQ(1u, obj.via.array.size);
e = obj.via.array.ptr[0];
EXPECT_EQ(MSGPACK_OBJECT_BIN, e.type);
EXPECT_EQ(std::string("bin_data",8), std::string(e.via.bin.ptr, e.via.bin.size));
break;
case 7:
EXPECT_EQ(MSGPACK_OBJECT_MAP, obj.type);
EXPECT_EQ(1u, obj.via.map.size);
e = obj.via.map.ptr[0].key;
EXPECT_EQ(MSGPACK_OBJECT_FLOAT, e.type);
ASSERT_FLOAT_EQ(0.4f, static_cast<float>(e.via.f64));
#if defined(MSGPACK_USE_LEGACY_NAME_AS_FLOAT)
EXPECT_EQ(MSGPACK_OBJECT_DOUBLE, e.type);
ASSERT_FLOAT_EQ(0.4f, static_cast<float>(e.via.dec));
#endif // MSGPACK_USE_LEGACY_NAME_AS_FLOAT
e = obj.via.map.ptr[0].val;
EXPECT_EQ(MSGPACK_OBJECT_FLOAT, e.type);
ASSERT_DOUBLE_EQ(0.8, e.via.f64);
#if defined(MSGPACK_USE_LEGACY_NAME_AS_FLOAT)
EXPECT_EQ(MSGPACK_OBJECT_DOUBLE, e.type);
ASSERT_DOUBLE_EQ(0.8, e.via.dec);
#endif // MSGPACK_USE_LEGACY_NAME_AS_FLOAT
break;
}
}
}
}
msgpack_unpacker_destroy(&pac);
msgpack_unpacked_destroy(&result);
msgpack_sbuffer_free(buffer);
}
TEST(streaming, basic_with_size)
{
int ret;
size_t bytes;
size_t parsed = 0;
msgpack_sbuffer* buffer = msgpack_sbuffer_new();
msgpack_packer* pk = msgpack_packer_new(buffer, msgpack_sbuffer_write);
msgpack_unpacked result;
msgpack_unpacker *unp;
// 1, 2, 3, "str", ["str_data"], "bin", ["bin_data"], {0.3: 0.4}
msgpack_pack_int(pk, 1);
msgpack_pack_int(pk, 2);
msgpack_pack_int(pk, 3);
msgpack_pack_str(pk, 3);
msgpack_pack_str_body(pk, "str", 3);
msgpack_pack_array(pk, 1);
msgpack_pack_str(pk, 8);
msgpack_pack_str_body(pk, "str_data", 8);
msgpack_pack_bin(pk, 3);
msgpack_pack_bin_body(pk, "bin", 3);
msgpack_pack_array(pk, 1);
msgpack_pack_bin(pk, 8);
msgpack_pack_bin_body(pk, "bin_data", 8);
msgpack_pack_map(pk, 1);
msgpack_pack_float(pk, 0.4f);
msgpack_pack_double(pk, 0.8);
msgpack_packer_free(pk);
unp = msgpack_unpacker_new(32 * 1024);
msgpack_unpacked_init(&result);
const char* input = buffer->data;
while (parsed < buffer->size) {
memcpy(msgpack_unpacker_buffer(unp), input, 1);
msgpack_unpacker_buffer_consumed(unp, 1);
input += 1;
bytes = 0;
ret = msgpack_unpacker_next_with_size(unp, &result, &bytes);
if (ret == MSGPACK_UNPACK_CONTINUE) {
EXPECT_GT(bytes, static_cast<size_t>(0));
continue;
}
while (ret == MSGPACK_UNPACK_SUCCESS) {
EXPECT_GT(bytes, static_cast<size_t>(0));
parsed += bytes;
ret = msgpack_unpacker_next_with_size(unp, &result, &bytes);
}
}
EXPECT_EQ(parsed, buffer->size);
msgpack_unpacked_destroy(&result);
msgpack_unpacker_free(unp);
msgpack_sbuffer_free(buffer);
}

17
update_version.sh Executable file
View File

@@ -0,0 +1,17 @@
#!/bin/sh
if [ "$#" -ne 1 ]; then
echo "Usage: $0 version" >&2
exit 1
fi
major=`echo $1 | sed -e "s/^\([0-9]*\)\.[0-9]*\.[0-9]*/\1/"`
minor=`echo $1 | sed -e "s/^[0-9]*\.\([0-9]*\)\.[0-9]*/\1/"`
revision=`echo $1 | sed -e "s/^[0-9]*\.[0-9]*\.\([0-9]*\)/\1/"`
sed -i -e "s/^\(#define MSGPACK_VERSION_MAJOR[[:space:]]*\)[0-9]*/\1$major/" include/msgpack/version_master.h
sed -i -e "s/^\(#define MSGPACK_VERSION_MINOR[[:space:]]*\)[0-9]*/\1$minor/" include/msgpack/version_master.h
sed -i -e "s/^\(#define MSGPACK_VERSION_REVISION[[:space:]]*\)[0-9]*/\1$revision/" include/msgpack/version_master.h
sed -i -e "s/\(^Version \)[0-9]*\.[0-9]*\.[0-9]*/\1$1/" README.md
sed -i -e "s/\(^version: \)[0-9]*\.[0-9]*\.[0-9]*/\1$1/" appveyor.yml