mirror of
https://github.com/msgpack/msgpack-python.git
synced 2026-02-06 17:59:52 +00:00
Compare commits
No commits in common. "0.1.2" and "main" have entirely different histories.
266 changed files with 7098 additions and 21077 deletions
33
.github/workflows/docs.yaml
vendored
Normal file
33
.github/workflows/docs.yaml
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
name: docs
|
||||
|
||||
on: ["push", "pull_request"]
|
||||
|
||||
jobs:
|
||||
docs:
|
||||
# We want to run on external PRs, but not on our own internal PRs as they'll be run
|
||||
# by the push to the branch.
|
||||
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
cache: "pip"
|
||||
cache-dependency-path: |
|
||||
requirements.txt
|
||||
docs/requirements.txt
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
pip install -r requirements.txt
|
||||
make cython
|
||||
|
||||
- name: Sphinx Documentation Generator
|
||||
run: |
|
||||
pip install -r docs/requirements.txt
|
||||
make docs
|
||||
22
.github/workflows/lint.yaml
vendored
Normal file
22
.github/workflows/lint.yaml
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
name: lint
|
||||
|
||||
on: ["push", "pull_request"]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
# We want to run on external PRs, but not on our own internal PRs as they'll be run
|
||||
# by the push to the branch.
|
||||
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: ruff check
|
||||
run: |
|
||||
pipx run ruff check --diff msgpack/ test/ setup.py
|
||||
|
||||
- name: ruff format
|
||||
run: |
|
||||
pipx run ruff format --diff msgpack/ test/ setup.py
|
||||
61
.github/workflows/test.yml
vendored
Normal file
61
.github/workflows/test.yml
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
name: Run tests
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
create:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
os: ["ubuntu-latest", "windows-latest", "windows-11-arm", "macos-latest"]
|
||||
py: ["3.14", "3.14t", "3.13", "3.12", "3.11", "3.10"]
|
||||
exclude:
|
||||
- os: windows-11-arm
|
||||
py: "3.10"
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: Run test with Python ${{ matrix.py }} on ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: ${{ matrix.py }}
|
||||
allow-prereleases: true
|
||||
cache: "pip"
|
||||
|
||||
- name: Prepare
|
||||
shell: bash
|
||||
run: |
|
||||
python -m pip install -r requirements.txt pytest
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
make cython
|
||||
pip install .
|
||||
|
||||
- name: Test (C extension)
|
||||
shell: bash
|
||||
run: |
|
||||
pytest -v test
|
||||
|
||||
- name: Test (pure Python fallback)
|
||||
shell: bash
|
||||
run: |
|
||||
MSGPACK_PUREPYTHON=1 pytest -v test
|
||||
|
||||
- name: build packages
|
||||
shell: bash
|
||||
run: |
|
||||
python -m build -nv
|
||||
|
||||
- name: upload packages
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dist-${{ matrix.os }}-${{ matrix.py }}
|
||||
path: dist
|
||||
88
.github/workflows/wheel.yml
vendored
Normal file
88
.github/workflows/wheel.yml
vendored
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
name: Build sdist and Wheels
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build_wheels:
|
||||
strategy:
|
||||
matrix:
|
||||
# macos-13 is for intel
|
||||
os: ["ubuntu-24.04", "ubuntu-24.04-arm", "windows-latest", "windows-11-arm", "macos-13", "macos-latest"]
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: Build wheels on ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.x"
|
||||
cache: "pip"
|
||||
- name: Cythonize
|
||||
shell: bash
|
||||
run: |
|
||||
pip install -r requirements.txt
|
||||
make cython
|
||||
|
||||
- name: Build
|
||||
uses: pypa/cibuildwheel@v3.3.0
|
||||
env:
|
||||
CIBW_TEST_REQUIRES: "pytest"
|
||||
CIBW_TEST_COMMAND: "pytest {package}/test"
|
||||
CIBW_SKIP: "pp* cp38-* cp39-* cp310-win_arm64"
|
||||
|
||||
- name: Build sdist
|
||||
if: runner.os == 'Linux' && runner.arch == 'X64'
|
||||
run: |
|
||||
pip install build
|
||||
python -m build -s -o wheelhouse
|
||||
|
||||
- name: Upload Wheels to artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: wheels-${{ matrix.os }}
|
||||
path: wheelhouse
|
||||
|
||||
# combine all wheels into one artifact
|
||||
combine_wheels:
|
||||
needs: [build_wheels]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
# unpacks all CIBW artifacts into dist/
|
||||
pattern: wheels-*
|
||||
path: dist
|
||||
merge-multiple: true
|
||||
|
||||
- name: Upload Wheels to artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: wheels-all
|
||||
path: dist
|
||||
|
||||
# https://github.com/pypa/cibuildwheel/blob/main/examples/github-deploy.yml
|
||||
upload_pypi:
|
||||
needs: [build_wheels]
|
||||
runs-on: ubuntu-latest
|
||||
environment: pypi
|
||||
permissions:
|
||||
id-token: write
|
||||
if: github.event_name == 'release' && github.event.action == 'published'
|
||||
# or, alternatively, upload to PyPI on every tag starting with 'v' (remove on: release above to use this)
|
||||
# if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
# unpacks all CIBW artifacts into dist/
|
||||
pattern: wheels-*
|
||||
path: dist
|
||||
merge-multiple: true
|
||||
|
||||
- uses: pypa/gh-action-pypi-publish@release/v1
|
||||
#with:
|
||||
# To test: repository-url: https://test.pypi.org/legacy/
|
||||
17
.gitignore
vendored
Normal file
17
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
MANIFEST
|
||||
build/*
|
||||
dist/*
|
||||
.tox
|
||||
.python-version
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.so
|
||||
*~
|
||||
msgpack/__version__.py
|
||||
msgpack/*.c
|
||||
msgpack/*.cpp
|
||||
*.egg-info
|
||||
/venv
|
||||
/tags
|
||||
/docs/_build
|
||||
.cache
|
||||
24
.readthedocs.yaml
Normal file
24
.readthedocs.yaml
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# Read the Docs configuration file for Sphinx projects.
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details.
|
||||
|
||||
version: 2
|
||||
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3.11"
|
||||
apt_packages:
|
||||
- build-essential
|
||||
jobs:
|
||||
pre_install:
|
||||
- pip install -r requirements.txt
|
||||
- make cython
|
||||
|
||||
python:
|
||||
install:
|
||||
- method: pip
|
||||
path: .
|
||||
- requirements: docs/requirements.txt
|
||||
|
||||
sphinx:
|
||||
configuration: docs/conf.py
|
||||
1
AUTHORS
1
AUTHORS
|
|
@ -1 +0,0 @@
|
|||
FURUHASHI Sadayuki <frsyuki _at_ users.sourceforge.jp>
|
||||
2
COPYING
2
COPYING
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
Copyright (C) 2008-2011 INADA Naoki <songofacandy@gmail.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
625
ChangeLog.rst
Normal file
625
ChangeLog.rst
Normal file
|
|
@ -0,0 +1,625 @@
|
|||
1.1.2
|
||||
=====
|
||||
|
||||
Release Date: 2025-10-08
|
||||
|
||||
This release does not change source code. It updates only building wheels:
|
||||
|
||||
* Update Cython to v3.1.4
|
||||
* Update cibuildwheel to v3.2.0
|
||||
* Drop Python 3.8
|
||||
* Add Python 3.14
|
||||
* Add windows-arm
|
||||
|
||||
1.1.1
|
||||
=====
|
||||
|
||||
Release Date: 2025-06-13
|
||||
|
||||
* No change from 1.1.1rc1.
|
||||
|
||||
1.1.1rc1
|
||||
========
|
||||
|
||||
Release Date: 2025-06-06
|
||||
|
||||
* Update Cython to 3.1.1 and cibuildwheel to 2.23.3.
|
||||
|
||||
1.1.0
|
||||
=====
|
||||
|
||||
Release Date: 2024-09-10
|
||||
|
||||
* use ``PyLong_*`` instead of ``PyInt_*`` for compatibility with
|
||||
future Cython. (#620)
|
||||
|
||||
1.1.0rc2
|
||||
========
|
||||
|
||||
Release Date: 2024-08-19
|
||||
|
||||
* Update Cython to 3.0.11 for better Python 3.13 support.
|
||||
* Update cibuildwheel to 2.20.0 to build Python 3.13 wheels.
|
||||
|
||||
1.1.0rc1
|
||||
========
|
||||
|
||||
Release Date: 2024-05-07
|
||||
|
||||
* Update Cython to 3.0.10 to reduce C warnings and future support for Python 3.13.
|
||||
* Stop using C++ mode in Cython to reduce compile error on some compilers.
|
||||
* ``Packer()`` has ``buf_size`` option to specify initial size of
|
||||
internal buffer to reduce reallocation.
|
||||
* The default internal buffer size of ``Packer()`` is reduced from
|
||||
1MiB to 256KiB to optimize for common use cases. Use ``buf_size``
|
||||
if you are packing large data.
|
||||
* ``Timestamp.to_datetime()`` and ``Timestamp.from_datetime()`` become
|
||||
more accurate by avoiding floating point calculations. (#591)
|
||||
* The Cython code for ``Unpacker`` has been slightly rewritten for maintainability.
|
||||
* The fallback implementation of ``Packer()`` and ``Unpacker()`` now uses keyword-only
|
||||
arguments to improve compatibility with the Cython implementation.
|
||||
|
||||
1.0.8
|
||||
=====
|
||||
|
||||
Release Date: 2024-03-01
|
||||
|
||||
* Update Cython to 3.0.8. This fixes memory leak when iterating
|
||||
``Unpacker`` object on Python 3.12.
|
||||
* Do not include C/Cython files in binary wheels.
|
||||
|
||||
|
||||
1.0.7
|
||||
=====
|
||||
|
||||
Release Date: 2023-09-28
|
||||
|
||||
* Fix build error of extension module on Windows. (#567)
|
||||
* ``setup.py`` doesn't skip build error of extension module. (#568)
|
||||
|
||||
|
||||
1.0.6
|
||||
=====
|
||||
|
||||
Release Date: 2023-09-21
|
||||
|
||||
.. note::
|
||||
v1.0.6 Wheels for Windows don't contain extension module.
|
||||
Please upgrade to v1.0.7 or newer.
|
||||
|
||||
* Add Python 3.12 wheels (#517)
|
||||
* Remove Python 2.7, 3.6, and 3.7 support
|
||||
|
||||
|
||||
1.0.5
|
||||
=====
|
||||
|
||||
Release Date: 2023-03-08
|
||||
|
||||
* Use ``__BYTE_ORDER__`` instead of ``__BYTE_ORDER`` for portability. (#513, #514)
|
||||
* Add Python 3.11 wheels (#517)
|
||||
* fallback: Fix packing multidimensional memoryview (#527)
|
||||
|
||||
1.0.4
|
||||
=====
|
||||
|
||||
Release Date: 2022-06-03
|
||||
|
||||
* Support Python 3.11 (beta).
|
||||
* Don't define `__*_ENDIAN__` macro on Unix. by @methane in https://github.com/msgpack/msgpack-python/pull/495
|
||||
* Use PyFloat_Pack8() on Python 3.11a7 by @vstinner in https://github.com/msgpack/msgpack-python/pull/499
|
||||
* Fix Unpacker max_buffer_length handling by @methane in https://github.com/msgpack/msgpack-python/pull/506
|
||||
|
||||
1.0.3
|
||||
=====
|
||||
|
||||
Release Date: 2021-11-24 JST
|
||||
|
||||
* Fix Docstring (#459)
|
||||
* Fix error formatting (#463)
|
||||
* Improve error message about strict_map_key (#485)
|
||||
|
||||
1.0.2
|
||||
=====
|
||||
|
||||
* Fix year 2038 problem regression in 1.0.1. (#451)
|
||||
|
||||
1.0.1
|
||||
=====
|
||||
|
||||
* Add Python 3.9 and linux/arm64 wheels. (#439)
|
||||
* Fixed Unpacker.tell() after read_bytes() (#426)
|
||||
* Fixed unpacking datetime before epoch on Windows (#433)
|
||||
* Fixed fallback Packer didn't check DateTime.tzinfo (#434)
|
||||
|
||||
1.0.0
|
||||
=====
|
||||
|
||||
Release Date: 2020-02-17
|
||||
|
||||
* Remove Python 2 support from the ``msgpack/_cmsgpack``.
|
||||
``msgpack/fallback`` still supports Python 2.
|
||||
* Remove ``encoding`` option from the Packer and Unpacker.
|
||||
* Unpacker: The default value of ``max_buffer_size`` is changed to 100MiB.
|
||||
* Unpacker: ``strict_map_key`` is True by default now.
|
||||
* Unpacker: String map keys are interned.
|
||||
* Drop old buffer protocol support.
|
||||
* Support Timestamp type.
|
||||
* Support serializing and decerializing ``datetime`` object
|
||||
with tzinfo.
|
||||
* Unpacker: ``Fix Unpacker.read_bytes()`` in fallback implementation. (#352)
|
||||
|
||||
|
||||
0.6.2
|
||||
=====
|
||||
|
||||
Release Date: 2019-09-20
|
||||
|
||||
* Support Python 3.8.
|
||||
* Update Cython to 0.29.13 for support Python 3.8.
|
||||
* Some small optimizations.
|
||||
|
||||
|
||||
0.6.1
|
||||
======
|
||||
|
||||
Release Date: 2019-01-25
|
||||
|
||||
This release is for mitigating pain caused by v0.6.0 reduced max input limits
|
||||
for security reason.
|
||||
|
||||
* ``unpackb(data)`` configures ``max_*_len`` options from ``len(data)``,
|
||||
instead of static default sizes.
|
||||
|
||||
* ``Unpacker(max_buffer_len=N)`` configures ``max_*_len`` options from ``N``,
|
||||
instead of static default sizes.
|
||||
|
||||
* ``max_bin_len``, ``max_str_len``, and ``max_ext_len`` are deprecated.
|
||||
Since this is minor release, it's document only deprecation.
|
||||
|
||||
|
||||
0.6.0
|
||||
======
|
||||
|
||||
Release Date: 2018-11-30
|
||||
|
||||
This release contains some backward incompatible changes for security reason (DoS).
|
||||
|
||||
Important changes
|
||||
-----------------
|
||||
|
||||
* unpacker: Default value of input limits are smaller than before to avoid DoS attack.
|
||||
If you need to handle large data, you need to specify limits manually. (#319)
|
||||
|
||||
* Unpacker doesn't wrap underlying ``ValueError`` (including ``UnicodeError``) into
|
||||
``UnpackValueError``. If you want to catch all exception during unpack, you need
|
||||
to use ``try ... except Exception`` with minimum try code block. (#323, #233)
|
||||
|
||||
* ``PackValueError`` and ``PackOverflowError`` are also removed. You need to catch
|
||||
normal ``ValueError`` and ``OverflowError``. (#323, #233)
|
||||
|
||||
* Unpacker has ``strict_map_key`` option now. When it is true, only bytes and str
|
||||
(unicode in Python 2) are allowed for map keys. It is recommended to avoid
|
||||
hashdos. Default value of this option is False for backward compatibility reason.
|
||||
But it will be changed True in 1.0. (#296, #334)
|
||||
|
||||
Other changes
|
||||
-------------
|
||||
|
||||
* Extension modules are merged. There is ``msgpack._cmsgpack`` instead of
|
||||
``msgpack._packer`` and ``msgpack._unpacker``. (#314, #328)
|
||||
|
||||
* Add ``Unpacker.getbuffer()`` method. (#320)
|
||||
|
||||
* unpacker: ``msgpack.StackError`` is raised when input data contains too
|
||||
nested data. (#331)
|
||||
|
||||
* unpacker: ``msgpack.FormatError`` is raised when input data is not valid
|
||||
msgpack format. (#331)
|
||||
|
||||
|
||||
0.5.6
|
||||
======
|
||||
|
||||
* Fix fallback.Unpacker.feed() dropped unused data from buffer (#287)
|
||||
* Resurrect fallback.unpack() and _unpacker.unpack().
|
||||
They were removed at 0.5.5 but it breaks backward compatibility. (#288, #290)
|
||||
|
||||
0.5.5
|
||||
======
|
||||
|
||||
* Fix memory leak in pure Python Unpacker.feed() (#283)
|
||||
* Fix unpack() didn't support `raw` option (#285)
|
||||
|
||||
0.5.4
|
||||
======
|
||||
|
||||
* Undeprecate ``unicode_errors`` option. (#278)
|
||||
|
||||
0.5.3
|
||||
======
|
||||
|
||||
* Fixed regression when passing ``unicode_errors`` to Packer but not ``encoding``. (#277)
|
||||
|
||||
0.5.2
|
||||
======
|
||||
|
||||
* Add ``raw`` option to Unpacker. It is preferred way than ``encoding`` option.
|
||||
|
||||
* Packer.pack() reset buffer on exception (#274)
|
||||
|
||||
|
||||
0.5.1
|
||||
======
|
||||
|
||||
* Remove FutureWarning about use_bin_type option (#271)
|
||||
|
||||
0.5.0
|
||||
======
|
||||
|
||||
There are some deprecations. Please read changes carefully.
|
||||
|
||||
Changes
|
||||
-------
|
||||
|
||||
* Drop Python 2.6 and ~3.4 support. Python 2.7 and 3.5+ are supported.
|
||||
|
||||
* Deprecate useless custom exceptions. Use ValueError instead of PackValueError,
|
||||
Exception instead of PackException and UnpackException, etc...
|
||||
See msgpack/exceptions.py
|
||||
|
||||
* Add *strict_types* option to packer. It can be used to serialize subclass of
|
||||
builtin types. For example, when packing object which type is subclass of dict,
|
||||
``default()`` is called. ``default()`` is called for tuple too.
|
||||
|
||||
* Pure Python implementation supports packing memoryview object.
|
||||
|
||||
* Support packing bytearray.
|
||||
|
||||
* Add ``Unpacker.tell()``. And ``write_bytes`` option is deprecated.
|
||||
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* Fixed zero length raw can't be decoded when encoding is specified. (#236)
|
||||
|
||||
|
||||
0.4.8
|
||||
=====
|
||||
:release date: 2016-07-29
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* Calling ext_hook with wrong length. (Only on Windows, maybe. #203)
|
||||
|
||||
|
||||
0.4.7
|
||||
=====
|
||||
:release date: 2016-01-25
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* Memory leak when unpack is failed
|
||||
|
||||
Changes
|
||||
-------
|
||||
|
||||
* Reduce compiler warnings while building extension module
|
||||
* unpack() now accepts ext_hook argument like Unpacker and unpackb()
|
||||
* Update Cython version to 0.23.4
|
||||
* default function is called when integer overflow
|
||||
|
||||
|
||||
0.4.6
|
||||
=====
|
||||
:release date: 2015-03-13
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* fallback.Unpacker: Fix Data corruption when OutOfData.
|
||||
This bug only affects "Streaming unpacking."
|
||||
|
||||
|
||||
0.4.5
|
||||
=====
|
||||
:release date: 2015-01-25
|
||||
|
||||
Incompatible Changes
|
||||
--------------------
|
||||
|
||||
Changes
|
||||
-------
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* Fix test failure on pytest 2.3. (by @ktdreyer)
|
||||
* Fix typos in ChangeLog. (Thanks to @dmick)
|
||||
* Improve README.rst (by @msabramo)
|
||||
|
||||
|
||||
0.4.4
|
||||
=====
|
||||
:release date: 2015-01-09
|
||||
|
||||
Incompatible Changes
|
||||
--------------------
|
||||
|
||||
Changes
|
||||
-------
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* Fix compile error.
|
||||
|
||||
0.4.3
|
||||
=====
|
||||
:release date: 2015-01-07
|
||||
|
||||
Incompatible Changes
|
||||
--------------------
|
||||
|
||||
Changes
|
||||
-------
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* Unpacker may unpack wrong uint32 value on 32bit or LLP64 environment. (#101)
|
||||
* Build failed on Windows Python 2.7.
|
||||
|
||||
0.4.2
|
||||
=====
|
||||
:release date: 2014-03-26
|
||||
|
||||
Incompatible Changes
|
||||
--------------------
|
||||
|
||||
Changes
|
||||
-------
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* Unpacker doesn't increment refcount of ExtType hook.
|
||||
* Packer raises no exception for inputs doesn't fit to msgpack format.
|
||||
|
||||
0.4.1
|
||||
=====
|
||||
:release date: 2014-02-17
|
||||
|
||||
Incompatible Changes
|
||||
--------------------
|
||||
|
||||
Changes
|
||||
-------
|
||||
|
||||
* fallback.Unpacker.feed() supports bytearray.
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* Unpacker doesn't increment refcount of hooks. Hooks may be GCed while unpacking.
|
||||
* Unpacker may read unfilled internal buffer.
|
||||
|
||||
0.4.0
|
||||
=====
|
||||
:release date: 2013-10-21
|
||||
|
||||
Incompatible Changes
|
||||
--------------------
|
||||
|
||||
* Raises TypeError instead of ValueError when packer receives unsupported type.
|
||||
|
||||
Changes
|
||||
-------
|
||||
|
||||
* Support New msgpack spec.
|
||||
|
||||
|
||||
0.3.0
|
||||
=====
|
||||
|
||||
Incompatible Changes
|
||||
--------------------
|
||||
|
||||
* Default value of ``use_list`` is ``True`` for now. (It was ``False`` for 0.2.x)
|
||||
You should pass it explicitly for compatibility to 0.2.x.
|
||||
* `Unpacker.unpack()` and some unpack methods now raise `OutOfData` instead of
|
||||
`StopIteration`. `StopIteration` is used for iterator protocol only.
|
||||
|
||||
Changes
|
||||
-------
|
||||
* Pure Python fallback module is added. (thanks to bwesterb)
|
||||
* Add ``.skip()`` method to ``Unpacker`` (thanks to jnothman)
|
||||
* Add capturing feature. You can pass the writable object to
|
||||
``Unpacker.unpack()`` as a second parameter.
|
||||
* Add ``Packer.pack_array_header`` and ``Packer.pack_map_header``.
|
||||
These methods only pack header of each type.
|
||||
* Add ``autoreset`` option to ``Packer`` (default: True).
|
||||
Packer doesn't return packed bytes and clear internal buffer.
|
||||
* Add ``Packer.pack_map_pairs``. It packs sequence of pair to map type.
|
||||
|
||||
|
||||
|
||||
0.2.4
|
||||
=====
|
||||
:release date: 2012-12-22
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* Fix SEGV when object_hook or object_pairs_hook raise Exception. (#39)
|
||||
|
||||
0.2.3
|
||||
=====
|
||||
:release date: 2012-12-11
|
||||
|
||||
Changes
|
||||
-------
|
||||
* Warn when use_list is not specified. It's default value will be changed in 0.3.
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
* Can't pack subclass of dict.
|
||||
|
||||
0.2.2
|
||||
=====
|
||||
:release date: 2012-09-21
|
||||
|
||||
Changes
|
||||
-------
|
||||
* Add ``use_single_float`` option to ``Packer``. When it is true, packs float
|
||||
object in single precision format.
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
* ``unpack()`` didn't restores gc state when it called with gc disabled.
|
||||
``unpack()`` doesn't control gc now instead of restoring gc state collectly.
|
||||
User can control gc state when gc cause performance issue.
|
||||
|
||||
* ``Unpacker``'s ``read_size`` option didn't used.
|
||||
|
||||
0.2.1
|
||||
=====
|
||||
:release date: 2012-08-20
|
||||
|
||||
Changes
|
||||
-------
|
||||
* Add ``max_buffer_size`` parameter to Unpacker. It limits internal buffer size
|
||||
and allows unpack data from untrusted source safely.
|
||||
|
||||
* Unpacker's buffer reallocation algorithm is less greedy now. It cause performance
|
||||
decrease in rare case but memory efficient and don't allocate than ``max_buffer_size``.
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
* Fix msgpack didn't work on SPARC Solaris. It was because choosing wrong byteorder
|
||||
on compilation time. Use ``sys.byteorder`` to get correct byte order.
|
||||
Very thanks to Chris Casey for giving test environment to me.
|
||||
|
||||
|
||||
0.2.0
|
||||
=====
|
||||
:release date: 2012-06-27
|
||||
|
||||
Changes
|
||||
-------
|
||||
* Drop supporting Python 2.5 and unify tests for Py2 and Py3.
|
||||
* Use new version of msgpack-c. It packs correctly on big endian platforms.
|
||||
* Remove deprecated packs and unpacks API.
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
* #8 Packing subclass of dict raises TypeError. (Thanks to Steeve Morin.)
|
||||
|
||||
|
||||
0.1.13
|
||||
======
|
||||
:release date: 2012-04-21
|
||||
|
||||
New
|
||||
---
|
||||
* Don't accept subtype of list and tuple as msgpack list. (Steeve Morin)
|
||||
It allows customize how it serialized with ``default`` argument.
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
* Fix wrong error message. (David Wolever)
|
||||
* Fix memory leak while unpacking when ``object_hook`` or ``list_hook`` is used.
|
||||
(Steeve Morin)
|
||||
|
||||
Other changes
|
||||
-------------
|
||||
* setup.py works on Python 2.5 (Steffen Siering)
|
||||
* Optimization for serializing dict.
|
||||
|
||||
|
||||
0.1.12
|
||||
======
|
||||
:release date: 2011-12-27
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* Re-enable packs/unpacks removed at 0.1.11. It will be removed when 0.2 is released.
|
||||
|
||||
|
||||
0.1.11
|
||||
======
|
||||
:release date: 2011-12-26
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* Include test code for Python3 to sdist. (Johan Bergström)
|
||||
* Fix compilation error on MSVC. (davidgaleano)
|
||||
|
||||
|
||||
0.1.10
|
||||
======
|
||||
:release date: 2011-08-22
|
||||
|
||||
New feature
|
||||
-----------
|
||||
* Add ``encoding`` and ``unicode_errors`` option to packer and unpacker.
|
||||
When this option is specified, (un)packs unicode object instead of bytes.
|
||||
This enables using msgpack as a replacement of json. (tailhook)
|
||||
|
||||
|
||||
0.1.9
|
||||
=====
|
||||
:release date: 2011-01-29
|
||||
|
||||
New feature
|
||||
-----------
|
||||
* ``use_list`` option is added to unpack(b) like Unpacker.
|
||||
(Use keyword argument because order of parameters are different)
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
* Fix typo.
|
||||
* Add MemoryError check.
|
||||
|
||||
0.1.8
|
||||
=====
|
||||
:release date: 2011-01-10
|
||||
|
||||
New feature
|
||||
-----------
|
||||
* Support ``loads`` and ``dumps`` aliases for API compatibility with
|
||||
simplejson and pickle.
|
||||
|
||||
* Add *object_hook* and *list_hook* option to unpacker. It allows you to
|
||||
hook unpacking mapping type and array type.
|
||||
|
||||
* Add *default* option to packer. It allows you to pack unsupported types.
|
||||
|
||||
* unpacker accepts (old) buffer types.
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
* Fix segv around ``Unpacker.feed`` or ``Unpacker(file)``.
|
||||
|
||||
|
||||
0.1.7
|
||||
=====
|
||||
:release date: 2010-11-02
|
||||
|
||||
New feature
|
||||
-----------
|
||||
* Add *object_hook* and *list_hook* option to unpacker. It allows you to
|
||||
hook unpacking mapping type and array type.
|
||||
|
||||
* Add *default* option to packer. It allows you to pack unsupported types.
|
||||
|
||||
* unpacker accepts (old) buffer types.
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
* Compilation error on win32.
|
||||
17
DEVELOP.md
Normal file
17
DEVELOP.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Developer's note
|
||||
|
||||
### Build
|
||||
|
||||
```
|
||||
$ make cython
|
||||
```
|
||||
|
||||
|
||||
### Test
|
||||
|
||||
MessagePack uses `pytest` for testing.
|
||||
Run test with following command:
|
||||
|
||||
```
|
||||
$ make test
|
||||
```
|
||||
202
LICENSE
202
LICENSE
|
|
@ -1,202 +0,0 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
5
MANIFEST.in
Normal file
5
MANIFEST.in
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
include setup.py
|
||||
include COPYING
|
||||
include README.md
|
||||
recursive-include msgpack *.h *.c *.pyx
|
||||
recursive-include test *.py
|
||||
59
Makefile
Normal file
59
Makefile
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
PYTHON_SOURCES = msgpack test setup.py
|
||||
|
||||
.PHONY: all
|
||||
all: cython
|
||||
python setup.py build_ext -i -f
|
||||
|
||||
.PHONY: format
|
||||
format:
|
||||
ruff format $(PYTHON_SOURCES)
|
||||
|
||||
.PHONY: lint
|
||||
lint:
|
||||
ruff check $(PYTHON_SOURCES)
|
||||
|
||||
.PHONY: doc
|
||||
doc:
|
||||
cd docs && sphinx-build -n -v -W --keep-going -b html -d doctrees . html
|
||||
|
||||
.PHONY: pyupgrade
|
||||
pyupgrade:
|
||||
@find $(PYTHON_SOURCES) -name '*.py' -type f -exec pyupgrade --py37-plus '{}' \;
|
||||
|
||||
.PHONY: cython
|
||||
cython:
|
||||
cython msgpack/_cmsgpack.pyx
|
||||
|
||||
.PHONY: test
|
||||
test: cython
|
||||
pip install -e .
|
||||
pytest -v test
|
||||
MSGPACK_PUREPYTHON=1 pytest -v test
|
||||
|
||||
.PHONY: serve-doc
|
||||
serve-doc: all
|
||||
cd docs && make serve
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf build
|
||||
rm -f msgpack/_cmsgpack.cpp
|
||||
rm -f msgpack/_cmsgpack.*.so
|
||||
rm -f msgpack/_cmsgpack.*.pyd
|
||||
rm -rf msgpack/__pycache__
|
||||
rm -rf test/__pycache__
|
||||
|
||||
.PHONY: update-docker
|
||||
update-docker:
|
||||
docker pull quay.io/pypa/manylinux2014_i686
|
||||
docker pull quay.io/pypa/manylinux2014_x86_64
|
||||
docker pull quay.io/pypa/manylinux2014_aarch64
|
||||
|
||||
.PHONY: linux-wheel
|
||||
linux-wheel:
|
||||
docker run --rm -v `pwd`:/project -w /project quay.io/pypa/manylinux2014_i686 bash docker/buildwheel.sh
|
||||
docker run --rm -v `pwd`:/project -w /project quay.io/pypa/manylinux2014_x86_64 bash docker/buildwheel.sh
|
||||
|
||||
.PHONY: linux-arm64-wheel
|
||||
linux-arm64-wheel:
|
||||
docker run --rm -v `pwd`:/project -w /project quay.io/pypa/manylinux2014_aarch64 bash docker/buildwheel.sh
|
||||
13
Makefile.am
13
Makefile.am
|
|
@ -1,13 +0,0 @@
|
|||
if ENABLE_CXX
|
||||
SUBDIRS = c cpp
|
||||
else
|
||||
SUBDIRS = c
|
||||
endif
|
||||
|
||||
nobase_include_HEADERS = \
|
||||
msgpack/pack_define.h \
|
||||
msgpack/pack_template.h \
|
||||
msgpack/unpack_define.h \
|
||||
msgpack/unpack_template.h \
|
||||
msgpack/sysdep.h
|
||||
|
||||
0
NEWS
0
NEWS
4
NOTICE
4
NOTICE
|
|
@ -1,4 +0,0 @@
|
|||
MessagePack is developed by FURUHASHI Sadayuki, licensed under Apache License,
|
||||
Version 2.0. The original software and related information is available at
|
||||
http://msgpack.sourceforge.jp/.
|
||||
|
||||
70
README
70
README
|
|
@ -1,70 +0,0 @@
|
|||
MessagePack
|
||||
-----------
|
||||
Binary-based efficient data interchange format.
|
||||
|
||||
|
||||
*Requirements
|
||||
|
||||
MessagePack is only tested on Linux and Mac OS X, but it may run on other
|
||||
UNIX-like platforms.
|
||||
|
||||
gcc >= 4.1 is required to build.
|
||||
|
||||
|
||||
*Installation
|
||||
|
||||
Simply run ./configure && make && make install to install C and C++ binding.
|
||||
|
||||
$ ./configure
|
||||
$ make
|
||||
$ sudo make install
|
||||
|
||||
To install Ruby binding, run ./gengem.sh script on ruby/ directory and install
|
||||
generated gem package.
|
||||
|
||||
$ cd ruby
|
||||
$ ./gengem.sh
|
||||
$ gem install gem/pkg/msgpack-*.gem
|
||||
|
||||
|
||||
*Usage
|
||||
|
||||
C++:
|
||||
include msgpack.hpp header and link libmsgpack library.
|
||||
see example/simple.cc for example.
|
||||
|
||||
g++ simple.cc -lmsgpack
|
||||
g++ stream.cc -lmsgpack -lpthread
|
||||
|
||||
|
||||
C:
|
||||
include msgpack.h header and link libmsgpackc library.
|
||||
see example/simple.c for example.
|
||||
|
||||
gcc simple.c -lmsgpackc
|
||||
|
||||
|
||||
Ruby:
|
||||
require msgpack library.
|
||||
see example/simple.rb for example.
|
||||
|
||||
ruby -rubygems simple.rb
|
||||
|
||||
|
||||
API Document is available at http://msgpack.sourceforge.jp/.
|
||||
|
||||
|
||||
Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
242
README.md
Normal file
242
README.md
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
# MessagePack for Python
|
||||
|
||||
[](https://github.com/msgpack/msgpack-python/actions/workflows/wheel.yml)
|
||||
[](https://msgpack-python.readthedocs.io/en/latest/?badge=latest)
|
||||
|
||||
## What is this?
|
||||
|
||||
[MessagePack](https://msgpack.org/) is an efficient binary serialization format.
|
||||
It lets you exchange data among multiple languages like JSON.
|
||||
But it's faster and smaller.
|
||||
This package provides CPython bindings for reading and writing MessagePack data.
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ pip install msgpack
|
||||
```
|
||||
|
||||
### Pure Python implementation
|
||||
|
||||
The extension module in msgpack (`msgpack._cmsgpack`) does not support PyPy.
|
||||
|
||||
But msgpack provides a pure Python implementation (`msgpack.fallback`) for PyPy.
|
||||
|
||||
|
||||
### Windows
|
||||
|
||||
If you can't use a binary distribution, you need to install Visual Studio
|
||||
or the Windows SDK on Windows.
|
||||
Without the extension, the pure Python implementation on CPython runs slowly.
|
||||
|
||||
|
||||
## How to use
|
||||
|
||||
### One-shot pack & unpack
|
||||
|
||||
Use `packb` for packing and `unpackb` for unpacking.
|
||||
msgpack provides `dumps` and `loads` as aliases for compatibility with
|
||||
`json` and `pickle`.
|
||||
|
||||
`pack` and `dump` pack to a file-like object.
|
||||
`unpack` and `load` unpack from a file-like object.
|
||||
|
||||
```pycon
|
||||
>>> import msgpack
|
||||
>>> msgpack.packb([1, 2, 3])
|
||||
'\x93\x01\x02\x03'
|
||||
>>> msgpack.unpackb(_)
|
||||
[1, 2, 3]
|
||||
```
|
||||
|
||||
Read the docstring for options.
|
||||
|
||||
|
||||
### Streaming unpacking
|
||||
|
||||
`Unpacker` is a "streaming unpacker". It unpacks multiple objects from one
|
||||
stream (or from bytes provided through its `feed` method).
|
||||
|
||||
```py
|
||||
import msgpack
|
||||
from io import BytesIO
|
||||
|
||||
buf = BytesIO()
|
||||
for i in range(100):
|
||||
buf.write(msgpack.packb(i))
|
||||
|
||||
buf.seek(0)
|
||||
|
||||
unpacker = msgpack.Unpacker(buf)
|
||||
for unpacked in unpacker:
|
||||
print(unpacked)
|
||||
```
|
||||
|
||||
|
||||
### Packing/unpacking of custom data types
|
||||
|
||||
It is also possible to pack/unpack custom data types. Here is an example for
|
||||
`datetime.datetime`.
|
||||
|
||||
```py
|
||||
import datetime
|
||||
import msgpack
|
||||
|
||||
useful_dict = {
|
||||
"id": 1,
|
||||
"created": datetime.datetime.now(),
|
||||
}
|
||||
|
||||
def decode_datetime(obj):
|
||||
if '__datetime__' in obj:
|
||||
obj = datetime.datetime.strptime(obj["as_str"], "%Y%m%dT%H:%M:%S.%f")
|
||||
return obj
|
||||
|
||||
def encode_datetime(obj):
|
||||
if isinstance(obj, datetime.datetime):
|
||||
return {'__datetime__': True, 'as_str': obj.strftime("%Y%m%dT%H:%M:%S.%f")}
|
||||
return obj
|
||||
|
||||
|
||||
packed_dict = msgpack.packb(useful_dict, default=encode_datetime)
|
||||
this_dict_again = msgpack.unpackb(packed_dict, object_hook=decode_datetime)
|
||||
```
|
||||
|
||||
`Unpacker`'s `object_hook` callback receives a dict; the
|
||||
`object_pairs_hook` callback may instead be used to receive a list of
|
||||
key-value pairs.
|
||||
|
||||
NOTE: msgpack can encode datetime with tzinfo into standard ext type for now.
|
||||
See `datetime` option in `Packer` docstring.
|
||||
|
||||
|
||||
### Extended types
|
||||
|
||||
It is also possible to pack/unpack custom data types using the **ext** type.
|
||||
|
||||
```pycon
|
||||
>>> import msgpack
|
||||
>>> import array
|
||||
>>> def default(obj):
|
||||
... if isinstance(obj, array.array) and obj.typecode == 'd':
|
||||
... return msgpack.ExtType(42, obj.tostring())
|
||||
... raise TypeError("Unknown type: %r" % (obj,))
|
||||
...
|
||||
>>> def ext_hook(code, data):
|
||||
... if code == 42:
|
||||
... a = array.array('d')
|
||||
... a.fromstring(data)
|
||||
... return a
|
||||
... return ExtType(code, data)
|
||||
...
|
||||
>>> data = array.array('d', [1.2, 3.4])
|
||||
>>> packed = msgpack.packb(data, default=default)
|
||||
>>> unpacked = msgpack.unpackb(packed, ext_hook=ext_hook)
|
||||
>>> data == unpacked
|
||||
True
|
||||
```
|
||||
|
||||
|
||||
### Advanced unpacking control
|
||||
|
||||
As an alternative to iteration, `Unpacker` objects provide `unpack`,
|
||||
`skip`, `read_array_header`, and `read_map_header` methods. The former two
|
||||
read an entire message from the stream, respectively deserializing and returning
|
||||
the result, or ignoring it. The latter two methods return the number of elements
|
||||
in the upcoming container, so that each element in an array, or key-value pair
|
||||
in a map, can be unpacked or skipped individually.
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
### String and binary types in the old MessagePack spec
|
||||
|
||||
Early versions of msgpack didn't distinguish string and binary types.
|
||||
The type for representing both string and binary types was named **raw**.
|
||||
|
||||
You can pack into and unpack from this old spec using `use_bin_type=False`
|
||||
and `raw=True` options.
|
||||
|
||||
```pycon
|
||||
>>> import msgpack
|
||||
>>> msgpack.unpackb(msgpack.packb([b'spam', 'eggs'], use_bin_type=False), raw=True)
|
||||
[b'spam', b'eggs']
|
||||
>>> msgpack.unpackb(msgpack.packb([b'spam', 'eggs'], use_bin_type=True), raw=False)
|
||||
[b'spam', 'eggs']
|
||||
```
|
||||
|
||||
### ext type
|
||||
|
||||
To use the **ext** type, pass a `msgpack.ExtType` object to the packer.
|
||||
|
||||
```pycon
|
||||
>>> import msgpack
|
||||
>>> packed = msgpack.packb(msgpack.ExtType(42, b'xyzzy'))
|
||||
>>> msgpack.unpackb(packed)
|
||||
ExtType(code=42, data='xyzzy')
|
||||
```
|
||||
|
||||
You can use it with `default` and `ext_hook`. See below.
|
||||
|
||||
|
||||
### Security
|
||||
|
||||
When unpacking data received from an unreliable source, msgpack provides
|
||||
two security options.
|
||||
|
||||
`max_buffer_size` (default: `100*1024*1024`) limits the internal buffer size.
|
||||
It is also used to limit preallocated list sizes.
|
||||
|
||||
`strict_map_key` (default: `True`) limits the type of map keys to bytes and str.
|
||||
While the MessagePack spec doesn't limit map key types,
|
||||
there is a risk of a hash DoS.
|
||||
If you need to support other types for map keys, use `strict_map_key=False`.
|
||||
|
||||
|
||||
### Performance tips
|
||||
|
||||
CPython's GC starts when the number of allocated objects grows.
|
||||
This means unpacking may trigger unnecessary GC.
|
||||
You can use `gc.disable()` when unpacking a large message.
|
||||
|
||||
A list is the default sequence type in Python.
|
||||
However, a tuple is lighter than a list.
|
||||
You can use `use_list=False` while unpacking when performance is important.
|
||||
|
||||
|
||||
## Major breaking changes in the history
|
||||
|
||||
### msgpack 0.5
|
||||
|
||||
The package name on PyPI was changed from `msgpack-python` to `msgpack` in 0.5.
|
||||
|
||||
When upgrading from msgpack-0.4 or earlier, do `pip uninstall msgpack-python` before
|
||||
`pip install -U msgpack`.
|
||||
|
||||
|
||||
### msgpack 1.0
|
||||
|
||||
* Python 2 support
|
||||
|
||||
* The extension module no longer supports Python 2.
|
||||
The pure Python implementation (`msgpack.fallback`) is used for Python 2.
|
||||
|
||||
* msgpack 1.0.6 drops official support of Python 2.7, as pip and
|
||||
GitHub Action "setup-python" no longer supports Python 2.7.
|
||||
|
||||
* Packer
|
||||
|
||||
* Packer uses `use_bin_type=True` by default.
|
||||
Bytes are encoded in the bin type in MessagePack.
|
||||
* The `encoding` option is removed. UTF-8 is always used.
|
||||
|
||||
* Unpacker
|
||||
|
||||
* Unpacker uses `raw=False` by default. It assumes str values are valid UTF-8 strings
|
||||
and decodes them to Python str (Unicode) objects.
|
||||
* `encoding` option is removed. You can use `raw=True` to support old format (e.g. unpack into bytes, not str).
|
||||
* The default value of `max_buffer_size` is changed from 0 to 100 MiB to avoid DoS attacks.
|
||||
You need to pass `max_buffer_size=0` if you have large but safe data.
|
||||
* The default value of `strict_map_key` is changed to True to avoid hash DoS.
|
||||
You need to pass `strict_map_key=False` if you have data that contain map keys
|
||||
whose type is neither bytes nor str.
|
||||
5
SECURITY.md
Normal file
5
SECURITY.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
## Security contact information
|
||||
|
||||
To report a security vulnerability, please use the
|
||||
[Tidelift security contact](https://tidelift.com/security).
|
||||
Tidelift will coordinate the fix and disclosure.
|
||||
38
benchmark/benchmark.py
Normal file
38
benchmark/benchmark.py
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
from msgpack import fallback
|
||||
|
||||
try:
|
||||
from msgpack import _cmsgpack
|
||||
|
||||
has_ext = True
|
||||
except ImportError:
|
||||
has_ext = False
|
||||
import timeit
|
||||
|
||||
|
||||
def profile(name, func):
|
||||
times = timeit.repeat(func, number=1000, repeat=4)
|
||||
times = ", ".join(["%8f" % t for t in times])
|
||||
print("%-30s %40s" % (name, times))
|
||||
|
||||
|
||||
def simple(name, data):
|
||||
if has_ext:
|
||||
packer = _cmsgpack.Packer()
|
||||
profile("packing %s (ext)" % name, lambda: packer.pack(data))
|
||||
packer = fallback.Packer()
|
||||
profile("packing %s (fallback)" % name, lambda: packer.pack(data))
|
||||
|
||||
data = packer.pack(data)
|
||||
if has_ext:
|
||||
profile("unpacking %s (ext)" % name, lambda: _cmsgpack.unpackb(data))
|
||||
profile("unpacking %s (fallback)" % name, lambda: fallback.unpackb(data))
|
||||
|
||||
|
||||
def main():
|
||||
simple("integers", [7] * 10000)
|
||||
simple("bytes", [b"x" * n for n in range(100)] * 10)
|
||||
simple("lists", [[]] * 10000)
|
||||
simple("dicts", [{}] * 10000)
|
||||
|
||||
|
||||
main()
|
||||
117
bootstrap
117
bootstrap
|
|
@ -1,117 +0,0 @@
|
|||
#!/bin/sh
|
||||
# vim:ts=4:sw=4
|
||||
# Calls autotools to build configure script and Makefile.in.
|
||||
# Generated automatically using bootstrapper 0.2.1
|
||||
# http://bootstrapper.sourceforge.net/
|
||||
#
|
||||
# Copyright (C) 2002 Anthony Ventimiglia
|
||||
#
|
||||
# This bootstrap script is free software; you can redistribute
|
||||
# it and/or modify it under the terms of the GNU General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 of the License, or (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Calls proper programs to create configure script and Makefile.in files.
|
||||
# if run with the --clean option, bootstrap removes files it generates. To
|
||||
# clean all autogenerated files (eg: for cvs imports) first run
|
||||
# make distclean, then bootstrap --clean
|
||||
# see bootstrapper(1) for more infor
|
||||
|
||||
|
||||
if test x"$1" = x"--help"; then
|
||||
echo "$0: automatic bootstrapping utility for GNU Autotools"
|
||||
echo " cleans up old autogenerated files and runs autoconf,"
|
||||
echo " automake and aclocal on local directory"
|
||||
echo
|
||||
echo " --clean clean up auto-generated files without"
|
||||
echo " creating new scripts"
|
||||
echo
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
mkdir -p ac
|
||||
(cd cpp && ./preprocess.sh $@; cd ..)
|
||||
|
||||
|
||||
ACLOCAL="aclocal"
|
||||
ACLOCAL_FILES="aclocal.m4"
|
||||
ALWAYS_CLEAN="config.status config.log config.cache libtool"
|
||||
AUTOCONF="autoconf"
|
||||
AUTOCONF_FILES="configure"
|
||||
AUTOHEADER="autoheader"
|
||||
AUTOHEADER_FILES=""
|
||||
AUTOMAKE="automake --add-missing --copy"
|
||||
AUTOMAKE_FILES="config.sub stamp-h.in ltmain.sh missing mkinstalldirs install-sh config.guess"
|
||||
CONFIG_AUX_DIR="."
|
||||
CONFIG_FILES="stamp-h ltconfig"
|
||||
CONFIG_HEADER=""
|
||||
if [ x`uname` = x"Darwin" ]; then
|
||||
LIBTOOLIZE="glibtoolize --force --copy"
|
||||
else
|
||||
LIBTOOLIZE="libtoolize --force --copy"
|
||||
fi
|
||||
LIBTOOLIZE_FILES="config.sub ltmain.sh config.guess"
|
||||
RM="rm"
|
||||
SUBDIRS="[]"
|
||||
|
||||
|
||||
# These are files created by configure, so we'll always clean them
|
||||
for i in $ALWAYS_CLEAN; do
|
||||
test -f $i && \
|
||||
$RM $i
|
||||
done
|
||||
|
||||
if test x"$1" = x"--clean"; then
|
||||
#
|
||||
#Clean Files left by previous bootstrap run
|
||||
#
|
||||
if test -n "$CONFIG_AUX_DIR";
|
||||
then CONFIG_AUX_DIR="$CONFIG_AUX_DIR/"
|
||||
fi
|
||||
# Clean Libtoolize generated files
|
||||
for cf in $LIBTOOLIZE_FILES; do
|
||||
cf="$CONFIG_AUX_DIR$cf"
|
||||
test -f $cf && \
|
||||
$RM $cf
|
||||
done
|
||||
#aclocal.m4 created by aclocal
|
||||
test -f $ACLOCAL_FILES && $RM $ACLOCAL_FILES
|
||||
#Clean Autoheader Generated files
|
||||
for cf in $AUTOHEADER_FILES; do
|
||||
cf=$CONFIG_AUX_DIR$cf
|
||||
test -f $cf && \
|
||||
$RM $cf
|
||||
done
|
||||
# remove config header (Usaually config.h)
|
||||
test -n "$CONFIG_HEADER" && test -f $CONFIG_HEADER && $RM $CONFIG_HEADER
|
||||
#Clean Automake generated files
|
||||
for cf in $AUTOMAKE_FILES; do
|
||||
cf=$CONFIG_AUX_DIR$cf
|
||||
test -f $cf && \
|
||||
$RM $cf
|
||||
done
|
||||
for i in $SUBDIRS; do
|
||||
test -f $i/Makefile.in && \
|
||||
$RM $i/Makefile.in
|
||||
done
|
||||
#Autoconf generated files
|
||||
for cf in $AUTOCONF_FILES; do
|
||||
test -f $cf && \
|
||||
$RM $cf
|
||||
done
|
||||
for cf in $CONFIG_FILES; do
|
||||
cf="$CONFIG_AUX_DIR$cf"
|
||||
test -f $cf && \
|
||||
$RM $cf
|
||||
done
|
||||
else
|
||||
$LIBTOOLIZE
|
||||
$ACLOCAL
|
||||
$AUTOHEADER
|
||||
$AUTOMAKE
|
||||
$AUTOCONF
|
||||
fi
|
||||
|
||||
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
lib_LTLIBRARIES = libmsgpackc.la
|
||||
|
||||
libmsgpackc_la_SOURCES = \
|
||||
unpack.c \
|
||||
object.c \
|
||||
vrefbuffer.c \
|
||||
zone.c
|
||||
|
||||
nobase_include_HEADERS = \
|
||||
msgpack.h \
|
||||
msgpack/sbuffer.h \
|
||||
msgpack/vrefbuffer.h \
|
||||
msgpack/pack.h \
|
||||
msgpack/unpack.h \
|
||||
msgpack/object.h \
|
||||
msgpack/zone.h
|
||||
|
||||
# -version-info CURRENT:REVISION:AGE
|
||||
libmsgpackc_la_LDFLAGS = -version-info 1:0:0
|
||||
|
||||
check_PROGRAMS = \
|
||||
msgpackc_test
|
||||
|
||||
msgpackc_test_SOURCES = test.cpp
|
||||
msgpackc_test_CXXFLAGS = -I$(top_srcdir) -I$(top_srcdir)/c
|
||||
msgpackc_test_LDFLAGS = libmsgpackc.la -lgtest_main
|
||||
|
||||
TESTS = $(check_PROGRAMS)
|
||||
323
c/bench.c
323
c/bench.c
|
|
@ -1,323 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <msgpack/pack.h>
|
||||
#include <msgpack/unpack.h>
|
||||
#include <yajl/yajl_parse.h>
|
||||
#include <yajl/yajl_gen.h>
|
||||
|
||||
|
||||
static struct timeval g_timer;
|
||||
|
||||
void reset_timer()
|
||||
{
|
||||
gettimeofday(&g_timer, NULL);
|
||||
}
|
||||
|
||||
void show_timer(size_t bufsz)
|
||||
{
|
||||
struct timeval endtime;
|
||||
gettimeofday(&endtime, NULL);
|
||||
double sec = (endtime.tv_sec - g_timer.tv_sec)
|
||||
+ (double)(endtime.tv_usec - g_timer.tv_usec) / 1000 / 1000;
|
||||
printf("%f sec\n", sec);
|
||||
printf("%f MB\n", ((double)bufsz)/1024/1024);
|
||||
printf("%f Mbps\n", ((double)bufsz)*8/sec/1000/1000);
|
||||
}
|
||||
|
||||
|
||||
static int reformat_null(void * ctx) { return 1; }
|
||||
static int reformat_boolean(void * ctx, int boolean) { return 1; }
|
||||
static int reformat_number(void * ctx, const char * s, unsigned int l) { return 1; }
|
||||
static int reformat_string(void * ctx, const unsigned char * stringVal, unsigned int stringLen) { return 1; }
|
||||
static int reformat_map_key(void * ctx, const unsigned char * stringVal, unsigned int stringLen) { return 1; }
|
||||
static int reformat_start_map(void * ctx) { return 1; }
|
||||
static int reformat_end_map(void * ctx) { return 1; }
|
||||
static int reformat_start_array(void * ctx) { return 1; }
|
||||
static int reformat_end_array(void * ctx) { return 1; }
|
||||
|
||||
|
||||
static void* unpack_uint8(void* data, uint8_t d) { return NULL; }
|
||||
static void* unpack_uint16(void* data, uint16_t d) { return NULL; }
|
||||
static void* unpack_uint32(void* data, uint32_t d) { return NULL; }
|
||||
static void* unpack_uint64(void* data, uint64_t d) { return NULL; }
|
||||
static void* unpack_int8(void* data, int8_t d) { return NULL; }
|
||||
static void* unpack_int16(void* data, int16_t d) { return NULL; }
|
||||
static void* unpack_int32(void* data, int32_t d) { return NULL; }
|
||||
static void* unpack_int64(void* data, int64_t d) { return NULL; }
|
||||
static void* unpack_float(void* data, float d) { return NULL; }
|
||||
static void* unpack_double(void* data, double d) { return NULL; }
|
||||
static void* unpack_nil(void* data) { return NULL; }
|
||||
static void* unpack_true(void* data) { return NULL; }
|
||||
static void* unpack_false(void* data) { return NULL; }
|
||||
static void* unpack_array(void* data, unsigned int n) { return NULL; }
|
||||
static void unpack_array_item(void* data, void* c, void* o) { }
|
||||
static void* unpack_map(void* data, unsigned int n) { return NULL; }
|
||||
static void unpack_map_item(void* data, void* c, void* k, void* v) { }
|
||||
static void* unpack_raw(void* data, const char* b, const char* p, unsigned int l) { /*printf("unpack raw %p %lu\n",p,l);*/ return NULL; }
|
||||
|
||||
|
||||
typedef struct {
|
||||
size_t allocated;
|
||||
size_t length;
|
||||
char* buffer;
|
||||
} pack_buffer;
|
||||
|
||||
static const size_t PACK_INITIAL_BUFFER_SIZE = 32*1024;
|
||||
|
||||
static void pack_buffer_init(pack_buffer* data)
|
||||
{
|
||||
data->buffer = malloc(PACK_INITIAL_BUFFER_SIZE);
|
||||
data->length = 0;
|
||||
data->allocated = PACK_INITIAL_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
static void pack_buffer_reset(pack_buffer* data)
|
||||
{
|
||||
data->buffer = realloc(data->buffer, PACK_INITIAL_BUFFER_SIZE);
|
||||
data->allocated = PACK_INITIAL_BUFFER_SIZE;
|
||||
data->length = 0;
|
||||
}
|
||||
|
||||
static void pack_buffer_free(pack_buffer* data)
|
||||
{
|
||||
free(data->buffer);
|
||||
}
|
||||
|
||||
static void pack_append_buffer(void* user, const char* b, unsigned int l)
|
||||
{
|
||||
pack_buffer* data = (pack_buffer*)user;
|
||||
if(data->allocated - data->length < l) {
|
||||
data->buffer = realloc(data->buffer, data->allocated*2);
|
||||
data->allocated *= 2;
|
||||
}
|
||||
memcpy(data->buffer + data->length, b, l);
|
||||
data->length += l;
|
||||
}
|
||||
|
||||
|
||||
static const unsigned int TASK_INT_NUM = 1<<24;
|
||||
static const unsigned int TASK_STR_LEN = 1<<15;
|
||||
//static const unsigned int TASK_INT_NUM = 1<<20;
|
||||
//static const unsigned int TASK_STR_LEN = 1<<12;
|
||||
static const char* TASK_STR_PTR;
|
||||
|
||||
|
||||
void bench_json(void)
|
||||
{
|
||||
puts("== JSON ==");
|
||||
|
||||
|
||||
yajl_gen_config gcfg = {0, NULL};
|
||||
yajl_gen g = yajl_gen_alloc(&gcfg);
|
||||
|
||||
yajl_parser_config hcfg = { 0, 0 };
|
||||
yajl_callbacks callbacks = {
|
||||
reformat_null,
|
||||
reformat_boolean,
|
||||
NULL,
|
||||
NULL,
|
||||
reformat_number,
|
||||
reformat_string,
|
||||
reformat_start_map,
|
||||
reformat_map_key,
|
||||
reformat_end_map,
|
||||
reformat_start_array,
|
||||
reformat_end_array
|
||||
};
|
||||
yajl_handle h = yajl_alloc(&callbacks, &hcfg, NULL);
|
||||
|
||||
|
||||
const unsigned char * buf;
|
||||
unsigned int len;
|
||||
|
||||
|
||||
puts("generate integer");
|
||||
reset_timer();
|
||||
{
|
||||
unsigned int i;
|
||||
yajl_gen_array_open(g);
|
||||
for(i=0; i < TASK_INT_NUM; ++i) {
|
||||
yajl_gen_integer(g, i);
|
||||
}
|
||||
yajl_gen_array_close(g);
|
||||
}
|
||||
show_timer(len);
|
||||
|
||||
yajl_gen_get_buf(g, &buf, &len);
|
||||
|
||||
puts("----");
|
||||
puts("parse integer");
|
||||
reset_timer();
|
||||
{
|
||||
yajl_status stat = yajl_parse(h, buf, len);
|
||||
if (stat != yajl_status_ok && stat != yajl_status_insufficient_data) {
|
||||
unsigned char * str = yajl_get_error(h, 1, buf, len);
|
||||
fprintf(stderr, (const char *) str);
|
||||
}
|
||||
}
|
||||
show_timer(len);
|
||||
|
||||
|
||||
//yajl_gen_clear(g);
|
||||
yajl_gen_free(g);
|
||||
g = yajl_gen_alloc(&gcfg);
|
||||
yajl_free(h);
|
||||
h = yajl_alloc(&callbacks, &hcfg, NULL);
|
||||
|
||||
|
||||
puts("----");
|
||||
puts("generate string");
|
||||
reset_timer();
|
||||
{
|
||||
unsigned int i;
|
||||
yajl_gen_array_open(g);
|
||||
for(i=0; i < TASK_STR_LEN; ++i) {
|
||||
yajl_gen_string(g, (const unsigned char*)TASK_STR_PTR, i);
|
||||
}
|
||||
yajl_gen_array_close(g);
|
||||
}
|
||||
show_timer(len);
|
||||
|
||||
yajl_gen_get_buf(g, &buf, &len);
|
||||
|
||||
puts("----");
|
||||
puts("parse string");
|
||||
reset_timer();
|
||||
{
|
||||
yajl_status stat = yajl_parse(h, buf, len);
|
||||
if (stat != yajl_status_ok && stat != yajl_status_insufficient_data) {
|
||||
unsigned char * str = yajl_get_error(h, 1, buf, len);
|
||||
fprintf(stderr, (const char *) str);
|
||||
}
|
||||
}
|
||||
show_timer(len);
|
||||
|
||||
|
||||
yajl_gen_free(g);
|
||||
yajl_free(h);
|
||||
}
|
||||
|
||||
|
||||
void bench_msgpack(void)
|
||||
{
|
||||
puts("== MessagePack ==");
|
||||
|
||||
|
||||
pack_buffer mpkbuf;
|
||||
pack_buffer_init(&mpkbuf);
|
||||
|
||||
msgpack_pack_t* mpk = msgpack_pack_new(
|
||||
&mpkbuf, pack_append_buffer);
|
||||
|
||||
msgpack_unpack_callback cb = {
|
||||
unpack_uint8,
|
||||
unpack_uint16,
|
||||
unpack_uint32,
|
||||
unpack_uint64,
|
||||
unpack_int8,
|
||||
unpack_int16,
|
||||
unpack_int32,
|
||||
unpack_int64,
|
||||
unpack_float,
|
||||
unpack_double,
|
||||
unpack_nil,
|
||||
unpack_true,
|
||||
unpack_false,
|
||||
unpack_array,
|
||||
unpack_array_item,
|
||||
unpack_map,
|
||||
unpack_map_item,
|
||||
unpack_raw,
|
||||
};
|
||||
msgpack_unpack_t* mupk = msgpack_unpack_new(NULL, &cb);
|
||||
|
||||
|
||||
size_t len;
|
||||
const char* buf;
|
||||
|
||||
|
||||
puts("pack integer");
|
||||
reset_timer();
|
||||
{
|
||||
unsigned int i;
|
||||
msgpack_pack_array(mpk, TASK_INT_NUM);
|
||||
for(i=0; i < TASK_INT_NUM; ++i) {
|
||||
msgpack_pack_unsigned_int(mpk, i);
|
||||
}
|
||||
}
|
||||
show_timer(mpkbuf.length);
|
||||
|
||||
len = mpkbuf.length;
|
||||
buf = mpkbuf.buffer;
|
||||
|
||||
puts("----");
|
||||
puts("unpack integer");
|
||||
reset_timer();
|
||||
{
|
||||
size_t off = 0;
|
||||
int ret = msgpack_unpack_execute(mupk, buf, len, &off);
|
||||
if(ret < 0) {
|
||||
fprintf(stderr, "Parse error.\n");
|
||||
} else if(ret == 0) {
|
||||
fprintf(stderr, "Not finished.\n");
|
||||
}
|
||||
}
|
||||
show_timer(mpkbuf.length);
|
||||
|
||||
|
||||
pack_buffer_reset(&mpkbuf);
|
||||
msgpack_unpack_reset(mupk);
|
||||
|
||||
|
||||
puts("----");
|
||||
puts("pack string");
|
||||
reset_timer();
|
||||
{
|
||||
unsigned int i;
|
||||
msgpack_pack_array(mpk, TASK_STR_LEN);
|
||||
for(i=0; i < TASK_STR_LEN; ++i) {
|
||||
msgpack_pack_raw(mpk, i);
|
||||
msgpack_pack_raw_body(mpk, TASK_STR_PTR, i);
|
||||
}
|
||||
}
|
||||
show_timer(mpkbuf.length);
|
||||
|
||||
len = mpkbuf.length;
|
||||
buf = mpkbuf.buffer;
|
||||
|
||||
puts("----");
|
||||
puts("unpack string");
|
||||
reset_timer();
|
||||
{
|
||||
size_t off = 0;
|
||||
int ret = msgpack_unpack_execute(mupk, buf, len, &off);
|
||||
if(ret < 0) {
|
||||
fprintf(stderr, "Parse error.\n");
|
||||
} else if(ret == 0) {
|
||||
fprintf(stderr, "Not finished.\n");
|
||||
}
|
||||
}
|
||||
show_timer(mpkbuf.length);
|
||||
|
||||
|
||||
msgpack_unpack_free(mupk);
|
||||
msgpack_pack_free(mpk);
|
||||
pack_buffer_free(&mpkbuf);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
char* str = malloc(TASK_STR_LEN);
|
||||
memset(str, 'a', TASK_STR_LEN);
|
||||
TASK_STR_PTR = str;
|
||||
|
||||
bench_msgpack();
|
||||
bench_json();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
|
||||
CFLAGS += -Wall -g -I. -I.. -O4
|
||||
LDFLAGS += -lyajl
|
||||
|
||||
all: bench
|
||||
|
||||
bench: bench.o pack.o unpack.o pack.h unpack.h
|
||||
$(CC) bench.o pack.o unpack.o $(CFLAGS) $(LDFLAGS) -o $@
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
.
|
||||
23
c/msgpack.h
23
c/msgpack.h
|
|
@ -1,23 +0,0 @@
|
|||
/*
|
||||
* MessagePack for C
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "msgpack/object.h"
|
||||
#include "msgpack/zone.h"
|
||||
#include "msgpack/pack.h"
|
||||
#include "msgpack/unpack.h"
|
||||
#include "msgpack/sbuffer.h"
|
||||
#include "msgpack/vrefbuffer.h"
|
||||
171
c/object.c
171
c/object.c
|
|
@ -1,171 +0,0 @@
|
|||
/*
|
||||
* MessagePack for C dynamic typing routine
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "msgpack/object.h"
|
||||
#include "msgpack/pack.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <inttypes.h>
|
||||
#else
|
||||
#ifndef PRIu64
|
||||
#define PRIu64 "I64u"
|
||||
#endif
|
||||
#ifndef PRIi64
|
||||
#define PRIi64 "I64d"
|
||||
#endif
|
||||
#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_DOUBLE:
|
||||
return msgpack_pack_double(pk, d.via.dec);
|
||||
|
||||
case MSGPACK_OBJECT_RAW:
|
||||
{
|
||||
int ret = msgpack_pack_raw(pk, d.via.raw.size);
|
||||
if(ret < 0) { return ret; }
|
||||
return msgpack_pack_raw_body(pk, d.via.raw.ptr, d.via.raw.size);
|
||||
}
|
||||
|
||||
case MSGPACK_OBJECT_ARRAY:
|
||||
{
|
||||
int ret = msgpack_pack_array(pk, d.via.array.size);
|
||||
if(ret < 0) { return ret; }
|
||||
|
||||
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; }
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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:
|
||||
fprintf(out, "%"PRIu64, o.via.u64);
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_NEGATIVE_INTEGER:
|
||||
fprintf(out, "%"PRIi64, o.via.i64);
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_DOUBLE:
|
||||
fprintf(out, "%f", o.via.dec);
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_RAW:
|
||||
fprintf(out, "\"");
|
||||
fwrite(o.via.raw.ptr, o.via.raw.size, 1, out);
|
||||
fprintf(out, "\"");
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_ARRAY:
|
||||
fprintf(out, "[");
|
||||
if(o.via.array.size != 0) {
|
||||
msgpack_object* p = o.via.array.ptr;
|
||||
msgpack_object_print(out, *p);
|
||||
++p;
|
||||
msgpack_object* const pend = o.via.array.ptr + o.via.array.size;
|
||||
for(; p < pend; ++p) {
|
||||
fprintf(out, ", ");
|
||||
msgpack_object_print(out, *p);
|
||||
}
|
||||
}
|
||||
fprintf(out, "]");
|
||||
break;
|
||||
// FIXME loop optimiziation
|
||||
|
||||
case MSGPACK_OBJECT_MAP:
|
||||
fprintf(out, "{");
|
||||
if(o.via.map.size != 0) {
|
||||
msgpack_object_kv* p = o.via.map.ptr;
|
||||
msgpack_object_print(out, p->key);
|
||||
fprintf(out, "=>");
|
||||
msgpack_object_print(out, p->val);
|
||||
++p;
|
||||
msgpack_object_kv* const pend = o.via.map.ptr + o.via.map.size;
|
||||
for(; p < pend; ++p) {
|
||||
fprintf(out, ", ");
|
||||
msgpack_object_print(out, p->key);
|
||||
fprintf(out, "=>");
|
||||
msgpack_object_print(out, p->val);
|
||||
}
|
||||
}
|
||||
fprintf(out, "}");
|
||||
break;
|
||||
// FIXME loop optimiziation
|
||||
|
||||
default:
|
||||
// FIXME
|
||||
fprintf(out, "#<UNKNOWN %hu %"PRIu64">", o.type, o.via.u64);
|
||||
}
|
||||
}
|
||||
|
||||
89
c/object.h
89
c/object.h
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* MessagePack for C dynamic typing routine
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef MSGPACK_OBJECT_H__
|
||||
#define MSGPACK_OBJECT_H__
|
||||
|
||||
#include "msgpack/zone.h"
|
||||
#include "msgpack/sysdep.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef enum {
|
||||
MSGPACK_OBJECT_NIL = 0x01,
|
||||
MSGPACK_OBJECT_BOOLEAN = 0x02,
|
||||
MSGPACK_OBJECT_POSITIVE_INTEGER = 0x03,
|
||||
MSGPACK_OBJECT_NEGATIVE_INTEGER = 0x04,
|
||||
MSGPACK_OBJECT_DOUBLE = 0x05,
|
||||
MSGPACK_OBJECT_RAW = 0x06,
|
||||
MSGPACK_OBJECT_ARRAY = 0x07,
|
||||
MSGPACK_OBJECT_MAP = 0x08,
|
||||
} 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_raw;
|
||||
|
||||
typedef union {
|
||||
bool boolean;
|
||||
uint64_t u64;
|
||||
int64_t i64;
|
||||
double dec;
|
||||
msgpack_object_array array;
|
||||
msgpack_object_map map;
|
||||
msgpack_object_raw raw;
|
||||
} 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;
|
||||
|
||||
|
||||
void msgpack_object_print(FILE* out, msgpack_object o);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* msgpack/object.h */
|
||||
|
||||
116
c/pack.h
116
c/pack.h
|
|
@ -1,116 +0,0 @@
|
|||
/*
|
||||
* MessagePack for C packing routine
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef MSGPACK_PACK_H__
|
||||
#define MSGPACK_PACK_H__
|
||||
|
||||
#include "msgpack/pack_define.h"
|
||||
#include "msgpack/object.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef int (*msgpack_packer_write)(void* data, const char* buf, unsigned int 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_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_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_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, unsigned int n);
|
||||
|
||||
static int msgpack_pack_map(msgpack_packer* pk, unsigned int n);
|
||||
|
||||
static int msgpack_pack_raw(msgpack_packer* pk, size_t l);
|
||||
static int msgpack_pack_raw_body(msgpack_packer* pk, const void* b, size_t l);
|
||||
|
||||
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_user msgpack_packer*
|
||||
|
||||
#define msgpack_pack_append_buffer(user, buf, len) \
|
||||
return (*(user)->callback)((user)->data, (const char*)buf, len)
|
||||
|
||||
#include "msgpack/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);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* msgpack/pack.h */
|
||||
|
||||
85
c/sbuffer.h
85
c/sbuffer.h
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
* MessagePack for C simple buffer implementation
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef MSGPACK_SBUFFER_H__
|
||||
#define MSGPACK_SBUFFER_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef MSGPACK_SBUFFER_INIT_SIZE
|
||||
#define MSGPACK_SBUFFER_INIT_SIZE 2048
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
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 int msgpack_sbuffer_write(void* data, const char* buf, unsigned int len)
|
||||
{
|
||||
msgpack_sbuffer* sbuf = (msgpack_sbuffer*)data;
|
||||
|
||||
if(sbuf->alloc - sbuf->size < len) {
|
||||
size_t nsize = (sbuf->alloc) ?
|
||||
sbuf->alloc * 2 : MSGPACK_SBUFFER_INIT_SIZE;
|
||||
|
||||
while(nsize < sbuf->size + len) { nsize *= 2; }
|
||||
|
||||
void* 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;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* msgpack/sbuffer.h */
|
||||
|
||||
424
c/test.cpp
424
c/test.cpp
|
|
@ -1,424 +0,0 @@
|
|||
#include "msgpack.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
const unsigned int kLoop = 10000;
|
||||
const double kEPS = 1e-10;
|
||||
|
||||
#define GEN_TEST_SIGNED(test_type, func_type) \
|
||||
do { \
|
||||
vector<test_type> v; \
|
||||
v.push_back(0); \
|
||||
v.push_back(1); \
|
||||
v.push_back(-1); \
|
||||
v.push_back(numeric_limits<test_type>::min()); \
|
||||
v.push_back(numeric_limits<test_type>::max()); \
|
||||
for (unsigned int i = 0; i < kLoop; i++) \
|
||||
v.push_back(rand()); \
|
||||
for (unsigned int i = 0; i < v.size() ; i++) { \
|
||||
test_type val = v[i]; \
|
||||
msgpack_sbuffer sbuf; \
|
||||
msgpack_sbuffer_init(&sbuf); \
|
||||
msgpack_packer pk; \
|
||||
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write); \
|
||||
msgpack_pack_##func_type(&pk, val); \
|
||||
msgpack_zone z; \
|
||||
msgpack_zone_init(&z, 2048); \
|
||||
msgpack_object obj; \
|
||||
msgpack_unpack_return ret = \
|
||||
msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj); \
|
||||
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret); \
|
||||
if (val < 0) { \
|
||||
EXPECT_EQ(MSGPACK_OBJECT_NEGATIVE_INTEGER, obj.type); \
|
||||
EXPECT_EQ(val, obj.via.i64); \
|
||||
} else { \
|
||||
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, obj.type); \
|
||||
EXPECT_EQ(val, obj.via.u64); \
|
||||
} \
|
||||
msgpack_zone_destroy(&z); \
|
||||
msgpack_sbuffer_destroy(&sbuf); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define GEN_TEST_UNSIGNED(test_type, func_type) \
|
||||
do { \
|
||||
vector<test_type> v; \
|
||||
v.push_back(0); \
|
||||
v.push_back(1); \
|
||||
v.push_back(2); \
|
||||
v.push_back(numeric_limits<test_type>::min()); \
|
||||
v.push_back(numeric_limits<test_type>::max()); \
|
||||
for (unsigned int i = 0; i < kLoop; i++) \
|
||||
v.push_back(rand()); \
|
||||
for (unsigned int i = 0; i < v.size() ; i++) { \
|
||||
test_type val = v[i]; \
|
||||
msgpack_sbuffer sbuf; \
|
||||
msgpack_sbuffer_init(&sbuf); \
|
||||
msgpack_packer pk; \
|
||||
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write); \
|
||||
msgpack_pack_##func_type(&pk, val); \
|
||||
msgpack_zone z; \
|
||||
msgpack_zone_init(&z, 2048); \
|
||||
msgpack_object obj; \
|
||||
msgpack_unpack_return ret = \
|
||||
msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj); \
|
||||
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret); \
|
||||
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, obj.type); \
|
||||
EXPECT_EQ(val, obj.via.u64); \
|
||||
msgpack_zone_destroy(&z); \
|
||||
msgpack_sbuffer_destroy(&sbuf); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_short)
|
||||
{
|
||||
GEN_TEST_SIGNED(short, short);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_int)
|
||||
{
|
||||
GEN_TEST_SIGNED(int, int);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_long)
|
||||
{
|
||||
GEN_TEST_SIGNED(long, long);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_long_long)
|
||||
{
|
||||
GEN_TEST_SIGNED(long long, long_long);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_unsigned_short)
|
||||
{
|
||||
GEN_TEST_UNSIGNED(unsigned short, unsigned_short);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_unsigned_int)
|
||||
{
|
||||
GEN_TEST_UNSIGNED(unsigned int, unsigned_int);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_unsigned_long)
|
||||
{
|
||||
GEN_TEST_UNSIGNED(unsigned long, unsigned_long);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_unsigned_long_long)
|
||||
{
|
||||
GEN_TEST_UNSIGNED(unsigned long long, unsigned_long_long);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_uint8)
|
||||
{
|
||||
GEN_TEST_UNSIGNED(uint8_t, uint8);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_uint16)
|
||||
{
|
||||
GEN_TEST_UNSIGNED(uint16_t, uint16);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_uint32)
|
||||
{
|
||||
GEN_TEST_UNSIGNED(uint32_t, uint32);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_uint64)
|
||||
{
|
||||
GEN_TEST_UNSIGNED(uint64_t, uint64);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_int8)
|
||||
{
|
||||
GEN_TEST_SIGNED(int8_t, int8);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_int16)
|
||||
{
|
||||
GEN_TEST_SIGNED(int16_t, int16);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_int32)
|
||||
{
|
||||
GEN_TEST_SIGNED(int32_t, int32);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_int64)
|
||||
{
|
||||
GEN_TEST_SIGNED(int64_t, int64);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_float)
|
||||
{
|
||||
vector<float> v;
|
||||
v.push_back(0.0);
|
||||
v.push_back(1.0);
|
||||
v.push_back(-1.0);
|
||||
v.push_back(numeric_limits<float>::min());
|
||||
v.push_back(numeric_limits<float>::max());
|
||||
v.push_back(nanf("tag"));
|
||||
v.push_back(1.0/0.0); // inf
|
||||
v.push_back(-(1.0/0.0)); // -inf
|
||||
for (unsigned int i = 0; i < kLoop; i++) {
|
||||
v.push_back(drand48());
|
||||
v.push_back(-drand48());
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < v.size() ; i++) {
|
||||
float val = v[i];
|
||||
msgpack_sbuffer sbuf;
|
||||
msgpack_sbuffer_init(&sbuf);
|
||||
msgpack_packer pk;
|
||||
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
|
||||
msgpack_pack_float(&pk, val);
|
||||
msgpack_zone z;
|
||||
msgpack_zone_init(&z, 2048);
|
||||
msgpack_object obj;
|
||||
msgpack_unpack_return ret =
|
||||
msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj);
|
||||
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret);
|
||||
EXPECT_EQ(MSGPACK_OBJECT_DOUBLE, obj.type);
|
||||
if (isnan(val))
|
||||
EXPECT_TRUE(isnan(obj.via.dec));
|
||||
else if (isinf(val))
|
||||
EXPECT_TRUE(isinf(obj.via.dec));
|
||||
else
|
||||
EXPECT_TRUE(fabs(obj.via.dec - val) <= kEPS);
|
||||
msgpack_zone_destroy(&z);
|
||||
msgpack_sbuffer_destroy(&sbuf);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_double)
|
||||
{
|
||||
vector<double> v;
|
||||
v.push_back(0.0);
|
||||
v.push_back(-0.0);
|
||||
v.push_back(1.0);
|
||||
v.push_back(-1.0);
|
||||
v.push_back(numeric_limits<double>::min());
|
||||
v.push_back(numeric_limits<double>::max());
|
||||
v.push_back(nan("tag"));
|
||||
v.push_back(1.0/0.0); // inf
|
||||
v.push_back(-(1.0/0.0)); // -inf
|
||||
for (unsigned int i = 0; i < kLoop; i++) {
|
||||
v.push_back(drand48());
|
||||
v.push_back(-drand48());
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < v.size() ; i++) {
|
||||
double val = v[i];
|
||||
msgpack_sbuffer sbuf;
|
||||
msgpack_sbuffer_init(&sbuf);
|
||||
msgpack_packer pk;
|
||||
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
|
||||
msgpack_pack_double(&pk, val);
|
||||
msgpack_zone z;
|
||||
msgpack_zone_init(&z, 2048);
|
||||
msgpack_object obj;
|
||||
msgpack_unpack_return ret =
|
||||
msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj);
|
||||
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret);
|
||||
EXPECT_EQ(MSGPACK_OBJECT_DOUBLE, obj.type);
|
||||
if (isnan(val))
|
||||
EXPECT_TRUE(isnan(obj.via.dec));
|
||||
else if (isinf(val))
|
||||
EXPECT_TRUE(isinf(obj.via.dec));
|
||||
else
|
||||
EXPECT_TRUE(fabs(obj.via.dec - val) <= kEPS);
|
||||
msgpack_zone_destroy(&z);
|
||||
msgpack_sbuffer_destroy(&sbuf);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_nil)
|
||||
{
|
||||
msgpack_sbuffer sbuf;
|
||||
msgpack_sbuffer_init(&sbuf);
|
||||
msgpack_packer pk;
|
||||
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
|
||||
msgpack_pack_nil(&pk);
|
||||
msgpack_zone z;
|
||||
msgpack_zone_init(&z, 2048);
|
||||
msgpack_object obj;
|
||||
msgpack_unpack_return ret =
|
||||
msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj);
|
||||
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret);
|
||||
EXPECT_EQ(MSGPACK_OBJECT_NIL, obj.type);
|
||||
msgpack_zone_destroy(&z);
|
||||
msgpack_sbuffer_destroy(&sbuf);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_true)
|
||||
{
|
||||
msgpack_sbuffer sbuf;
|
||||
msgpack_sbuffer_init(&sbuf);
|
||||
msgpack_packer pk;
|
||||
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
|
||||
msgpack_pack_true(&pk);
|
||||
msgpack_zone z;
|
||||
msgpack_zone_init(&z, 2048);
|
||||
msgpack_object obj;
|
||||
msgpack_unpack_return ret =
|
||||
msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj);
|
||||
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret);
|
||||
EXPECT_EQ(MSGPACK_OBJECT_BOOLEAN, obj.type);
|
||||
EXPECT_EQ(true, obj.via.boolean);
|
||||
msgpack_zone_destroy(&z);
|
||||
msgpack_sbuffer_destroy(&sbuf);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_false)
|
||||
{
|
||||
msgpack_sbuffer sbuf;
|
||||
msgpack_sbuffer_init(&sbuf);
|
||||
msgpack_packer pk;
|
||||
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
|
||||
msgpack_pack_false(&pk);
|
||||
msgpack_zone z;
|
||||
msgpack_zone_init(&z, 2048);
|
||||
msgpack_object obj;
|
||||
msgpack_unpack_return ret =
|
||||
msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj);
|
||||
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret);
|
||||
EXPECT_EQ(MSGPACK_OBJECT_BOOLEAN, obj.type);
|
||||
EXPECT_EQ(false, obj.via.boolean);
|
||||
msgpack_zone_destroy(&z);
|
||||
msgpack_sbuffer_destroy(&sbuf);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_array)
|
||||
{
|
||||
unsigned int array_size = 5;
|
||||
|
||||
msgpack_sbuffer sbuf;
|
||||
msgpack_sbuffer_init(&sbuf);
|
||||
msgpack_packer pk;
|
||||
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
|
||||
msgpack_pack_array(&pk, array_size);
|
||||
msgpack_pack_nil(&pk);
|
||||
msgpack_pack_true(&pk);
|
||||
msgpack_pack_false(&pk);
|
||||
msgpack_pack_int(&pk, 10);
|
||||
msgpack_pack_int(&pk, -10);
|
||||
|
||||
msgpack_zone z;
|
||||
msgpack_zone_init(&z, 2048);
|
||||
msgpack_object obj;
|
||||
msgpack_unpack_return ret;
|
||||
ret = msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj);
|
||||
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret);
|
||||
EXPECT_EQ(MSGPACK_OBJECT_ARRAY, obj.type);
|
||||
EXPECT_EQ(array_size, obj.via.array.size);
|
||||
|
||||
for (unsigned int i = 0; i < obj.via.array.size; i++) {
|
||||
msgpack_object o = obj.via.array.ptr[i];
|
||||
switch (i) {
|
||||
case 0:
|
||||
EXPECT_EQ(MSGPACK_OBJECT_NIL, o.type);
|
||||
break;
|
||||
case 1:
|
||||
EXPECT_EQ(MSGPACK_OBJECT_BOOLEAN, o.type);
|
||||
EXPECT_EQ(true, o.via.boolean);
|
||||
break;
|
||||
case 2:
|
||||
EXPECT_EQ(MSGPACK_OBJECT_BOOLEAN, o.type);
|
||||
EXPECT_EQ(false, o.via.boolean);
|
||||
break;
|
||||
case 3:
|
||||
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, o.type);
|
||||
EXPECT_EQ(10, o.via.u64);
|
||||
break;
|
||||
case 4:
|
||||
EXPECT_EQ(MSGPACK_OBJECT_NEGATIVE_INTEGER, o.type);
|
||||
EXPECT_EQ(-10, o.via.i64);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
msgpack_zone_destroy(&z);
|
||||
msgpack_sbuffer_destroy(&sbuf);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_map)
|
||||
{
|
||||
unsigned int map_size = 2;
|
||||
|
||||
msgpack_sbuffer sbuf;
|
||||
msgpack_sbuffer_init(&sbuf);
|
||||
msgpack_packer pk;
|
||||
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
|
||||
msgpack_pack_map(&pk, map_size);
|
||||
msgpack_pack_true(&pk);
|
||||
msgpack_pack_false(&pk);
|
||||
msgpack_pack_int(&pk, 10);
|
||||
msgpack_pack_int(&pk, -10);
|
||||
|
||||
msgpack_zone z;
|
||||
msgpack_zone_init(&z, 2048);
|
||||
msgpack_object obj;
|
||||
msgpack_unpack_return ret;
|
||||
ret = msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj);
|
||||
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret);
|
||||
EXPECT_EQ(MSGPACK_OBJECT_MAP, obj.type);
|
||||
EXPECT_EQ(map_size, obj.via.map.size);
|
||||
|
||||
for (unsigned int i = 0; i < map_size; i++) {
|
||||
msgpack_object key = obj.via.map.ptr[i].key;
|
||||
msgpack_object val = obj.via.map.ptr[i].val;
|
||||
switch (i) {
|
||||
case 0:
|
||||
EXPECT_EQ(MSGPACK_OBJECT_BOOLEAN, key.type);
|
||||
EXPECT_EQ(true, key.via.boolean);
|
||||
EXPECT_EQ(MSGPACK_OBJECT_BOOLEAN, val.type);
|
||||
EXPECT_EQ(false, val.via.boolean);
|
||||
break;
|
||||
case 1:
|
||||
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, key.type);
|
||||
EXPECT_EQ(10, key.via.u64);
|
||||
EXPECT_EQ(MSGPACK_OBJECT_NEGATIVE_INTEGER, val.type);
|
||||
EXPECT_EQ(-10, val.via.i64);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
msgpack_zone_destroy(&z);
|
||||
msgpack_sbuffer_destroy(&sbuf);
|
||||
}
|
||||
|
||||
TEST(MSGPACKC, simple_buffer_raw)
|
||||
{
|
||||
unsigned int raw_size = 7;
|
||||
|
||||
msgpack_sbuffer sbuf;
|
||||
msgpack_sbuffer_init(&sbuf);
|
||||
msgpack_packer pk;
|
||||
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
|
||||
msgpack_pack_raw(&pk, raw_size);
|
||||
msgpack_pack_raw_body(&pk, "fr", 2);
|
||||
msgpack_pack_raw_body(&pk, "syuki", 5);
|
||||
// invalid data
|
||||
msgpack_pack_raw_body(&pk, "", 0);
|
||||
msgpack_pack_raw_body(&pk, "kzk", 0);
|
||||
|
||||
msgpack_zone z;
|
||||
msgpack_zone_init(&z, 2048);
|
||||
msgpack_object obj;
|
||||
msgpack_unpack_return ret;
|
||||
ret = msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj);
|
||||
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret);
|
||||
EXPECT_EQ(MSGPACK_OBJECT_RAW, obj.type);
|
||||
EXPECT_EQ(raw_size, obj.via.raw.size);
|
||||
EXPECT_EQ(0, memcmp("frsyuki", obj.via.raw.ptr, raw_size));
|
||||
|
||||
msgpack_zone_destroy(&z);
|
||||
msgpack_sbuffer_destroy(&sbuf);
|
||||
}
|
||||
399
c/unpack.c
399
c/unpack.c
|
|
@ -1,399 +0,0 @@
|
|||
/*
|
||||
* MessagePack for C unpacking routine
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "msgpack/unpack.h"
|
||||
#include "msgpack/unpack_define.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
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; return o; }
|
||||
|
||||
static inline int template_callback_uint8(unpack_user* u, uint8_t d, msgpack_object* o)
|
||||
{ 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)
|
||||
{ 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)
|
||||
{ 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)
|
||||
{ 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)
|
||||
{ if(d >= 0) { o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = 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)
|
||||
{ if(d >= 0) { o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = 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)
|
||||
{ if(d >= 0) { o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = 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)
|
||||
{ if(d >= 0) { o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = 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)
|
||||
{ o->type = MSGPACK_OBJECT_DOUBLE; o->via.dec = d; return 0; }
|
||||
|
||||
static inline int template_callback_double(unpack_user* u, double d, msgpack_object* o)
|
||||
{ o->type = MSGPACK_OBJECT_DOUBLE; o->via.dec = d; return 0; }
|
||||
|
||||
static inline int template_callback_nil(unpack_user* u, msgpack_object* o)
|
||||
{ o->type = MSGPACK_OBJECT_NIL; return 0; }
|
||||
|
||||
static inline int template_callback_true(unpack_user* u, msgpack_object* o)
|
||||
{ o->type = MSGPACK_OBJECT_BOOLEAN; o->via.boolean = true; return 0; }
|
||||
|
||||
static inline int template_callback_false(unpack_user* u, msgpack_object* o)
|
||||
{ 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)
|
||||
{
|
||||
o->type = MSGPACK_OBJECT_ARRAY;
|
||||
o->via.array.size = 0;
|
||||
o->via.array.ptr = (msgpack_object*)msgpack_zone_malloc(u->z, n*sizeof(msgpack_object));
|
||||
if(o->via.array.ptr == NULL) { return -1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int template_callback_array_item(unpack_user* u, msgpack_object* c, msgpack_object o)
|
||||
{ c->via.array.ptr[c->via.array.size++] = o; return 0; }
|
||||
|
||||
static inline int template_callback_map(unpack_user* u, unsigned int n, msgpack_object* o)
|
||||
{
|
||||
o->type = MSGPACK_OBJECT_MAP;
|
||||
o->via.map.size = 0;
|
||||
o->via.map.ptr = (msgpack_object_kv*)msgpack_zone_malloc(u->z, n*sizeof(msgpack_object_kv));
|
||||
if(o->via.map.ptr == NULL) { return -1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int template_callback_map_item(unpack_user* u, msgpack_object* c, msgpack_object k, msgpack_object v)
|
||||
{
|
||||
c->via.map.ptr[c->via.map.size].key = k;
|
||||
c->via.map.ptr[c->via.map.size].val = v;
|
||||
++c->via.map.size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int template_callback_raw(unpack_user* u, const char* b, const char* p, unsigned int l, msgpack_object* o)
|
||||
{
|
||||
o->type = MSGPACK_OBJECT_RAW;
|
||||
o->via.raw.ptr = p;
|
||||
o->via.raw.size = l;
|
||||
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 decl_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)
|
||||
{
|
||||
if(initial_buffer_size < COUNTER_SIZE) {
|
||||
initial_buffer_size = COUNTER_SIZE;
|
||||
}
|
||||
|
||||
char* buffer = (char*)malloc(initial_buffer_size);
|
||||
if(buffer == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void* ctx = malloc(sizeof(template_context));
|
||||
if(ctx == NULL) {
|
||||
free(buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
msgpack_zone* z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
|
||||
if(z == NULL) {
|
||||
free(ctx);
|
||||
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 = z;
|
||||
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);
|
||||
decl_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) {
|
||||
size_t next_size = (mpac->used + mpac->free) * 2; // include COUNTER_SIZE
|
||||
while(next_size < size + mpac->used) {
|
||||
next_size *= 2;
|
||||
}
|
||||
|
||||
char* tmp = (char*)realloc(mpac->buffer, next_size);
|
||||
if(tmp == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mpac->buffer = tmp;
|
||||
mpac->free = next_size - mpac->used;
|
||||
|
||||
} else {
|
||||
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) {
|
||||
next_size *= 2;
|
||||
}
|
||||
|
||||
char* 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, decl_count, mpac->buffer)) {
|
||||
free(tmp);
|
||||
return false;
|
||||
}
|
||||
CTX_REFERENCED(mpac) = false;
|
||||
} else {
|
||||
decl_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)
|
||||
{
|
||||
if(!msgpack_unpacker_flush_zone(mpac)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
msgpack_zone* r = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
|
||||
if(r == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
msgpack_zone* old = mpac->z;
|
||||
mpac->z = r;
|
||||
|
||||
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, decl_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;
|
||||
}
|
||||
|
||||
|
||||
msgpack_unpack_return
|
||||
msgpack_unpack(const char* data, size_t len, size_t* off,
|
||||
msgpack_zone* z, msgpack_object* result)
|
||||
{
|
||||
template_context ctx;
|
||||
template_init(&ctx);
|
||||
|
||||
ctx.user.z = z;
|
||||
ctx.user.referenced = false;
|
||||
|
||||
size_t noff = 0;
|
||||
if(off != NULL) { noff = *off; }
|
||||
|
||||
int ret = template_execute(&ctx, data, len, &noff);
|
||||
if(ret < 0) {
|
||||
return MSGPACK_UNPACK_PARSE_ERROR;
|
||||
}
|
||||
|
||||
if(off != NULL) { *off = noff; }
|
||||
|
||||
if(ret == 0) {
|
||||
return MSGPACK_UNPACK_CONTINUE;
|
||||
}
|
||||
|
||||
*result = template_data(&ctx);
|
||||
|
||||
if(noff < len) {
|
||||
return MSGPACK_UNPACK_EXTRA_BYTES;
|
||||
}
|
||||
|
||||
return MSGPACK_UNPACK_SUCCESS;
|
||||
}
|
||||
|
||||
123
c/unpack.h
123
c/unpack.h
|
|
@ -1,123 +0,0 @@
|
|||
/*
|
||||
* MessagePack for C unpacking routine
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef MSGPACK_UNPACKER_H__
|
||||
#define MSGPACK_UNPACKER_H__
|
||||
|
||||
#include "msgpack/zone.h"
|
||||
#include "msgpack/object.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
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;
|
||||
|
||||
|
||||
bool msgpack_unpacker_init(msgpack_unpacker* mpac, size_t initial_buffer_size);
|
||||
void msgpack_unpacker_destroy(msgpack_unpacker* mpac);
|
||||
|
||||
msgpack_unpacker* msgpack_unpacker_new(size_t initial_buffer_size);
|
||||
void msgpack_unpacker_free(msgpack_unpacker* mpac);
|
||||
|
||||
static inline bool msgpack_unpacker_reserve_buffer(msgpack_unpacker* mpac, size_t size);
|
||||
static inline char* msgpack_unpacker_buffer(msgpack_unpacker* mpac);
|
||||
static inline size_t msgpack_unpacker_buffer_capacity(const msgpack_unpacker* mpac);
|
||||
static inline void msgpack_unpacker_buffer_consumed(msgpack_unpacker* mpac, size_t size);
|
||||
|
||||
|
||||
int msgpack_unpacker_execute(msgpack_unpacker* mpac);
|
||||
|
||||
msgpack_object msgpack_unpacker_data(msgpack_unpacker* mpac);
|
||||
|
||||
msgpack_zone* msgpack_unpacker_release_zone(msgpack_unpacker* mpac);
|
||||
|
||||
void msgpack_unpacker_reset_zone(msgpack_unpacker* mpac);
|
||||
|
||||
void msgpack_unpacker_reset(msgpack_unpacker* mpac);
|
||||
|
||||
static inline size_t msgpack_unpacker_message_size(const msgpack_unpacker* mpac);
|
||||
|
||||
|
||||
|
||||
typedef enum {
|
||||
MSGPACK_UNPACK_SUCCESS = 2,
|
||||
MSGPACK_UNPACK_EXTRA_BYTES = 1,
|
||||
MSGPACK_UNPACK_CONTINUE = 0,
|
||||
MSGPACK_UNPACK_PARSE_ERROR = -1,
|
||||
} msgpack_unpack_return;
|
||||
|
||||
msgpack_unpack_return
|
||||
msgpack_unpack(const char* data, size_t len, size_t* off,
|
||||
msgpack_zone* z, msgpack_object* result);
|
||||
|
||||
|
||||
static inline size_t msgpack_unpacker_parsed_size(const msgpack_unpacker* mpac);
|
||||
|
||||
bool msgpack_unpacker_flush_zone(msgpack_unpacker* mpac);
|
||||
|
||||
bool msgpack_unpacker_expand_buffer(msgpack_unpacker* mpac, size_t size);
|
||||
|
||||
bool msgpack_unpacker_reserve_buffer(msgpack_unpacker* mpac, size_t size)
|
||||
{
|
||||
if(mpac->free >= size) { return true; }
|
||||
return msgpack_unpacker_expand_buffer(mpac, size);
|
||||
}
|
||||
|
||||
char* msgpack_unpacker_buffer(msgpack_unpacker* mpac)
|
||||
{
|
||||
return mpac->buffer + mpac->used;
|
||||
}
|
||||
|
||||
size_t msgpack_unpacker_buffer_capacity(const msgpack_unpacker* mpac)
|
||||
{
|
||||
return mpac->free;
|
||||
}
|
||||
|
||||
void msgpack_unpacker_buffer_consumed(msgpack_unpacker* mpac, size_t size)
|
||||
{
|
||||
mpac->used += size;
|
||||
mpac->free -= size;
|
||||
}
|
||||
|
||||
size_t msgpack_unpacker_message_size(const msgpack_unpacker* mpac)
|
||||
{
|
||||
return mpac->parsed - mpac->off + mpac->used;
|
||||
}
|
||||
|
||||
size_t msgpack_unpacker_parsed_size(const msgpack_unpacker* mpac)
|
||||
{
|
||||
return mpac->parsed;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* msgpack/unpack.h */
|
||||
|
||||
135
c/vrefbuffer.c
135
c/vrefbuffer.c
|
|
@ -1,135 +0,0 @@
|
|||
/*
|
||||
* MessagePack for C zero-copy buffer implementation
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "msgpack/vrefbuffer.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
bool msgpack_vrefbuffer_init(msgpack_vrefbuffer* vbuf,
|
||||
size_t ref_size, size_t chunk_size)
|
||||
{
|
||||
if(chunk_size < sizeof(msgpack_vrefbuffer_chunk)+72) {
|
||||
chunk_size = 72;
|
||||
} else {
|
||||
chunk_size -= sizeof(msgpack_vrefbuffer_chunk);
|
||||
}
|
||||
|
||||
vbuf->chunk_size = chunk_size;
|
||||
vbuf->ref_size = ref_size;
|
||||
|
||||
// glibcは72バイト以下のmallocが高速
|
||||
size_t nfirst = (sizeof(struct iovec) < 72/2) ?
|
||||
72 / sizeof(struct iovec) : 8;
|
||||
|
||||
struct iovec* array = (struct iovec*)malloc(
|
||||
sizeof(struct iovec) * nfirst);
|
||||
if(array == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
vbuf->tail = array;
|
||||
vbuf->end = array + nfirst;
|
||||
vbuf->array = array;
|
||||
|
||||
vbuf->chunk = (msgpack_vrefbuffer_chunk*)malloc(
|
||||
chunk_size + sizeof(msgpack_vrefbuffer_chunk));
|
||||
if(vbuf->chunk == NULL) {
|
||||
free(array);
|
||||
return false;
|
||||
}
|
||||
|
||||
vbuf->chunk->next = NULL;
|
||||
vbuf->chunk->free = chunk_size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void msgpack_vrefbuffer_destroy(msgpack_vrefbuffer* vbuf)
|
||||
{
|
||||
msgpack_vrefbuffer_chunk* c = vbuf->chunk;
|
||||
while(true) {
|
||||
msgpack_vrefbuffer_chunk* n = c->next;
|
||||
free(c);
|
||||
if(n) {
|
||||
c = n;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(vbuf->array);
|
||||
}
|
||||
|
||||
int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf,
|
||||
const char* buf, unsigned int len)
|
||||
{
|
||||
if(vbuf->tail == vbuf->end) {
|
||||
const size_t nused = vbuf->end - vbuf->array;
|
||||
const size_t nnext = nused * 2;
|
||||
|
||||
struct iovec* nvec = (struct iovec*)realloc(
|
||||
vbuf->array, sizeof(struct 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, unsigned int len)
|
||||
{
|
||||
msgpack_vrefbuffer_chunk* chunk = vbuf->chunk;
|
||||
size_t cur_size = vbuf->chunk_size;
|
||||
|
||||
if(chunk->free < len) {
|
||||
cur_size = (cur_size > len) ? cur_size : len;
|
||||
|
||||
chunk = (msgpack_vrefbuffer_chunk*)malloc(
|
||||
cur_size + sizeof(msgpack_vrefbuffer_chunk));
|
||||
if(chunk == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
chunk->free = cur_size;
|
||||
chunk->next = vbuf->chunk;
|
||||
vbuf->chunk = chunk;
|
||||
}
|
||||
|
||||
char* m = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk)
|
||||
+ (cur_size - chunk->free);
|
||||
|
||||
memcpy(m, buf, len);
|
||||
chunk->free -= 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);
|
||||
}
|
||||
}
|
||||
|
||||
106
c/vrefbuffer.h
106
c/vrefbuffer.h
|
|
@ -1,106 +0,0 @@
|
|||
/*
|
||||
* MessagePack for C zero-copy buffer implementation
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef MSGPACK_VREFBUFFER_H__
|
||||
#define MSGPACK_VREFBUFFER_H__
|
||||
|
||||
#include "msgpack/zone.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/uio.h>
|
||||
#else
|
||||
struct iovec {
|
||||
void *iov_base;
|
||||
size_t iov_len;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef MSGPACK_VREFBUFFER_REF_SIZE
|
||||
#define MSGPACK_VREFBUFFER_REF_SIZE 32
|
||||
#endif
|
||||
|
||||
#ifndef MSGPACK_VREFBUFFER_CHUNK_SIZE
|
||||
#define MSGPACK_VREFBUFFER_CHUNK_SIZE 2048
|
||||
#endif
|
||||
|
||||
typedef struct msgpack_vrefbuffer_chunk {
|
||||
size_t free;
|
||||
struct msgpack_vrefbuffer_chunk* next;
|
||||
/* data ... */
|
||||
} msgpack_vrefbuffer_chunk;
|
||||
|
||||
typedef struct msgpack_vrefbuffer {
|
||||
size_t chunk_size;
|
||||
size_t ref_size;
|
||||
|
||||
struct iovec* tail;
|
||||
struct iovec* end;
|
||||
struct iovec* array;
|
||||
|
||||
msgpack_vrefbuffer_chunk* chunk;
|
||||
} msgpack_vrefbuffer;
|
||||
|
||||
|
||||
bool msgpack_vrefbuffer_init(msgpack_vrefbuffer* vbuf,
|
||||
size_t ref_size, size_t chunk_size);
|
||||
void msgpack_vrefbuffer_destroy(msgpack_vrefbuffer* vbuf);
|
||||
|
||||
static inline int msgpack_vrefbuffer_write(void* data, const char* buf, unsigned int len);
|
||||
|
||||
static inline const struct iovec* msgpack_vrefbuffer_vec(const msgpack_vrefbuffer* vref);
|
||||
static inline size_t msgpack_vrefbuffer_veclen(const msgpack_vrefbuffer* vref);
|
||||
|
||||
int msgpack_vrefbuffer_append_copy(msgpack_vrefbuffer* vbuf,
|
||||
const char* buf, unsigned int len);
|
||||
|
||||
int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf,
|
||||
const char* buf, unsigned int len);
|
||||
|
||||
|
||||
int msgpack_vrefbuffer_write(void* data, const char* buf, unsigned int len)
|
||||
{
|
||||
msgpack_vrefbuffer* vbuf = (msgpack_vrefbuffer*)data;
|
||||
|
||||
if(len < vbuf->ref_size) {
|
||||
return msgpack_vrefbuffer_append_copy(vbuf, buf, len);
|
||||
} else {
|
||||
return msgpack_vrefbuffer_append_ref(vbuf, buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
const struct iovec* msgpack_vrefbuffer_vec(const msgpack_vrefbuffer* vref)
|
||||
{
|
||||
return vref->array;
|
||||
}
|
||||
|
||||
size_t msgpack_vrefbuffer_veclen(const msgpack_vrefbuffer* vref)
|
||||
{
|
||||
return vref->tail - vref->array;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* msgpack/vrefbuffer.h */
|
||||
|
||||
241
c/zone.c
241
c/zone.c
|
|
@ -1,241 +0,0 @@
|
|||
/*
|
||||
* MessagePack for C memory pool implementation
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "msgpack/zone.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static inline bool init_chunk_array(msgpack_zone_chunk_array* ca, size_t chunk_size)
|
||||
{
|
||||
// glibcは72バイト以下のmallocが高速
|
||||
const size_t nfirst = (sizeof(msgpack_zone_chunk) < 72/2) ?
|
||||
72 / sizeof(msgpack_zone_chunk) : 8;
|
||||
|
||||
msgpack_zone_chunk* array = (msgpack_zone_chunk*)malloc(
|
||||
sizeof(msgpack_zone_chunk) * nfirst);
|
||||
if(array == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t sz = chunk_size;
|
||||
|
||||
char* ptr = (char*)malloc(sz);
|
||||
if(ptr == NULL) {
|
||||
free(array);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ca->tail = array;
|
||||
ca->end = array + nfirst;
|
||||
ca->array = array;
|
||||
|
||||
array[0].free = sz;
|
||||
array[0].ptr = ptr;
|
||||
array[0].alloc = ptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void destroy_chunk_array(msgpack_zone_chunk_array* ca)
|
||||
{
|
||||
msgpack_zone_chunk* chunk = ca->array;
|
||||
for(; chunk != ca->tail+1; ++chunk) {
|
||||
free(chunk->alloc);
|
||||
}
|
||||
|
||||
free(ca->array);
|
||||
}
|
||||
|
||||
static inline void clear_chunk_array(msgpack_zone_chunk_array* ca)
|
||||
{
|
||||
msgpack_zone_chunk* chunk = ca->array + 1;
|
||||
for(; chunk != ca->tail+1; ++chunk) {
|
||||
free(chunk->alloc);
|
||||
}
|
||||
|
||||
ca->tail = ca->array;
|
||||
|
||||
ca->array[0].free += ca->array[0].ptr - (char*)ca->array[0].alloc;
|
||||
ca->array[0].ptr = (char*)ca->array[0].alloc;
|
||||
}
|
||||
|
||||
void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size)
|
||||
{
|
||||
msgpack_zone_chunk_array* const ca = &zone->chunk_array;
|
||||
|
||||
msgpack_zone_chunk* chunk = ++ca->tail;
|
||||
|
||||
if(chunk == ca->end) {
|
||||
// ca->arrayに空きがない
|
||||
// ca->arrayを拡張する
|
||||
|
||||
const size_t nused = ca->end - ca->array;
|
||||
const size_t nnext = (ca->end - ca->array) * 2;
|
||||
|
||||
chunk = (msgpack_zone_chunk*)realloc(ca->array,
|
||||
sizeof(msgpack_zone_chunk) * nnext);
|
||||
if(chunk == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ca->array = chunk;
|
||||
ca->end = chunk + nnext;
|
||||
chunk = ca->tail = chunk + nused;
|
||||
}
|
||||
|
||||
size_t sz = zone->chunk_size;
|
||||
|
||||
while(sz < size) {
|
||||
sz *= 2;
|
||||
}
|
||||
|
||||
char* ptr = (char*)malloc(sz);
|
||||
if(ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
chunk->free = sz - size;
|
||||
chunk->ptr = ptr + size;
|
||||
chunk->alloc = ptr;
|
||||
|
||||
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;
|
||||
|
||||
const size_t nused = fa->end - fa->array;
|
||||
|
||||
size_t nnext;
|
||||
if(nused == 0) {
|
||||
// 初回の呼び出し:fa->tail == fa->end == fa->array == NULL
|
||||
|
||||
// glibcは72バイト以下のmallocが高速
|
||||
nnext = (sizeof(msgpack_zone_finalizer) < 72/2) ?
|
||||
72 / sizeof(msgpack_zone_finalizer) : 8;
|
||||
|
||||
} else {
|
||||
nnext = nused * 2;
|
||||
}
|
||||
|
||||
msgpack_zone_finalizer* 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_array* const ca = &zone->chunk_array;
|
||||
msgpack_zone_finalizer_array* const fa = &zone->finalizer_array;
|
||||
return ca->array[0].ptr == ca->array[0].alloc &&
|
||||
ca->tail == ca->array &&
|
||||
fa->tail == fa->array;
|
||||
}
|
||||
|
||||
|
||||
bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size)
|
||||
{
|
||||
zone->chunk_size = chunk_size;
|
||||
|
||||
if(!init_chunk_array(&zone->chunk_array, chunk_size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
init_finalizer_array(&zone->finalizer_array);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void msgpack_zone_destroy(msgpack_zone* zone)
|
||||
{
|
||||
destroy_finalizer_array(&zone->finalizer_array);
|
||||
destroy_chunk_array(&zone->chunk_array);
|
||||
}
|
||||
|
||||
void msgpack_zone_clear(msgpack_zone* zone)
|
||||
{
|
||||
clear_finalizer_array(&zone->finalizer_array);
|
||||
clear_chunk_array(&zone->chunk_array);
|
||||
}
|
||||
|
||||
msgpack_zone* msgpack_zone_new(size_t chunk_size)
|
||||
{
|
||||
msgpack_zone* zone = (msgpack_zone*)malloc(sizeof(msgpack_zone));
|
||||
if(zone == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!msgpack_zone_init(zone, chunk_size)) {
|
||||
free(zone);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return zone;
|
||||
}
|
||||
|
||||
void msgpack_zone_free(msgpack_zone* zone)
|
||||
{
|
||||
msgpack_zone_destroy(zone);
|
||||
free(zone);
|
||||
}
|
||||
|
||||
135
c/zone.h
135
c/zone.h
|
|
@ -1,135 +0,0 @@
|
|||
/*
|
||||
* MessagePack for C memory pool implementation
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef MSGPACK_ZONE_H__
|
||||
#define MSGPACK_ZONE_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct msgpack_zone_chunk {
|
||||
size_t free;
|
||||
char* ptr;
|
||||
void* alloc;
|
||||
} msgpack_zone_chunk;
|
||||
|
||||
typedef struct msgpack_zone_finalizer {
|
||||
void (*func)(void* data);
|
||||
void* data;
|
||||
} msgpack_zone_finalizer;
|
||||
|
||||
typedef struct msgpack_zone_chunk_array {
|
||||
msgpack_zone_chunk* tail;
|
||||
msgpack_zone_chunk* end;
|
||||
msgpack_zone_chunk* array;
|
||||
} msgpack_zone_chunk_array;
|
||||
|
||||
typedef struct msgpack_zone_finalizer_array {
|
||||
msgpack_zone_finalizer* tail;
|
||||
msgpack_zone_finalizer* end;
|
||||
msgpack_zone_finalizer* array;
|
||||
} msgpack_zone_finalizer_array;
|
||||
|
||||
typedef struct msgpack_zone {
|
||||
msgpack_zone_chunk_array chunk_array;
|
||||
msgpack_zone_finalizer_array finalizer_array;
|
||||
size_t chunk_size;
|
||||
} msgpack_zone;
|
||||
|
||||
#ifndef MSGPACK_ZONE_CHUNK_SIZE
|
||||
#define MSGPACK_ZONE_CHUNK_SIZE 2048
|
||||
#endif
|
||||
|
||||
bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size);
|
||||
void msgpack_zone_destroy(msgpack_zone* zone);
|
||||
|
||||
msgpack_zone* msgpack_zone_new(size_t chunk_size);
|
||||
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);
|
||||
|
||||
bool msgpack_zone_is_empty(msgpack_zone* zone);
|
||||
|
||||
void msgpack_zone_clear(msgpack_zone* zone);
|
||||
|
||||
|
||||
|
||||
#ifndef MSGPACK_ZONE_ALIGN
|
||||
#define MSGPACK_ZONE_ALIGN sizeof(int)
|
||||
#endif
|
||||
|
||||
void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size);
|
||||
|
||||
void* msgpack_zone_malloc_no_align(msgpack_zone* zone, size_t size)
|
||||
{
|
||||
msgpack_zone_chunk* chunk = zone->chunk_array.tail;
|
||||
|
||||
if(chunk->free < size) {
|
||||
return msgpack_zone_malloc_expand(zone, size);
|
||||
}
|
||||
|
||||
char* ptr = chunk->ptr;
|
||||
chunk->ptr += size;
|
||||
chunk->free -= size;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* msgpack_zone_malloc(msgpack_zone* zone, size_t size)
|
||||
{
|
||||
return msgpack_zone_malloc_no_align(zone,
|
||||
((size)+((MSGPACK_ZONE_ALIGN)-1)) & ~((MSGPACK_ZONE_ALIGN)-1));
|
||||
}
|
||||
|
||||
|
||||
bool msgpack_zone_push_finalizer_expand(msgpack_zone* zone,
|
||||
void (*func)(void* data), void* data);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* msgpack/zone.h */
|
||||
|
||||
39
configure.in
39
configure.in
|
|
@ -1,39 +0,0 @@
|
|||
AC_INIT(msgpack/unpack_template.h)
|
||||
AC_CONFIG_AUX_DIR(ac)
|
||||
AM_INIT_AUTOMAKE(msgpack, 0.3.9)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
|
||||
AC_SUBST(CFLAGS)
|
||||
if test "" = "$CFLAGS"; then
|
||||
CFLAGS="-g -O4"
|
||||
fi
|
||||
|
||||
AC_PROG_CC
|
||||
|
||||
CFLAGS="-O4 -Wall $CFLAGS -I.."
|
||||
|
||||
|
||||
AC_MSG_CHECKING([if c++ api is enabled])
|
||||
AC_ARG_ENABLE(cxx,
|
||||
AS_HELP_STRING([--disable-cxx],
|
||||
[don't build c++ api.]) )
|
||||
AC_MSG_RESULT($enable_cxx)
|
||||
if test "$enable_cxx" != "no"; then
|
||||
AC_SUBST(CXXFLAGS)
|
||||
if test "" = "$CXXFLAGS"; then
|
||||
CXXFLAGS="-g -O4"
|
||||
fi
|
||||
fi
|
||||
|
||||
# FIXME
|
||||
AC_PROG_CXX
|
||||
|
||||
CXXFLAGS="-O4 -Wall $CXXFLAGS -I.. -I../c"
|
||||
|
||||
|
||||
AM_CONDITIONAL(ENABLE_CXX, test "$enable_cxx" != "no")
|
||||
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
AC_OUTPUT([Makefile c/Makefile cpp/Makefile])
|
||||
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
lib_LTLIBRARIES = libmsgpack.la
|
||||
|
||||
libmsgpack_la_SOURCES = \
|
||||
object.cpp
|
||||
|
||||
nobase_include_HEADERS = \
|
||||
msgpack.hpp \
|
||||
msgpack/sbuffer.hpp \
|
||||
msgpack/vrefbuffer.hpp \
|
||||
msgpack/pack.hpp \
|
||||
msgpack/unpack.hpp \
|
||||
msgpack/object.hpp \
|
||||
msgpack/zone.hpp \
|
||||
msgpack/type.hpp \
|
||||
msgpack/type/bool.hpp \
|
||||
msgpack/type/float.hpp \
|
||||
msgpack/type/int.hpp \
|
||||
msgpack/type/list.hpp \
|
||||
msgpack/type/deque.hpp \
|
||||
msgpack/type/map.hpp \
|
||||
msgpack/type/nil.hpp \
|
||||
msgpack/type/pair.hpp \
|
||||
msgpack/type/raw.hpp \
|
||||
msgpack/type/set.hpp \
|
||||
msgpack/type/string.hpp \
|
||||
msgpack/type/vector.hpp \
|
||||
msgpack/type/tuple.hpp \
|
||||
msgpack/type/define.hpp
|
||||
|
||||
libmsgpack_la_LIBADD = -L../c -lmsgpackc
|
||||
|
||||
# -version-info CURRENT:REVISION:AGE
|
||||
libmsgpack_la_LDFLAGS = -version-info 1:0:0
|
||||
|
||||
check_PROGRAMS = \
|
||||
msgpack_test
|
||||
|
||||
msgpack_test_SOURCES = test.cpp
|
||||
msgpack_test_CXXFLAGS = -I$(top_srcdir) -I$(top_srcdir)/c -I$(top_srcdir)/cpp
|
||||
msgpack_test_LDFLAGS = libmsgpack.la -lgtest_main
|
||||
|
||||
TESTS = $(check_PROGRAMS)
|
||||
188
cpp/bench.cpp
188
cpp/bench.cpp
|
|
@ -1,188 +0,0 @@
|
|||
#include <msgpack/unpack.hpp>
|
||||
#include <msgpack/pack.hpp>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
static const unsigned int TASK_INT_NUM = 1<<24;
|
||||
static const unsigned int TASK_STR_LEN = 1<<15;
|
||||
//static const unsigned int TASK_INT_NUM = 1<<22;
|
||||
//static const unsigned int TASK_STR_LEN = 1<<13;
|
||||
static const char* TASK_STR_PTR;
|
||||
|
||||
|
||||
class simple_timer {
|
||||
public:
|
||||
void reset() { gettimeofday(&m_timeval, NULL); }
|
||||
void show_stat(size_t bufsz)
|
||||
{
|
||||
struct timeval endtime;
|
||||
gettimeofday(&endtime, NULL);
|
||||
double sec = (endtime.tv_sec - m_timeval.tv_sec)
|
||||
+ (double)(endtime.tv_usec - m_timeval.tv_usec) / 1000 / 1000;
|
||||
std::cout << sec << " sec" << std::endl;
|
||||
std::cout << (double(bufsz)/1024/1024) << " MB" << std::endl;
|
||||
std::cout << (bufsz/sec/1000/1000*8) << " Mbps" << std::endl;
|
||||
}
|
||||
private:
|
||||
timeval m_timeval;
|
||||
};
|
||||
|
||||
|
||||
class simple_buffer {
|
||||
public:
|
||||
static const size_t DEFAULT_INITIAL_SIZE = 32*1024;//512*1024*1024*2;
|
||||
|
||||
simple_buffer(size_t initial_size = DEFAULT_INITIAL_SIZE) :
|
||||
m_storage((char*)malloc(initial_size)),
|
||||
m_allocated(initial_size),
|
||||
m_used(0)
|
||||
{
|
||||
if(!m_storage) { throw std::bad_alloc(); }
|
||||
}
|
||||
|
||||
~simple_buffer()
|
||||
{
|
||||
free(m_storage);
|
||||
}
|
||||
|
||||
public:
|
||||
inline void write(const char* buf, size_t len)
|
||||
{
|
||||
if(m_allocated - m_used < len) {
|
||||
expand_buffer(len);
|
||||
}
|
||||
memcpy(m_storage + m_used, buf, len);
|
||||
m_used += len;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_used = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void expand_buffer(size_t req)
|
||||
{
|
||||
size_t nsize = m_allocated * 2;
|
||||
size_t at_least = m_used + req;
|
||||
while(nsize < at_least) { nsize *= 2; }
|
||||
char* tmp = (char*)realloc(m_storage, nsize);
|
||||
if(!tmp) { throw std::bad_alloc(); }
|
||||
m_storage = tmp;
|
||||
m_allocated = nsize;
|
||||
}
|
||||
|
||||
public:
|
||||
size_t size() const { return m_used; }
|
||||
const char* data() const { return m_storage; }
|
||||
|
||||
private:
|
||||
char* m_storage;
|
||||
size_t m_allocated;
|
||||
size_t m_used;
|
||||
};
|
||||
|
||||
|
||||
void bench_msgpack_int()
|
||||
{
|
||||
simple_buffer buf;
|
||||
simple_timer timer;
|
||||
|
||||
std::cout << "----" << std::endl;
|
||||
std::cout << "pack integer" << std::endl;
|
||||
|
||||
timer.reset();
|
||||
{
|
||||
msgpack::packer<simple_buffer> pk(buf);
|
||||
pk.pack_array(TASK_INT_NUM);
|
||||
for(unsigned int i=0; i < TASK_INT_NUM; ++i) {
|
||||
pk.pack_unsigned_int(i);
|
||||
}
|
||||
}
|
||||
timer.show_stat(buf.size());
|
||||
|
||||
|
||||
std::cout << "----" << std::endl;
|
||||
std::cout << "unpack integer" << std::endl;
|
||||
|
||||
msgpack::zone z;
|
||||
msgpack::object obj;
|
||||
|
||||
timer.reset();
|
||||
{
|
||||
obj = msgpack::unpack(buf.data(), buf.size(), z);
|
||||
}
|
||||
timer.show_stat(buf.size());
|
||||
|
||||
/*
|
||||
std::cout << "----" << std::endl;
|
||||
std::cout << "dynamic pack integer" << std::endl;
|
||||
|
||||
buf.clear();
|
||||
|
||||
timer.reset();
|
||||
msgpack::pack(buf, obj);
|
||||
timer.show_stat(buf.size());
|
||||
*/
|
||||
}
|
||||
|
||||
void bench_msgpack_str()
|
||||
{
|
||||
simple_buffer buf;
|
||||
simple_timer timer;
|
||||
|
||||
std::cout << "----" << std::endl;
|
||||
std::cout << "pack string" << std::endl;
|
||||
|
||||
timer.reset();
|
||||
{
|
||||
msgpack::packer<simple_buffer> pk(buf);
|
||||
pk.pack_array(TASK_STR_LEN);
|
||||
for(unsigned int i=0; i < TASK_STR_LEN; ++i) {
|
||||
pk.pack_raw(i);
|
||||
pk.pack_raw_body(TASK_STR_PTR, i);
|
||||
}
|
||||
}
|
||||
timer.show_stat(buf.size());
|
||||
|
||||
|
||||
std::cout << "----" << std::endl;
|
||||
std::cout << "unpack string" << std::endl;
|
||||
|
||||
msgpack::zone z;
|
||||
msgpack::object obj;
|
||||
|
||||
timer.reset();
|
||||
{
|
||||
obj = msgpack::unpack(buf.data(), buf.size(), z);
|
||||
}
|
||||
timer.show_stat(buf.size());
|
||||
|
||||
|
||||
/*
|
||||
std::cout << "----" << std::endl;
|
||||
std::cout << "dynamic pack string" << std::endl;
|
||||
|
||||
buf.clear();
|
||||
|
||||
timer.reset();
|
||||
msgpack::pack(buf, obj);
|
||||
timer.show_stat(buf.size());
|
||||
*/
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char* str = (char*)malloc(TASK_STR_LEN);
|
||||
memset(str, 'a', TASK_STR_LEN);
|
||||
TASK_STR_PTR = str;
|
||||
|
||||
bench_msgpack_int();
|
||||
bench_msgpack_str();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
|
||||
CXXFLAGS += -Wall -g -I. -I.. -O4
|
||||
LDFLAGS +=
|
||||
|
||||
all: bench
|
||||
|
||||
bench: bench.o unpack.o zone.o object.o pack.hpp unpack.hpp zone.hpp object.hpp
|
||||
$(CXX) bench.o unpack.o zone.o object.o $(CXXFLAGS) $(LDFLAGS) -o $@
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
.
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#include "msgpack/object.hpp"
|
||||
#include "msgpack/zone.hpp"
|
||||
#include "msgpack/pack.hpp"
|
||||
#include "msgpack/unpack.hpp"
|
||||
#include "msgpack/sbuffer.hpp"
|
||||
#include "msgpack/vrefbuffer.hpp"
|
||||
#include "msgpack.h"
|
||||
138
cpp/object.cpp
138
cpp/object.cpp
|
|
@ -1,138 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ dynamic typed objects
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#include "msgpack/object.hpp"
|
||||
#include <string.h>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
std::ostream& operator<< (std::ostream& s, const object o)
|
||||
{
|
||||
switch(o.type) {
|
||||
case type::NIL:
|
||||
s << "nil";
|
||||
break;
|
||||
|
||||
case type::BOOLEAN:
|
||||
s << (o.via.boolean ? "true" : "false");
|
||||
break;
|
||||
|
||||
case type::POSITIVE_INTEGER:
|
||||
s << o.via.u64;
|
||||
break;
|
||||
|
||||
case type::NEGATIVE_INTEGER:
|
||||
s << o.via.i64;
|
||||
break;
|
||||
|
||||
case type::DOUBLE:
|
||||
s << o.via.dec;
|
||||
break;
|
||||
|
||||
case type::RAW:
|
||||
(s << '"').write(o.via.raw.ptr, o.via.raw.size) << '"';
|
||||
break;
|
||||
|
||||
case type::ARRAY:
|
||||
s << "[";
|
||||
if(o.via.array.size != 0) {
|
||||
object* p(o.via.array.ptr);
|
||||
s << *p;
|
||||
++p;
|
||||
for(object* const pend(o.via.array.ptr + o.via.array.size);
|
||||
p < pend; ++p) {
|
||||
s << ", " << *p;
|
||||
}
|
||||
}
|
||||
s << "]";
|
||||
break;
|
||||
// FIXME loop optimiziation
|
||||
|
||||
case type::MAP:
|
||||
s << "{";
|
||||
if(o.via.map.size != 0) {
|
||||
object_kv* p(o.via.map.ptr);
|
||||
s << p->key << "=>" << p->val;
|
||||
++p;
|
||||
for(object_kv* const pend(o.via.map.ptr + o.via.map.size);
|
||||
p < pend; ++p) {
|
||||
s << ", " << p->key << "=>" << p->val;
|
||||
}
|
||||
}
|
||||
s << "}";
|
||||
break;
|
||||
// FIXME loop optimiziation
|
||||
|
||||
default:
|
||||
// FIXME
|
||||
s << "#<UNKNOWN " << (uint16_t)o.type << ">";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
bool operator==(const object x, const object y)
|
||||
{
|
||||
if(x.type != y.type) { return false; }
|
||||
|
||||
switch(x.type) {
|
||||
case type::NIL:
|
||||
return true;
|
||||
|
||||
case type::BOOLEAN:
|
||||
return x.via.boolean == y.via.boolean;
|
||||
|
||||
case type::POSITIVE_INTEGER:
|
||||
return x.via.u64 == y.via.u64;
|
||||
|
||||
case type::NEGATIVE_INTEGER:
|
||||
return x.via.i64 == y.via.i64;
|
||||
|
||||
case type::RAW:
|
||||
return x.via.raw.size == y.via.raw.size &&
|
||||
memcmp(x.via.raw.ptr, y.via.raw.ptr, x.via.raw.size) == 0;
|
||||
|
||||
case type::ARRAY:
|
||||
if(x.via.array.size != y.via.array.size) { return false; }
|
||||
for(object* px(x.via.array.ptr),
|
||||
* const pxend(x.via.array.ptr + x.via.array.size),
|
||||
* py(y.via.array.ptr);
|
||||
px < pxend; ++px, ++py) {
|
||||
if(*px != *py) { return false; }
|
||||
}
|
||||
return true;
|
||||
// FIXME loop optimiziation
|
||||
|
||||
case type::MAP:
|
||||
if(x.via.map.size != y.via.map.size) { return false; }
|
||||
for(object_kv* px(x.via.map.ptr),
|
||||
* const pxend(x.via.map.ptr + x.via.map.size),
|
||||
* py(y.via.map.ptr);
|
||||
px < pxend; ++px, ++py) {
|
||||
if(px->key != py->key || px->val != py->val) { return false; }
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
329
cpp/object.hpp
329
cpp/object.hpp
|
|
@ -1,329 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_OBJECT_HPP__
|
||||
#define MSGPACK_OBJECT_HPP__
|
||||
|
||||
#include "msgpack/object.h"
|
||||
#include "msgpack/pack.hpp"
|
||||
#include <string.h>
|
||||
#include <stdexcept>
|
||||
#include <typeinfo>
|
||||
#include <limits>
|
||||
#include <ostream>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
class type_error : public std::bad_cast { };
|
||||
|
||||
|
||||
namespace type {
|
||||
enum object_type {
|
||||
NIL = 0x01,
|
||||
BOOLEAN = 0x02,
|
||||
POSITIVE_INTEGER = 0x03,
|
||||
NEGATIVE_INTEGER = 0x04,
|
||||
DOUBLE = 0x05,
|
||||
RAW = 0x06,
|
||||
ARRAY = 0x07,
|
||||
MAP = 0x08,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
struct object;
|
||||
struct object_kv;
|
||||
|
||||
struct object_array {
|
||||
uint32_t size;
|
||||
object* ptr;
|
||||
};
|
||||
|
||||
struct object_map {
|
||||
uint32_t size;
|
||||
object_kv* ptr;
|
||||
};
|
||||
|
||||
struct object_raw {
|
||||
uint32_t size;
|
||||
const char* ptr;
|
||||
};
|
||||
|
||||
struct object {
|
||||
union union_type {
|
||||
bool boolean;
|
||||
uint64_t u64;
|
||||
int64_t i64;
|
||||
double dec;
|
||||
object_array array;
|
||||
object_map map;
|
||||
object_raw raw;
|
||||
object_raw ref; // obsolete
|
||||
};
|
||||
|
||||
type::object_type type;
|
||||
union_type via;
|
||||
|
||||
bool is_nil() const { return type == type::NIL; }
|
||||
|
||||
template <typename T>
|
||||
T as() const;
|
||||
|
||||
template <typename T>
|
||||
void convert(T* v) const;
|
||||
|
||||
object();
|
||||
object(msgpack_object obj);
|
||||
operator msgpack_object();
|
||||
|
||||
private:
|
||||
struct implicit_type;
|
||||
|
||||
public:
|
||||
implicit_type convert() const;
|
||||
};
|
||||
|
||||
struct object_kv {
|
||||
object key;
|
||||
object val;
|
||||
};
|
||||
|
||||
bool operator==(const object x, const object y);
|
||||
bool operator!=(const object x, const object y);
|
||||
|
||||
std::ostream& operator<< (std::ostream& s, const object o);
|
||||
|
||||
|
||||
template <typename Stream, typename T>
|
||||
packer<Stream>& operator<< (packer<Stream>& o, const T& v);
|
||||
|
||||
template <typename T>
|
||||
T& operator>> (object o, T& v);
|
||||
|
||||
|
||||
struct object::implicit_type {
|
||||
implicit_type(object o) : obj(o) { }
|
||||
~implicit_type() { }
|
||||
|
||||
template <typename T>
|
||||
operator T() { return obj.as<T>(); }
|
||||
|
||||
private:
|
||||
object obj;
|
||||
};
|
||||
|
||||
|
||||
// obsolete
|
||||
template <typename Type>
|
||||
class define : public Type {
|
||||
public:
|
||||
typedef Type msgpack_type;
|
||||
typedef define<Type> define_type;
|
||||
|
||||
define() {}
|
||||
define(const msgpack_type& v) : msgpack_type(v) {}
|
||||
|
||||
template <typename Packer>
|
||||
void msgpack_pack(Packer& o) const
|
||||
{
|
||||
o << static_cast<const msgpack_type&>(*this);
|
||||
}
|
||||
|
||||
void msgpack_unpack(object o)
|
||||
{
|
||||
o >> static_cast<msgpack_type&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Stream>
|
||||
template <typename T>
|
||||
inline packer<Stream>& packer<Stream>::pack(const T& v)
|
||||
{
|
||||
*this << v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline object& operator>> (object o, object& v)
|
||||
{
|
||||
v = o;
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T& operator>> (object o, T& v)
|
||||
{
|
||||
v.msgpack_unpack(o.convert());
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Stream, typename T>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const T& v)
|
||||
{
|
||||
v.msgpack_pack(o);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
inline bool operator!=(const object x, const object y)
|
||||
{ return !(x == y); }
|
||||
|
||||
|
||||
inline object::object() { }
|
||||
|
||||
inline object::object(msgpack_object obj)
|
||||
{
|
||||
// FIXME beter way?
|
||||
::memcpy(this, &obj, sizeof(obj));
|
||||
}
|
||||
|
||||
inline object::operator msgpack_object()
|
||||
{
|
||||
// FIXME beter way?
|
||||
msgpack_object obj;
|
||||
::memcpy(&obj, this, sizeof(obj));
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
inline object::implicit_type object::convert() const
|
||||
{
|
||||
return implicit_type(*this);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void object::convert(T* v) const
|
||||
{
|
||||
*this >> *v;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T object::as() const
|
||||
{
|
||||
T v;
|
||||
convert(&v);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
// obsolete
|
||||
template <typename T>
|
||||
inline void convert(T& v, object o)
|
||||
{
|
||||
o.convert(&v);
|
||||
}
|
||||
|
||||
// obsolete
|
||||
template <typename Stream, typename T>
|
||||
inline void pack(packer<Stream>& o, const T& v)
|
||||
{
|
||||
o.pack(v);
|
||||
}
|
||||
|
||||
// obsolete
|
||||
template <typename Stream, typename T>
|
||||
inline void pack_copy(packer<Stream>& o, T v)
|
||||
{
|
||||
pack(o, v);
|
||||
}
|
||||
|
||||
|
||||
template <typename Stream>
|
||||
packer<Stream>& operator<< (packer<Stream>& o, const object& v)
|
||||
{
|
||||
switch(v.type) {
|
||||
case type::NIL:
|
||||
o.pack_nil();
|
||||
return o;
|
||||
|
||||
case type::BOOLEAN:
|
||||
if(v.via.boolean) {
|
||||
o.pack_true();
|
||||
} else {
|
||||
o.pack_false();
|
||||
}
|
||||
return o;
|
||||
|
||||
case type::POSITIVE_INTEGER:
|
||||
if(v.via.u64 <= (uint64_t)std::numeric_limits<uint16_t>::max()) {
|
||||
if(v.via.u64 <= (uint16_t)std::numeric_limits<uint8_t>::max()) {
|
||||
o.pack_uint8(v.via.u64);
|
||||
} else {
|
||||
o.pack_uint16(v.via.u64);
|
||||
}
|
||||
} else {
|
||||
if(v.via.u64 <= (uint64_t)std::numeric_limits<uint32_t>::max()) {
|
||||
o.pack_uint32(v.via.u64);
|
||||
} else {
|
||||
o.pack_uint64(v.via.u64);
|
||||
}
|
||||
}
|
||||
return o;
|
||||
|
||||
case type::NEGATIVE_INTEGER:
|
||||
if(v.via.i64 >= (int64_t)std::numeric_limits<int16_t>::min()) {
|
||||
if(v.via.i64 >= (int64_t)std::numeric_limits<int8_t>::min()) {
|
||||
o.pack_int8(v.via.i64);
|
||||
} else {
|
||||
o.pack_int16(v.via.i64);
|
||||
}
|
||||
} else {
|
||||
if(v.via.i64 >= (int64_t)std::numeric_limits<int32_t>::min()) {
|
||||
o.pack_int64(v.via.i64);
|
||||
} else {
|
||||
o.pack_int64(v.via.i64);
|
||||
}
|
||||
}
|
||||
return o;
|
||||
|
||||
case type::RAW:
|
||||
o.pack_raw(v.via.raw.size);
|
||||
o.pack_raw_body(v.via.raw.ptr, v.via.raw.size);
|
||||
return o;
|
||||
|
||||
case type::ARRAY:
|
||||
o.pack_array(v.via.array.size);
|
||||
for(object* p(v.via.array.ptr),
|
||||
* const pend(v.via.array.ptr + v.via.array.size);
|
||||
p < pend; ++p) {
|
||||
o << *p;
|
||||
}
|
||||
return o;
|
||||
|
||||
case type::MAP:
|
||||
o.pack_map(v.via.map.size);
|
||||
for(object_kv* p(v.via.map.ptr),
|
||||
* const pend(v.via.map.ptr + v.via.map.size);
|
||||
p < pend; ++p) {
|
||||
o << p->key;
|
||||
o << p->val;
|
||||
}
|
||||
return o;
|
||||
|
||||
default:
|
||||
throw type_error();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#include "msgpack/type.hpp"
|
||||
|
||||
#endif /* msgpack/object.hpp */
|
||||
|
||||
252
cpp/pack.hpp
252
cpp/pack.hpp
|
|
@ -1,252 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ serializing routine
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_PACK_HPP__
|
||||
#define MSGPACK_PACK_HPP__
|
||||
|
||||
#include "msgpack/pack_define.h"
|
||||
#include <stdexcept>
|
||||
#include <limits.h>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
template <typename Stream>
|
||||
class packer {
|
||||
public:
|
||||
packer(Stream& s);
|
||||
~packer();
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
packer<Stream>& pack(const T& v);
|
||||
|
||||
packer<Stream>& pack_uint8(uint8_t d);
|
||||
packer<Stream>& pack_uint16(uint16_t d);
|
||||
packer<Stream>& pack_uint32(uint32_t d);
|
||||
packer<Stream>& pack_uint64(uint64_t d);
|
||||
packer<Stream>& pack_int8(uint8_t d);
|
||||
packer<Stream>& pack_int16(uint16_t d);
|
||||
packer<Stream>& pack_int32(uint32_t d);
|
||||
packer<Stream>& pack_int64(uint64_t d);
|
||||
|
||||
packer<Stream>& pack_short(int d);
|
||||
packer<Stream>& pack_int(int d);
|
||||
packer<Stream>& pack_long(long d);
|
||||
packer<Stream>& pack_long_long(long long d);
|
||||
packer<Stream>& pack_unsigned_short(unsigned short d);
|
||||
packer<Stream>& pack_unsigned_int(unsigned int d);
|
||||
packer<Stream>& pack_unsigned_long(unsigned long d);
|
||||
packer<Stream>& pack_unsigned_long_long(unsigned long long d);
|
||||
|
||||
packer<Stream>& pack_float(float d);
|
||||
packer<Stream>& pack_double(double d);
|
||||
|
||||
packer<Stream>& pack_nil();
|
||||
packer<Stream>& pack_true();
|
||||
packer<Stream>& pack_false();
|
||||
|
||||
packer<Stream>& pack_array(unsigned int n);
|
||||
|
||||
packer<Stream>& pack_map(unsigned int n);
|
||||
|
||||
packer<Stream>& pack_raw(size_t l);
|
||||
packer<Stream>& pack_raw_body(const char* b, size_t l);
|
||||
|
||||
private:
|
||||
static void _pack_uint8(Stream& x, uint8_t d);
|
||||
static void _pack_uint16(Stream& x, uint16_t d);
|
||||
static void _pack_uint32(Stream& x, uint32_t d);
|
||||
static void _pack_uint64(Stream& x, uint64_t d);
|
||||
static void _pack_int8(Stream& x, int8_t d);
|
||||
static void _pack_int16(Stream& x, int16_t d);
|
||||
static void _pack_int32(Stream& x, int32_t d);
|
||||
static void _pack_int64(Stream& x, int64_t d);
|
||||
|
||||
static void _pack_short(Stream& x, short d);
|
||||
static void _pack_int(Stream& x, int d);
|
||||
static void _pack_long(Stream& x, long d);
|
||||
static void _pack_long_long(Stream& x, long long d);
|
||||
static void _pack_unsigned_short(Stream& x, unsigned short d);
|
||||
static void _pack_unsigned_int(Stream& x, unsigned int d);
|
||||
static void _pack_unsigned_long(Stream& x, unsigned long d);
|
||||
static void _pack_unsigned_long_long(Stream& x, unsigned long long d);
|
||||
|
||||
static void _pack_float(Stream& x, float d);
|
||||
static void _pack_double(Stream& x, double d);
|
||||
|
||||
static void _pack_nil(Stream& x);
|
||||
static void _pack_true(Stream& x);
|
||||
static void _pack_false(Stream& x);
|
||||
|
||||
static void _pack_array(Stream& x, unsigned int n);
|
||||
|
||||
static void _pack_map(Stream& x, unsigned int n);
|
||||
|
||||
static void _pack_raw(Stream& x, size_t l);
|
||||
static void _pack_raw_body(Stream& x, const void* b, size_t l);
|
||||
|
||||
static void append_buffer(Stream& x, const unsigned char* buf, unsigned int len)
|
||||
{ x.write((const char*)buf, len); }
|
||||
|
||||
private:
|
||||
Stream& m_stream;
|
||||
|
||||
private:
|
||||
packer();
|
||||
};
|
||||
|
||||
|
||||
template <typename Stream, typename T>
|
||||
inline void pack(Stream& s, const T& v)
|
||||
{
|
||||
packer<Stream>(s).pack(v);
|
||||
}
|
||||
|
||||
|
||||
#define msgpack_pack_inline_func(name) \
|
||||
template <typename Stream> \
|
||||
inline void packer<Stream>::_pack ## name
|
||||
|
||||
#define msgpack_pack_inline_func_cint(name) \
|
||||
template <typename Stream> \
|
||||
inline void packer<Stream>::_pack ## name
|
||||
|
||||
#define msgpack_pack_user Stream&
|
||||
|
||||
#define msgpack_pack_append_buffer append_buffer
|
||||
|
||||
#include "msgpack/pack_template.h"
|
||||
|
||||
|
||||
template <typename Stream>
|
||||
packer<Stream>::packer(Stream& s) : m_stream(s) { }
|
||||
|
||||
template <typename Stream>
|
||||
packer<Stream>::~packer() { }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_uint8(uint8_t d)
|
||||
{ _pack_uint8(m_stream, d); return *this; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_uint16(uint16_t d)
|
||||
{ _pack_uint16(m_stream, d); return *this; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_uint32(uint32_t d)
|
||||
{ _pack_uint32(m_stream, d); return *this; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_uint64(uint64_t d)
|
||||
{ _pack_uint64(m_stream, d); return *this; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_int8(uint8_t d)
|
||||
{ _pack_int8(m_stream, d); return *this; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_int16(uint16_t d)
|
||||
{ _pack_int16(m_stream, d); return *this; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_int32(uint32_t d)
|
||||
{ _pack_int32(m_stream, d); return *this; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_int64(uint64_t d)
|
||||
{ _pack_int64(m_stream, d); return *this;}
|
||||
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_short(int d)
|
||||
{ _pack_short(m_stream, d); return *this; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_int(int d)
|
||||
{ _pack_int(m_stream, d); return *this; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_long(long d)
|
||||
{ _pack_long(m_stream, d); return *this; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_long_long(long long d)
|
||||
{ _pack_long_long(m_stream, d); return *this; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_unsigned_short(unsigned short d)
|
||||
{ _pack_unsigned_short(m_stream, d); return *this; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_unsigned_int(unsigned int d)
|
||||
{ _pack_unsigned_int(m_stream, d); return *this; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_unsigned_long(unsigned long d)
|
||||
{ _pack_unsigned_long(m_stream, d); return *this; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_unsigned_long_long(unsigned long long d)
|
||||
{ _pack_unsigned_long_long(m_stream, d); return *this; }
|
||||
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_float(float d)
|
||||
{ _pack_float(m_stream, d); return *this; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_double(double d)
|
||||
{ _pack_double(m_stream, d); return *this; }
|
||||
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_nil()
|
||||
{ _pack_nil(m_stream); return *this; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_true()
|
||||
{ _pack_true(m_stream); return *this; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_false()
|
||||
{ _pack_false(m_stream); return *this; }
|
||||
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_array(unsigned int n)
|
||||
{ _pack_array(m_stream, n); return *this; }
|
||||
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_map(unsigned int n)
|
||||
{ _pack_map(m_stream, n); return *this; }
|
||||
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_raw(size_t l)
|
||||
{ _pack_raw(m_stream, l); return *this; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& packer<Stream>::pack_raw_body(const char* b, size_t l)
|
||||
{ _pack_raw_body(m_stream, b, l); return *this; }
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/pack.hpp */
|
||||
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
preprocess() {
|
||||
ruby -r erb -e 'puts ERB.new(ARGF.read).result' $1.erb > $1.tmp
|
||||
if [ "$?" != 0 ]; then
|
||||
echo ""
|
||||
echo "** preprocess failed **"
|
||||
echo ""
|
||||
else
|
||||
mv $1.tmp $1
|
||||
fi
|
||||
}
|
||||
|
||||
preprocess msgpack/type/tuple.hpp
|
||||
preprocess msgpack/type/define.hpp
|
||||
preprocess msgpack/zone.hpp
|
||||
|
||||
103
cpp/sbuffer.hpp
103
cpp/sbuffer.hpp
|
|
@ -1,103 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ simple buffer implementation
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_SBUFFER_HPP__
|
||||
#define MSGPACK_SBUFFER_HPP__
|
||||
|
||||
#include "msgpack/sbuffer.h"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
class sbuffer : public msgpack_sbuffer {
|
||||
public:
|
||||
sbuffer(size_t initsz = MSGPACK_SBUFFER_INIT_SIZE)
|
||||
{
|
||||
base::data = (char*)::malloc(initsz);
|
||||
if(!base::data) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
base::size = 0;
|
||||
base::alloc = initsz;
|
||||
}
|
||||
|
||||
~sbuffer()
|
||||
{
|
||||
::free(base::data);
|
||||
}
|
||||
|
||||
public:
|
||||
void write(const char* buf, unsigned int len)
|
||||
{
|
||||
if(base::alloc - base::size < len) {
|
||||
expand_buffer(len);
|
||||
}
|
||||
memcpy(base::data + base::size, buf, len);
|
||||
base::size += len;
|
||||
}
|
||||
|
||||
char* data()
|
||||
{
|
||||
return base::data;
|
||||
}
|
||||
|
||||
const char* data() const
|
||||
{
|
||||
return base::data;
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return base::size;
|
||||
}
|
||||
|
||||
char* release()
|
||||
{
|
||||
return msgpack_sbuffer_release(this);
|
||||
}
|
||||
|
||||
private:
|
||||
void expand_buffer(size_t len)
|
||||
{
|
||||
size_t nsize = (base::alloc) ?
|
||||
base::alloc * 2 : MSGPACK_SBUFFER_INIT_SIZE;
|
||||
|
||||
while(nsize < base::size + len) { nsize *= 2; }
|
||||
|
||||
void* tmp = realloc(base::data, nsize);
|
||||
if(!tmp) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
base::data = (char*)tmp;
|
||||
base::alloc = nsize;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef msgpack_sbuffer base;
|
||||
|
||||
private:
|
||||
sbuffer(const sbuffer&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/sbuffer.hpp */
|
||||
|
||||
792
cpp/test.cpp
792
cpp/test.cpp
|
|
@ -1,792 +0,0 @@
|
|||
#include "msgpack.hpp"
|
||||
|
||||
#include <math.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
#include <list>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
const unsigned int kLoop = 10000;
|
||||
const unsigned int kElements = 100;
|
||||
const double kEPS = 1e-10;
|
||||
|
||||
#define GEN_TEST(test_type) \
|
||||
do { \
|
||||
vector<test_type> v; \
|
||||
v.push_back(0); \
|
||||
v.push_back(1); \
|
||||
v.push_back(2); \
|
||||
v.push_back(numeric_limits<test_type>::min()); \
|
||||
v.push_back(numeric_limits<test_type>::max()); \
|
||||
for (unsigned int i = 0; i < kLoop; i++) \
|
||||
v.push_back(rand()); \
|
||||
for (unsigned int i = 0; i < v.size() ; i++) { \
|
||||
msgpack::sbuffer sbuf; \
|
||||
test_type val1 = v[i]; \
|
||||
msgpack::pack(sbuf, val1); \
|
||||
msgpack::zone z; \
|
||||
msgpack::object obj; \
|
||||
msgpack::unpack_return ret = \
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj); \
|
||||
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret); \
|
||||
test_type val2; \
|
||||
obj.convert(&val2); \
|
||||
EXPECT_EQ(val1, val2); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
TEST(MSGPACK, simple_buffer_short)
|
||||
{
|
||||
GEN_TEST(short);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_int)
|
||||
{
|
||||
GEN_TEST(int);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_long)
|
||||
{
|
||||
GEN_TEST(long);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_long_long)
|
||||
{
|
||||
GEN_TEST(long long);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_unsigned_short)
|
||||
{
|
||||
GEN_TEST(unsigned short);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_unsigned_int)
|
||||
{
|
||||
GEN_TEST(unsigned int);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_unsigned_long)
|
||||
{
|
||||
GEN_TEST(unsigned long);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_unsigned_long_long)
|
||||
{
|
||||
GEN_TEST(unsigned long long);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_uint8)
|
||||
{
|
||||
GEN_TEST(uint8_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_uint16)
|
||||
{
|
||||
GEN_TEST(uint16_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_uint32)
|
||||
{
|
||||
GEN_TEST(uint32_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_uint64)
|
||||
{
|
||||
GEN_TEST(uint64_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_int8)
|
||||
{
|
||||
GEN_TEST(int8_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_int16)
|
||||
{
|
||||
GEN_TEST(int16_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_int32)
|
||||
{
|
||||
GEN_TEST(int32_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_int64)
|
||||
{
|
||||
GEN_TEST(int64_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_float)
|
||||
{
|
||||
vector<float> v;
|
||||
v.push_back(0.0);
|
||||
v.push_back(-0.0);
|
||||
v.push_back(1.0);
|
||||
v.push_back(-1.0);
|
||||
v.push_back(numeric_limits<float>::min());
|
||||
v.push_back(numeric_limits<float>::max());
|
||||
v.push_back(nanf("tag"));
|
||||
v.push_back(1.0/0.0); // inf
|
||||
v.push_back(-(1.0/0.0)); // -inf
|
||||
for (unsigned int i = 0; i < kLoop; i++) {
|
||||
v.push_back(drand48());
|
||||
v.push_back(-drand48());
|
||||
}
|
||||
for (unsigned int i = 0; i < v.size() ; i++) {
|
||||
msgpack::sbuffer sbuf;
|
||||
float val1 = v[i];
|
||||
msgpack::pack(sbuf, val1);
|
||||
msgpack::zone z;
|
||||
msgpack::object obj;
|
||||
msgpack::unpack_return ret =
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
|
||||
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
|
||||
float val2;
|
||||
obj.convert(&val2);
|
||||
|
||||
if (isnan(val1))
|
||||
EXPECT_TRUE(isnan(val2));
|
||||
else if (isinf(val1))
|
||||
EXPECT_TRUE(isinf(val2));
|
||||
else
|
||||
EXPECT_TRUE(fabs(val2 - val1) <= kEPS);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_double)
|
||||
{
|
||||
vector<double> v;
|
||||
v.push_back(0.0);
|
||||
v.push_back(-0.0);
|
||||
v.push_back(1.0);
|
||||
v.push_back(-1.0);
|
||||
v.push_back(numeric_limits<double>::min());
|
||||
v.push_back(numeric_limits<double>::max());
|
||||
v.push_back(nanf("tag"));
|
||||
v.push_back(1.0/0.0); // inf
|
||||
v.push_back(-(1.0/0.0)); // -inf
|
||||
for (unsigned int i = 0; i < kLoop; i++) {
|
||||
v.push_back(drand48());
|
||||
v.push_back(-drand48());
|
||||
}
|
||||
for (unsigned int i = 0; i < v.size() ; i++) {
|
||||
msgpack::sbuffer sbuf;
|
||||
double val1 = v[i];
|
||||
msgpack::pack(sbuf, val1);
|
||||
msgpack::zone z;
|
||||
msgpack::object obj;
|
||||
msgpack::unpack_return ret =
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
|
||||
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
|
||||
double val2;
|
||||
obj.convert(&val2);
|
||||
|
||||
if (isnan(val1))
|
||||
EXPECT_TRUE(isnan(val2));
|
||||
else if (isinf(val1))
|
||||
EXPECT_TRUE(isinf(val2));
|
||||
else
|
||||
EXPECT_TRUE(fabs(val2 - val1) <= kEPS);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_true)
|
||||
{
|
||||
msgpack::sbuffer sbuf;
|
||||
bool val1 = true;
|
||||
msgpack::pack(sbuf, val1);
|
||||
msgpack::zone z;
|
||||
msgpack::object obj;
|
||||
msgpack::unpack_return ret =
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
|
||||
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
|
||||
bool val2;
|
||||
obj.convert(&val2);
|
||||
EXPECT_EQ(val1, val2);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_false)
|
||||
{
|
||||
msgpack::sbuffer sbuf;
|
||||
bool val1 = false;
|
||||
msgpack::pack(sbuf, val1);
|
||||
msgpack::zone z;
|
||||
msgpack::object obj;
|
||||
msgpack::unpack_return ret =
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
|
||||
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
|
||||
bool val2;
|
||||
obj.convert(&val2);
|
||||
EXPECT_EQ(val1, val2);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
TEST(MSGPACK_STL, simple_buffer_string)
|
||||
{
|
||||
for (unsigned int k = 0; k < kLoop; k++) {
|
||||
string val1;
|
||||
for (unsigned int i = 0; i < kElements; i++)
|
||||
val1 += 'a' + rand() % 26;
|
||||
msgpack::sbuffer sbuf;
|
||||
msgpack::pack(sbuf, val1);
|
||||
msgpack::zone z;
|
||||
msgpack::object obj;
|
||||
msgpack::unpack_return ret =
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
|
||||
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
|
||||
string val2;
|
||||
obj.convert(&val2);
|
||||
EXPECT_EQ(val1.size(), val2.size());
|
||||
EXPECT_EQ(val1, val2);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MSGPACK_STL, simple_buffer_vector)
|
||||
{
|
||||
for (unsigned int k = 0; k < kLoop; k++) {
|
||||
vector<int> val1;
|
||||
for (unsigned int i = 0; i < kElements; i++)
|
||||
val1.push_back(rand());
|
||||
msgpack::sbuffer sbuf;
|
||||
msgpack::pack(sbuf, val1);
|
||||
msgpack::zone z;
|
||||
msgpack::object obj;
|
||||
msgpack::unpack_return ret =
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
|
||||
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
|
||||
vector<int> val2;
|
||||
obj.convert(&val2);
|
||||
EXPECT_EQ(val1.size(), val2.size());
|
||||
EXPECT_TRUE(equal(val1.begin(), val1.end(), val2.begin()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MSGPACK_STL, simple_buffer_map)
|
||||
{
|
||||
for (unsigned int k = 0; k < kLoop; k++) {
|
||||
map<int, int> val1;
|
||||
for (unsigned int i = 0; i < kElements; i++)
|
||||
val1[rand()] = rand();
|
||||
msgpack::sbuffer sbuf;
|
||||
msgpack::pack(sbuf, val1);
|
||||
msgpack::zone z;
|
||||
msgpack::object obj;
|
||||
msgpack::unpack_return ret =
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
|
||||
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
|
||||
map<int, int> val2;
|
||||
obj.convert(&val2);
|
||||
EXPECT_EQ(val1.size(), val2.size());
|
||||
EXPECT_TRUE(equal(val1.begin(), val1.end(), val2.begin()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MSGPACK_STL, simple_buffer_deque)
|
||||
{
|
||||
for (unsigned int k = 0; k < kLoop; k++) {
|
||||
deque<int> val1;
|
||||
for (unsigned int i = 0; i < kElements; i++)
|
||||
val1.push_back(rand());
|
||||
msgpack::sbuffer sbuf;
|
||||
msgpack::pack(sbuf, val1);
|
||||
msgpack::zone z;
|
||||
msgpack::object obj;
|
||||
msgpack::unpack_return ret =
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
|
||||
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
|
||||
deque<int> val2;
|
||||
obj.convert(&val2);
|
||||
EXPECT_EQ(val1.size(), val2.size());
|
||||
EXPECT_TRUE(equal(val1.begin(), val1.end(), val2.begin()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MSGPACK_STL, simple_buffer_list)
|
||||
{
|
||||
for (unsigned int k = 0; k < kLoop; k++) {
|
||||
list<int> val1;
|
||||
for (unsigned int i = 0; i < kElements; i++)
|
||||
val1.push_back(rand());
|
||||
msgpack::sbuffer sbuf;
|
||||
msgpack::pack(sbuf, val1);
|
||||
msgpack::zone z;
|
||||
msgpack::object obj;
|
||||
msgpack::unpack_return ret =
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
|
||||
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
|
||||
list<int> val2;
|
||||
obj.convert(&val2);
|
||||
EXPECT_EQ(val1.size(), val2.size());
|
||||
EXPECT_TRUE(equal(val1.begin(), val1.end(), val2.begin()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MSGPACK_STL, simple_buffer_set)
|
||||
{
|
||||
for (unsigned int k = 0; k < kLoop; k++) {
|
||||
set<int> val1;
|
||||
for (unsigned int i = 0; i < kElements; i++)
|
||||
val1.insert(rand());
|
||||
msgpack::sbuffer sbuf;
|
||||
msgpack::pack(sbuf, val1);
|
||||
msgpack::zone z;
|
||||
msgpack::object obj;
|
||||
msgpack::unpack_return ret =
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
|
||||
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
|
||||
set<int> val2;
|
||||
obj.convert(&val2);
|
||||
EXPECT_EQ(val1.size(), val2.size());
|
||||
EXPECT_TRUE(equal(val1.begin(), val1.end(), val2.begin()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MSGPACK_STL, simple_buffer_pair)
|
||||
{
|
||||
for (unsigned int k = 0; k < kLoop; k++) {
|
||||
pair<int, int> val1 = make_pair(rand(), rand());
|
||||
msgpack::sbuffer sbuf;
|
||||
msgpack::pack(sbuf, val1);
|
||||
msgpack::zone z;
|
||||
msgpack::object obj;
|
||||
msgpack::unpack_return ret =
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
|
||||
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
|
||||
pair<int, int> val2;
|
||||
obj.convert(&val2);
|
||||
EXPECT_EQ(val1.first, val2.first);
|
||||
EXPECT_EQ(val1.second, val2.second);
|
||||
}
|
||||
}
|
||||
|
||||
class TestClass
|
||||
{
|
||||
public:
|
||||
TestClass() : i(0), s("kzk") {}
|
||||
int i;
|
||||
string s;
|
||||
MSGPACK_DEFINE(i, s);
|
||||
};
|
||||
|
||||
TEST(MSGPACK_USER_DEFINED, simple_buffer_class)
|
||||
{
|
||||
for (unsigned int k = 0; k < kLoop; k++) {
|
||||
TestClass val1;
|
||||
msgpack::sbuffer sbuf;
|
||||
msgpack::pack(sbuf, val1);
|
||||
msgpack::zone z;
|
||||
msgpack::object obj;
|
||||
msgpack::unpack_return ret =
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
|
||||
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
|
||||
TestClass val2;
|
||||
val2.i = -1;
|
||||
val2.s = "";
|
||||
obj.convert(&val2);
|
||||
EXPECT_EQ(val1.i, val2.i);
|
||||
EXPECT_EQ(val1.s, val2.s);
|
||||
}
|
||||
}
|
||||
|
||||
class TestClass2
|
||||
{
|
||||
public:
|
||||
TestClass2() : i(0), s("kzk") {
|
||||
for (unsigned int i = 0; i < kElements; i++)
|
||||
v.push_back(rand());
|
||||
}
|
||||
int i;
|
||||
string s;
|
||||
vector<int> v;
|
||||
MSGPACK_DEFINE(i, s, v);
|
||||
};
|
||||
|
||||
TEST(MSGPACK_USER_DEFINED, simple_buffer_class_old_to_new)
|
||||
{
|
||||
for (unsigned int k = 0; k < kLoop; k++) {
|
||||
TestClass val1;
|
||||
msgpack::sbuffer sbuf;
|
||||
msgpack::pack(sbuf, val1);
|
||||
msgpack::zone z;
|
||||
msgpack::object obj;
|
||||
msgpack::unpack_return ret =
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
|
||||
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
|
||||
TestClass2 val2;
|
||||
val2.i = -1;
|
||||
val2.s = "";
|
||||
val2.v = vector<int>();
|
||||
obj.convert(&val2);
|
||||
EXPECT_EQ(val1.i, val2.i);
|
||||
EXPECT_EQ(val1.s, val2.s);
|
||||
EXPECT_FALSE(val2.s.empty());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MSGPACK_USER_DEFINED, simple_buffer_class_new_to_old)
|
||||
{
|
||||
for (unsigned int k = 0; k < kLoop; k++) {
|
||||
TestClass2 val1;
|
||||
msgpack::sbuffer sbuf;
|
||||
msgpack::pack(sbuf, val1);
|
||||
msgpack::zone z;
|
||||
msgpack::object obj;
|
||||
msgpack::unpack_return ret =
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
|
||||
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
|
||||
TestClass val2;
|
||||
val2.i = -1;
|
||||
val2.s = "";
|
||||
obj.convert(&val2);
|
||||
EXPECT_EQ(val1.i, val2.i);
|
||||
EXPECT_EQ(val1.s, val2.s);
|
||||
EXPECT_FALSE(val2.s.empty());
|
||||
}
|
||||
}
|
||||
|
||||
class TestEnumMemberClass
|
||||
{
|
||||
public:
|
||||
TestEnumMemberClass()
|
||||
: t1(STATE_A), t2(STATE_B), t3(STATE_C) {}
|
||||
|
||||
enum TestEnumType {
|
||||
STATE_INVALID = 0,
|
||||
STATE_A = 1,
|
||||
STATE_B = 2,
|
||||
STATE_C = 3
|
||||
};
|
||||
TestEnumType t1;
|
||||
TestEnumType t2;
|
||||
TestEnumType t3;
|
||||
|
||||
MSGPACK_DEFINE((int&)t1, (int&)t2, (int&)t3);
|
||||
};
|
||||
|
||||
TEST(MSGPACK_USER_DEFINED, simple_buffer_enum_member)
|
||||
{
|
||||
TestEnumMemberClass val1;
|
||||
msgpack::sbuffer sbuf;
|
||||
msgpack::pack(sbuf, val1);
|
||||
msgpack::zone z;
|
||||
msgpack::object obj;
|
||||
msgpack::unpack_return ret =
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
|
||||
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
|
||||
TestEnumMemberClass val2;
|
||||
val2.t1 = TestEnumMemberClass::STATE_INVALID;
|
||||
val2.t2 = TestEnumMemberClass::STATE_INVALID;
|
||||
val2.t3 = TestEnumMemberClass::STATE_INVALID;
|
||||
obj.convert(&val2);
|
||||
EXPECT_EQ(val1.t1, val2.t1);
|
||||
EXPECT_EQ(val1.t2, val2.t2);
|
||||
EXPECT_EQ(val1.t3, val2.t3);
|
||||
}
|
||||
|
||||
class TestUnionMemberClass
|
||||
{
|
||||
public:
|
||||
TestUnionMemberClass() {}
|
||||
TestUnionMemberClass(double f) {
|
||||
is_double = true;
|
||||
value.f = f;
|
||||
}
|
||||
TestUnionMemberClass(int i) {
|
||||
is_double = false;
|
||||
value.i = i;
|
||||
}
|
||||
|
||||
union {
|
||||
double f;
|
||||
int i;
|
||||
} value;
|
||||
bool is_double;
|
||||
|
||||
template <typename Packer>
|
||||
void msgpack_pack(Packer& pk) const
|
||||
{
|
||||
if (is_double)
|
||||
pk.pack(msgpack::type::tuple<bool, double>(true, value.f));
|
||||
else
|
||||
pk.pack(msgpack::type::tuple<bool, int>(false, value.i));
|
||||
}
|
||||
|
||||
void msgpack_unpack(msgpack::object o)
|
||||
{
|
||||
msgpack::type::tuple<bool, msgpack::object> tuple;
|
||||
o.convert(&tuple);
|
||||
|
||||
is_double = tuple.get<0>();
|
||||
if (is_double)
|
||||
tuple.get<1>().convert(&value.f);
|
||||
else
|
||||
tuple.get<1>().convert(&value.i);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(MSGPACK_USER_DEFINED, simple_buffer_union_member)
|
||||
{
|
||||
{
|
||||
// double
|
||||
TestUnionMemberClass val1(1.0);
|
||||
msgpack::sbuffer sbuf;
|
||||
msgpack::pack(sbuf, val1);
|
||||
msgpack::zone z;
|
||||
msgpack::object obj;
|
||||
msgpack::unpack_return ret =
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
|
||||
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
|
||||
TestUnionMemberClass val2;
|
||||
obj.convert(&val2);
|
||||
EXPECT_EQ(val1.is_double, val2.is_double);
|
||||
EXPECT_TRUE(fabs(val1.value.f - val2.value.f) < kEPS);
|
||||
}
|
||||
{
|
||||
// int
|
||||
TestUnionMemberClass val1(1);
|
||||
msgpack::sbuffer sbuf;
|
||||
msgpack::pack(sbuf, val1);
|
||||
msgpack::zone z;
|
||||
msgpack::object obj;
|
||||
msgpack::unpack_return ret =
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
|
||||
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
|
||||
TestUnionMemberClass val2;
|
||||
obj.convert(&val2);
|
||||
EXPECT_EQ(val1.is_double, val2.is_double);
|
||||
EXPECT_EQ(val1.value.i, 1);
|
||||
EXPECT_EQ(val1.value.i, val2.value.i);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define GEN_TEST_VREF(test_type) \
|
||||
do { \
|
||||
vector<test_type> v; \
|
||||
v.push_back(0); \
|
||||
for (unsigned int i = 0; i < v.size(); i++) { \
|
||||
test_type val1 = v[i]; \
|
||||
msgpack::vrefbuffer vbuf; \
|
||||
msgpack::pack(vbuf, val1); \
|
||||
msgpack::sbuffer sbuf; \
|
||||
const struct iovec* cur = vbuf.vector(); \
|
||||
const struct iovec* end = cur + vbuf.vector_size(); \
|
||||
for(; cur != end; ++cur) \
|
||||
sbuf.write((const char*)cur->iov_base, cur->iov_len); \
|
||||
msgpack::zone z; \
|
||||
msgpack::object obj; \
|
||||
msgpack::unpack_return ret = \
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj); \
|
||||
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret); \
|
||||
test_type val2; \
|
||||
obj.convert(&val2); \
|
||||
EXPECT_EQ(val1, val2); \
|
||||
} \
|
||||
} while(0);
|
||||
|
||||
TEST(MSGPACK, vrefbuffer_short)
|
||||
{
|
||||
GEN_TEST_VREF(short);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, vrefbuffer_int)
|
||||
{
|
||||
GEN_TEST_VREF(int);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, vrefbuffer_long)
|
||||
{
|
||||
GEN_TEST_VREF(long);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, vrefbuffer_long_long)
|
||||
{
|
||||
GEN_TEST_VREF(long long);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, vrefbuffer_unsigned_short)
|
||||
{
|
||||
GEN_TEST_VREF(unsigned short);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, vrefbuffer_unsigned_int)
|
||||
{
|
||||
GEN_TEST_VREF(unsigned int);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, vrefbuffer_unsigned_long)
|
||||
{
|
||||
GEN_TEST_VREF(unsigned long);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, vrefbuffer_unsigned_long_long)
|
||||
{
|
||||
GEN_TEST_VREF(unsigned long long);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, vrefbuffer_uint8)
|
||||
{
|
||||
GEN_TEST_VREF(uint8_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, vrefbuffer_uint16)
|
||||
{
|
||||
GEN_TEST_VREF(uint16_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, vrefbuffer_uint32)
|
||||
{
|
||||
GEN_TEST_VREF(uint32_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, vrefbuffer_uint64)
|
||||
{
|
||||
GEN_TEST_VREF(uint64_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, vrefbuffer_int8)
|
||||
{
|
||||
GEN_TEST_VREF(int8_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, vrefbuffer_int16)
|
||||
{
|
||||
GEN_TEST_VREF(int16_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, vrefbuffer_int32)
|
||||
{
|
||||
GEN_TEST_VREF(int32_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, vrefbuffer_int64)
|
||||
{
|
||||
GEN_TEST_VREF(int64_t);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define GEN_TEST_STREAM(test_type) \
|
||||
for (unsigned int k = 0; k < kLoop; k++) { \
|
||||
msgpack::sbuffer sbuf; \
|
||||
msgpack::packer<msgpack::sbuffer> pk(sbuf); \
|
||||
typedef std::vector<test_type> vec_type; \
|
||||
vec_type vec; \
|
||||
for(unsigned int i = 0; i < rand() % kLoop; ++i) { \
|
||||
vec_type::value_type r = rand(); \
|
||||
vec.push_back(r); \
|
||||
pk.pack(r); \
|
||||
} \
|
||||
msgpack::unpacker pac; \
|
||||
vec_type::const_iterator it = vec.begin(); \
|
||||
const char *p = sbuf.data(); \
|
||||
const char * const pend = p + sbuf.size(); \
|
||||
while (p < pend) { \
|
||||
const size_t sz = std::min<size_t>(pend - p, rand() % 128); \
|
||||
pac.reserve_buffer(sz); \
|
||||
memcpy(pac.buffer(), p, sz); \
|
||||
pac.buffer_consumed(sz); \
|
||||
while (pac.execute()) { \
|
||||
if (it == vec.end()) goto out; \
|
||||
msgpack::object obj = pac.data(); \
|
||||
msgpack::zone *life = pac.release_zone(); \
|
||||
EXPECT_TRUE(life != NULL); \
|
||||
pac.reset(); \
|
||||
vec_type::value_type val; \
|
||||
obj.convert(&val); \
|
||||
EXPECT_EQ(*it, val); \
|
||||
++it; \
|
||||
delete life; \
|
||||
} \
|
||||
p += sz; \
|
||||
} \
|
||||
out: \
|
||||
; \
|
||||
}
|
||||
|
||||
TEST(MSGPACK, stream_short)
|
||||
{
|
||||
GEN_TEST_STREAM(short);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, stream_int)
|
||||
{
|
||||
GEN_TEST_STREAM(int);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, stream_long)
|
||||
{
|
||||
GEN_TEST_STREAM(long);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, stream_long_long)
|
||||
{
|
||||
GEN_TEST_STREAM(long long);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, stream_unsigned_short)
|
||||
{
|
||||
GEN_TEST_STREAM(unsigned short);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, stream_unsigned_int)
|
||||
{
|
||||
GEN_TEST_STREAM(unsigned int);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, stream_unsigned_long)
|
||||
{
|
||||
GEN_TEST_STREAM(unsigned long);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, stream_unsigned_long_long)
|
||||
{
|
||||
GEN_TEST_STREAM(unsigned long long);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, stream_uint8)
|
||||
{
|
||||
GEN_TEST_STREAM(uint8_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, stream_uint16)
|
||||
{
|
||||
GEN_TEST_STREAM(uint16_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, stream_uint32)
|
||||
{
|
||||
GEN_TEST_STREAM(uint32_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, stream_uint64)
|
||||
{
|
||||
GEN_TEST_STREAM(uint64_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, stream_int8)
|
||||
{
|
||||
GEN_TEST_STREAM(int8_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, stream_int16)
|
||||
{
|
||||
GEN_TEST_STREAM(int16_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, stream_int32)
|
||||
{
|
||||
GEN_TEST_STREAM(int32_t);
|
||||
}
|
||||
|
||||
TEST(MSGPACK, stream_int64)
|
||||
{
|
||||
GEN_TEST_STREAM(int64_t);
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
|
||||
CXXFLAGS += -Wall -g -I. -I.. -O4
|
||||
LDFLAGS +=
|
||||
|
||||
all: test
|
||||
|
||||
test: test.o unpack.o zone.o object.o pack.hpp unpack.hpp zone.hpp object.hpp
|
||||
$(CXX) test.o unpack.o zone.o object.o $(CXXFLAGS) $(LDFLAGS) -o $@
|
||||
|
||||
15
cpp/type.hpp
15
cpp/type.hpp
|
|
@ -1,15 +0,0 @@
|
|||
#include "msgpack/type/bool.hpp"
|
||||
#include "msgpack/type/float.hpp"
|
||||
#include "msgpack/type/int.hpp"
|
||||
#include "msgpack/type/list.hpp"
|
||||
#include "msgpack/type/deque.hpp"
|
||||
#include "msgpack/type/map.hpp"
|
||||
#include "msgpack/type/nil.hpp"
|
||||
#include "msgpack/type/pair.hpp"
|
||||
#include "msgpack/type/raw.hpp"
|
||||
#include "msgpack/type/set.hpp"
|
||||
#include "msgpack/type/string.hpp"
|
||||
#include "msgpack/type/vector.hpp"
|
||||
#include "msgpack/type/tuple.hpp"
|
||||
#include "msgpack/type/define.hpp"
|
||||
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_TYPE_BOOL_HPP__
|
||||
#define MSGPACK_TYPE_BOOL_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
inline bool& operator>> (object o, bool& v)
|
||||
{
|
||||
if(o.type != type::BOOLEAN) { throw type_error(); }
|
||||
v = o.via.boolean;
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const bool& v)
|
||||
{
|
||||
if(v) { o.pack_true(); }
|
||||
else { o.pack_false(); }
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/bool.hpp */
|
||||
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_TYPE_DEFINE_HPP__
|
||||
#define MSGPACK_TYPE_DEFINE_HPP__
|
||||
|
||||
#define MSGPACK_DEFINE(...) \
|
||||
template <typename Packer> \
|
||||
void msgpack_pack(Packer& pk) const \
|
||||
{ \
|
||||
msgpack::type::make_define(__VA_ARGS__).msgpack_pack(pk); \
|
||||
} \
|
||||
void msgpack_unpack(msgpack::object o) \
|
||||
{ \
|
||||
msgpack::type::make_define(__VA_ARGS__).msgpack_unpack(o); \
|
||||
}
|
||||
|
||||
namespace msgpack {
|
||||
namespace type {
|
||||
|
||||
|
||||
<% GENERATION_LIMIT = 31 %>
|
||||
template <typename A0 = void<%1.upto(GENERATION_LIMIT+1) {|i|%>, typename A<%=i%> = void<%}%>>
|
||||
struct define;
|
||||
|
||||
|
||||
template <>
|
||||
struct define<> {
|
||||
typedef define<> value_type;
|
||||
typedef tuple<> tuple_type;
|
||||
template <typename Packer>
|
||||
void msgpack_pack(Packer& pk) const
|
||||
{
|
||||
pk.pack_array(1);
|
||||
}
|
||||
void msgpack_unpack(msgpack::object o)
|
||||
{
|
||||
if(o.type != type::ARRAY) { throw type_error(); }
|
||||
}
|
||||
};
|
||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||
template <typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
|
||||
struct define<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> {
|
||||
typedef define<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> value_type;
|
||||
typedef tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> tuple_type;
|
||||
define(A0& _a0<%1.upto(i) {|j|%>, A<%=j%>& _a<%=j%><%}%>) :
|
||||
a0(_a0)<%1.upto(i) {|j|%>, a<%=j%>(_a<%=j%>)<%}%> {}
|
||||
template <typename Packer>
|
||||
void msgpack_pack(Packer& pk) const
|
||||
{
|
||||
pk.pack_array(<%=i+1%>);
|
||||
<%0.upto(i) {|j|%>
|
||||
pk.pack(a<%=j%>);<%}%>
|
||||
}
|
||||
void msgpack_unpack(msgpack::object o)
|
||||
{
|
||||
if(o.type != type::ARRAY) { throw type_error(); }
|
||||
const size_t size = o.via.array.size;
|
||||
<%0.upto(i) {|j|%>
|
||||
if(size <= <%=j%>) { return; } o.via.array.ptr[<%=j%>].convert(&a<%=j%>);<%}%>
|
||||
}
|
||||
<%0.upto(i) {|j|%>
|
||||
A<%=j%>& a<%=j%>;<%}%>
|
||||
};
|
||||
<%}%>
|
||||
|
||||
inline define<> make_define()
|
||||
{
|
||||
return define<>();
|
||||
}
|
||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||
template <typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
|
||||
define<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> make_define(A0& a0<%1.upto(i) {|j|%>, A<%=j%>& a<%=j%><%}%>)
|
||||
{
|
||||
return define<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>>(a0<%1.upto(i) {|j|%>, a<%=j%><%}%>);
|
||||
}
|
||||
<%}%>
|
||||
|
||||
} // namespace type
|
||||
} // namespace msgpack
|
||||
|
||||
|
||||
#endif /* msgpack/type/define.hpp */
|
||||
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_TYPE_DEQUE_HPP__
|
||||
#define MSGPACK_TYPE_DEQUE_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include <deque>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
template <typename T>
|
||||
inline std::deque<T>& operator>> (object o, std::deque<T>& v)
|
||||
{
|
||||
if(o.type != type::ARRAY) { throw type_error(); }
|
||||
v.resize(o.via.array.size);
|
||||
object* p = o.via.array.ptr;
|
||||
object* const pend = o.via.array.ptr + o.via.array.size;
|
||||
typename std::deque<T>::iterator it = v.begin();
|
||||
for(; p < pend; ++p, ++it) {
|
||||
p->convert(&*it);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Stream, typename T>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const std::deque<T>& v)
|
||||
{
|
||||
o.pack_array(v.size());
|
||||
for(typename std::deque<T>::const_iterator it(v.begin()), it_end(v.end());
|
||||
it != it_end; ++it) {
|
||||
o.pack(*it);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/deque.hpp */
|
||||
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_TYPE_FLOAT_HPP__
|
||||
#define MSGPACK_TYPE_FLOAT_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
// FIXME check overflow, underflow
|
||||
|
||||
|
||||
inline float& operator>> (object o, float& v)
|
||||
{
|
||||
if(o.type != type::DOUBLE) { throw type_error(); }
|
||||
v = o.via.dec;
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const float& v)
|
||||
{
|
||||
o.pack_float(v);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
inline double& operator>> (object o, double& v)
|
||||
{
|
||||
if(o.type != type::DOUBLE) { throw type_error(); }
|
||||
v = o.via.dec;
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const double& v)
|
||||
{
|
||||
o.pack_double(v);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/float.hpp */
|
||||
|
||||
147
cpp/type/int.hpp
147
cpp/type/int.hpp
|
|
@ -1,147 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_TYPE_INT_HPP__
|
||||
#define MSGPACK_TYPE_INT_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include <limits>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
namespace type {
|
||||
namespace detail {
|
||||
template <typename T, bool Signed>
|
||||
struct convert_integer_sign;
|
||||
|
||||
template <typename T>
|
||||
struct convert_integer_sign<T, true> {
|
||||
static inline T convert(object o) {
|
||||
if(o.type == type::POSITIVE_INTEGER) {
|
||||
if(o.via.u64 > (uint64_t)std::numeric_limits<T>::max())
|
||||
{ throw type_error(); }
|
||||
return o.via.u64;
|
||||
} else if(o.type == type::NEGATIVE_INTEGER) {
|
||||
if(o.via.i64 < (int64_t)std::numeric_limits<T>::min())
|
||||
{ throw type_error(); }
|
||||
return o.via.i64;
|
||||
}
|
||||
throw type_error();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct convert_integer_sign<T, false> {
|
||||
static inline T convert(object o) {
|
||||
if(o.type == type::POSITIVE_INTEGER) {
|
||||
if(o.via.u64 > (uint64_t)std::numeric_limits<T>::max())
|
||||
{ throw type_error(); }
|
||||
return o.via.u64;
|
||||
}
|
||||
throw type_error();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
static inline T convert_integer(object o)
|
||||
{
|
||||
return detail::convert_integer_sign<T, std::numeric_limits<T>::is_signed>::convert(o);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace type
|
||||
|
||||
|
||||
inline signed char& operator>> (object o, signed char& v)
|
||||
{ v = type::detail::convert_integer<signed char>(o); return v; }
|
||||
|
||||
inline signed short& operator>> (object o, signed short& v)
|
||||
{ v = type::detail::convert_integer<signed short>(o); return v; }
|
||||
|
||||
inline signed int& operator>> (object o, signed int& v)
|
||||
{ v = type::detail::convert_integer<signed int>(o); return v; }
|
||||
|
||||
inline signed long& operator>> (object o, signed long& v)
|
||||
{ v = type::detail::convert_integer<signed long>(o); return v; }
|
||||
|
||||
inline signed long long& operator>> (object o, signed long long& v)
|
||||
{ v = type::detail::convert_integer<signed long long>(o); return v; }
|
||||
|
||||
|
||||
inline unsigned char& operator>> (object o, unsigned char& v)
|
||||
{ v = type::detail::convert_integer<unsigned char>(o); return v; }
|
||||
|
||||
inline unsigned short& operator>> (object o, unsigned short& v)
|
||||
{ v = type::detail::convert_integer<unsigned short>(o); return v; }
|
||||
|
||||
inline unsigned int& operator>> (object o, unsigned int& v)
|
||||
{ v = type::detail::convert_integer<unsigned int>(o); return v; }
|
||||
|
||||
inline unsigned long& operator>> (object o, unsigned long& v)
|
||||
{ v = type::detail::convert_integer<unsigned long>(o); return v; }
|
||||
|
||||
inline unsigned long long& operator>> (object o, unsigned long long& v)
|
||||
{ v = type::detail::convert_integer<unsigned long long>(o); return v; }
|
||||
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const signed char& v)
|
||||
{ o.pack_int8(v); return o; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const signed short& v)
|
||||
{ o.pack_short(v); return o; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const signed int& v)
|
||||
{ o.pack_int(v); return o; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const signed long& v)
|
||||
{ o.pack_long(v); return o; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const signed long long& v)
|
||||
{ o.pack_long_long(v); return o; }
|
||||
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const unsigned char& v)
|
||||
{ o.pack_uint8(v); return o; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const unsigned short& v)
|
||||
{ o.pack_unsigned_short(v); return o; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const unsigned int& v)
|
||||
{ o.pack_unsigned_int(v); return o; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const unsigned long& v)
|
||||
{ o.pack_unsigned_long(v); return o; }
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const unsigned long long& v)
|
||||
{ o.pack_unsigned_long_long(v); return o; }
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/int.hpp */
|
||||
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_TYPE_LIST_HPP__
|
||||
#define MSGPACK_TYPE_LIST_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include <list>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
template <typename T>
|
||||
inline std::list<T>& operator>> (object o, std::list<T>& v)
|
||||
{
|
||||
if(o.type != type::ARRAY) { throw type_error(); }
|
||||
v.resize(o.via.array.size);
|
||||
object* p = o.via.array.ptr;
|
||||
object* const pend = o.via.array.ptr + o.via.array.size;
|
||||
typename std::list<T>::iterator it = v.begin();
|
||||
for(; p < pend; ++p, ++it) {
|
||||
p->convert(&*it);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Stream, typename T>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const std::list<T>& v)
|
||||
{
|
||||
o.pack_array(v.size());
|
||||
for(typename std::list<T>::const_iterator it(v.begin()), it_end(v.end());
|
||||
it != it_end; ++it) {
|
||||
o.pack(*it);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/list.hpp */
|
||||
|
||||
139
cpp/type/map.hpp
139
cpp/type/map.hpp
|
|
@ -1,139 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_TYPE_MAP_HPP__
|
||||
#define MSGPACK_TYPE_MAP_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
namespace type {
|
||||
|
||||
template <typename K, typename V>
|
||||
class assoc_vector : public std::vector< std::pair<K, V> > {};
|
||||
|
||||
namespace detail {
|
||||
template <typename K, typename V>
|
||||
struct pair_first_less {
|
||||
bool operator() (const std::pair<K, V>& x, const std::pair<K, V>& y) const
|
||||
{ return x.first < y.first; }
|
||||
};
|
||||
}
|
||||
|
||||
} //namespace type
|
||||
|
||||
|
||||
template <typename K, typename V>
|
||||
inline type::assoc_vector<K,V>& operator>> (object o, type::assoc_vector<K,V>& v)
|
||||
{
|
||||
if(o.type != type::MAP) { throw type_error(); }
|
||||
v.resize(o.via.map.size);
|
||||
object_kv* p = o.via.map.ptr;
|
||||
object_kv* const pend = o.via.map.ptr + o.via.map.size;
|
||||
std::pair<K, V>* it(&v.front());
|
||||
for(; p < pend; ++p, ++it) {
|
||||
p->key.convert(&it->first);
|
||||
p->val.convert(&it->second);
|
||||
}
|
||||
std::sort(v.begin(), v.end(), type::detail::pair_first_less<K,V>());
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Stream, typename K, typename V>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const type::assoc_vector<K,V>& v)
|
||||
{
|
||||
o.pack_map(v.size());
|
||||
for(typename type::assoc_vector<K,V>::const_iterator it(v.begin()), it_end(v.end());
|
||||
it != it_end; ++it) {
|
||||
o.pack(it->first);
|
||||
o.pack(it->second);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
template <typename K, typename V>
|
||||
inline std::map<K, V> operator>> (object o, std::map<K, V>& v)
|
||||
{
|
||||
if(o.type != type::MAP) { throw type_error(); }
|
||||
object_kv* p(o.via.map.ptr);
|
||||
object_kv* const pend(o.via.map.ptr + o.via.map.size);
|
||||
for(; p != pend; ++p) {
|
||||
K key;
|
||||
p->key.convert(&key);
|
||||
typename std::map<K,V>::iterator it(v.lower_bound(key));
|
||||
if(it != v.end() && !(key < it->first)) {
|
||||
p->val.convert(&it->second);
|
||||
} else {
|
||||
V val;
|
||||
p->val.convert(&val);
|
||||
v.insert(it, std::pair<K,V>(key, val));
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Stream, typename K, typename V>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const std::map<K,V>& v)
|
||||
{
|
||||
o.pack_map(v.size());
|
||||
for(typename std::map<K,V>::const_iterator it(v.begin()), it_end(v.end());
|
||||
it != it_end; ++it) {
|
||||
o.pack(it->first);
|
||||
o.pack(it->second);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
template <typename K, typename V>
|
||||
inline std::multimap<K, V> operator>> (object o, std::multimap<K, V>& v)
|
||||
{
|
||||
if(o.type != type::MAP) { throw type_error(); }
|
||||
object_kv* p(o.via.map.ptr);
|
||||
object_kv* const pend(o.via.map.ptr + o.via.map.size);
|
||||
for(; p != pend; ++p) {
|
||||
std::pair<K, V> value;
|
||||
p->key.convert(&value.first);
|
||||
p->val.convert(&value.second);
|
||||
v.insert(value);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Stream, typename K, typename V>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const std::multimap<K,V>& v)
|
||||
{
|
||||
o.pack_map(v.size());
|
||||
for(typename std::multimap<K,V>::const_iterator it(v.begin()), it_end(v.end());
|
||||
it != it_end; ++it) {
|
||||
o.pack(it->first);
|
||||
o.pack(it->second);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/map.hpp */
|
||||
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_TYPE_NIL_HPP__
|
||||
#define MSGPACK_TYPE_NIL_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
namespace type {
|
||||
|
||||
struct nil { };
|
||||
|
||||
} // namespace type
|
||||
|
||||
|
||||
inline type::nil& operator>> (object o, type::nil& v)
|
||||
{
|
||||
if(o.type != type::NIL) { throw type_error(); }
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const type::nil& v)
|
||||
{
|
||||
o.pack_nil();
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/nil.hpp */
|
||||
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_TYPE_PAIR_HPP__
|
||||
#define MSGPACK_TYPE_PAIR_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include <utility>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline std::pair<T1, T2>& operator>> (object o, std::pair<T1, T2>& v)
|
||||
{
|
||||
if(o.type != type::ARRAY) { throw type_error(); }
|
||||
if(o.via.array.size != 2) { throw type_error(); }
|
||||
o.via.array.ptr[0].convert(&v.first);
|
||||
o.via.array.ptr[1].convert(&v.second);
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Stream, typename T1, typename T2>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const std::pair<T1, T2>& v)
|
||||
{
|
||||
o.pack_array(2);
|
||||
o.pack(v.first);
|
||||
o.pack(v.second);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/pair.hpp */
|
||||
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_TYPE_RAW_HPP__
|
||||
#define MSGPACK_TYPE_RAW_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
namespace type {
|
||||
|
||||
struct raw_ref {
|
||||
raw_ref() : size(0), ptr(NULL) {}
|
||||
raw_ref(const char* p, uint32_t s) : size(s), ptr(p) {}
|
||||
|
||||
uint32_t size;
|
||||
const char* ptr;
|
||||
|
||||
std::string str() { return std::string(ptr, size); }
|
||||
|
||||
bool operator== (const raw_ref& x)
|
||||
{
|
||||
return size == x.size && memcmp(ptr, x.ptr, size) == 0;
|
||||
}
|
||||
|
||||
bool operator!= (const raw_ref& x)
|
||||
{
|
||||
return !(*this != x);
|
||||
}
|
||||
|
||||
bool operator< (const raw_ref& x)
|
||||
{
|
||||
if(size == x.size) { return memcmp(ptr, x.ptr, size) < 0; }
|
||||
else { return size < x.size; }
|
||||
}
|
||||
|
||||
bool operator> (const raw_ref& x)
|
||||
{
|
||||
if(size == x.size) { return memcmp(ptr, x.ptr, size) > 0; }
|
||||
else { return size > x.size; }
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace type
|
||||
|
||||
|
||||
inline type::raw_ref& operator>> (object o, type::raw_ref& v)
|
||||
{
|
||||
if(o.type != type::RAW) { throw type_error(); }
|
||||
v.ptr = o.via.raw.ptr;
|
||||
v.size = o.via.raw.size;
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const type::raw_ref& v)
|
||||
{
|
||||
o.pack_raw(v.size);
|
||||
o.pack_raw_body(v.ptr, v.size);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/raw.hpp */
|
||||
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_TYPE_SET_HPP__
|
||||
#define MSGPACK_TYPE_SET_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include <set>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
template <typename T>
|
||||
inline std::set<T>& operator>> (object o, std::set<T>& v)
|
||||
{
|
||||
if(o.type != type::ARRAY) { throw type_error(); }
|
||||
object* p = o.via.array.ptr + o.via.array.size;
|
||||
object* const pbegin = o.via.array.ptr;
|
||||
while(p > pbegin) {
|
||||
--p;
|
||||
v.insert(p->as<T>());
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Stream, typename T>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const std::set<T>& v)
|
||||
{
|
||||
o.pack_array(v.size());
|
||||
for(typename std::set<T>::const_iterator it(v.begin()), it_end(v.end());
|
||||
it != it_end; ++it) {
|
||||
o.pack(*it);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/set.hpp */
|
||||
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_TYPE_STRING_HPP__
|
||||
#define MSGPACK_TYPE_STRING_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
inline std::string& operator>> (object o, std::string& v)
|
||||
{
|
||||
if(o.type != type::RAW) { throw type_error(); }
|
||||
v.assign(o.via.raw.ptr, o.via.raw.size);
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Stream>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const std::string& v)
|
||||
{
|
||||
o.pack_raw(v.size());
|
||||
o.pack_raw_body(v.data(), v.size());
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/string.hpp */
|
||||
|
||||
|
|
@ -1,171 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_TYPE_TUPLE_HPP__
|
||||
#define MSGPACK_TYPE_TUPLE_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
namespace type {
|
||||
|
||||
// FIXME operator==
|
||||
// FIXME operator!=
|
||||
<% GENERATION_LIMIT = 31 %>
|
||||
|
||||
template <typename A0 = void<%1.upto(GENERATION_LIMIT+1) {|i|%>, typename A<%=i%> = void<%}%>>
|
||||
struct tuple;
|
||||
|
||||
template <typename Tuple, int N>
|
||||
struct tuple_element;
|
||||
|
||||
template <typename Tuple, int N>
|
||||
struct const_tuple_element;
|
||||
|
||||
template <typename T>
|
||||
struct tuple_type {
|
||||
typedef T type;
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef const T& transparent_reference;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct tuple_type<T&> {
|
||||
typedef T type;
|
||||
typedef T& value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T& transparent_reference;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct tuple_type<const T&> {
|
||||
typedef T type;
|
||||
typedef T& value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef const T& transparent_reference;
|
||||
};
|
||||
|
||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||
<%0.upto(i) {|j|%>
|
||||
template <typename A0<%1.upto(i) {|k|%>, typename A<%=k%><%}%>>
|
||||
struct tuple_element<tuple<A0<%1.upto(i) {|k|%>, A<%=k%><%}%>>, <%=j%>> : tuple_type<A<%=j%>> {
|
||||
tuple_element(tuple<A0<%1.upto(i) {|k|%>, A<%=k%> <%}%>>& x) : _x(x.a<%=j%>) {}
|
||||
typename tuple_type<A<%=j%>>::reference get() { return _x; }
|
||||
typename tuple_type<A<%=j%>>::const_reference get() const { return _x; }
|
||||
private:
|
||||
typename tuple_type<A<%=j%>>::reference _x;
|
||||
};
|
||||
<%}%>
|
||||
<%}%>
|
||||
|
||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||
<%0.upto(i) {|j|%>
|
||||
template <typename A0<%1.upto(i) {|k|%>, typename A<%=k%><%}%>>
|
||||
struct const_tuple_element<tuple<A0<%1.upto(i) {|k|%>, A<%=k%><%}%>>, <%=j%>> : tuple_type<A<%=j%>> {
|
||||
const_tuple_element(const tuple<A0<%1.upto(i) {|k|%>, A<%=k%><%}%>>& x) : _x(x.a<%=j%>) {}
|
||||
typename tuple_type<A<%=j%>>::const_reference get() const { return _x; }
|
||||
private:
|
||||
typename tuple_type<A<%=j%>>::const_reference _x;
|
||||
};
|
||||
<%}%>
|
||||
<%}%>
|
||||
|
||||
template <>
|
||||
struct tuple<> {
|
||||
tuple() {}
|
||||
tuple(object o) { o.convert(this); }
|
||||
typedef tuple<> value_type;
|
||||
};
|
||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||
template <typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
|
||||
struct tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> {
|
||||
typedef tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> value_type;
|
||||
tuple() {}
|
||||
tuple(typename tuple_type<A0>::transparent_reference _a0<%1.upto(i) {|j|%>, typename tuple_type<A<%=j%>>::transparent_reference _a<%=j%><%}%>) :
|
||||
a0(_a0)<%1.upto(i) {|j|%>, a<%=j%>(_a<%=j%>)<%}%> {}
|
||||
tuple(object o) { o.convert(this); }
|
||||
template <int N> typename tuple_element<value_type, N>::reference get()
|
||||
{ return tuple_element<value_type, N>(*this).get(); }
|
||||
template <int N> typename const_tuple_element<value_type, N>::const_reference get() const
|
||||
{ return const_tuple_element<value_type, N>(*this).get(); }
|
||||
<%0.upto(i) {|j|%>
|
||||
A<%=j%> a<%=j%>;<%}%>
|
||||
};
|
||||
<%}%>
|
||||
|
||||
inline tuple<> make_tuple()
|
||||
{
|
||||
return tuple<>();
|
||||
}
|
||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||
template <typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
|
||||
tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> make_tuple(typename tuple_type<A0>::transparent_reference a0<%1.upto(i) {|j|%>, typename tuple_type<A<%=j%>>::transparent_reference a<%=j%><%}%>)
|
||||
{
|
||||
return tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>>(a0<%1.upto(i) {|j|%>, a<%=j%><%}%>);
|
||||
}
|
||||
<%}%>
|
||||
|
||||
} // namespace type
|
||||
|
||||
|
||||
inline type::tuple<>& operator>> (
|
||||
object o,
|
||||
type::tuple<>& v) {
|
||||
if(o.type != type::ARRAY) { throw type_error(); }
|
||||
return v;
|
||||
}
|
||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||
template <typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
|
||||
type::tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>>& operator>> (
|
||||
object o,
|
||||
type::tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>>& v) {
|
||||
if(o.type != type::ARRAY) { throw type_error(); }
|
||||
if(o.via.array.size < <%=i+1%>) { throw type_error(); }
|
||||
<%0.upto(i) {|j|%>
|
||||
o.via.array.ptr[<%=j%>].convert<A<%=j%>>(&v.template get<<%=j%>>());<%}%>
|
||||
return v;
|
||||
}
|
||||
<%}%>
|
||||
|
||||
template <typename Stream>
|
||||
const packer<Stream>& operator<< (
|
||||
packer<Stream>& o,
|
||||
const type::tuple<>& v) {
|
||||
o.pack_array(0);
|
||||
return o;
|
||||
}
|
||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||
template <typename Stream, typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
|
||||
const packer<Stream>& operator<< (
|
||||
packer<Stream>& o,
|
||||
const type::tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>>& v) {
|
||||
o.pack_array(<%=i+1%>);
|
||||
<%0.upto(i) {|j|%>
|
||||
o.pack(v.template get<<%=j%>>());<%}%>
|
||||
return o;
|
||||
}
|
||||
<%}%>
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/tuple.hpp */
|
||||
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_TYPE_VECTOR_HPP__
|
||||
#define MSGPACK_TYPE_VECTOR_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
template <typename T>
|
||||
inline std::vector<T>& operator>> (object o, std::vector<T>& v)
|
||||
{
|
||||
if(o.type != type::ARRAY) { throw type_error(); }
|
||||
v.resize(o.via.array.size);
|
||||
object* p = o.via.array.ptr;
|
||||
object* const pend = o.via.array.ptr + o.via.array.size;
|
||||
T* it = &v.front();
|
||||
for(; p < pend; ++p, ++it) {
|
||||
p->convert(it);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Stream, typename T>
|
||||
inline packer<Stream>& operator<< (packer<Stream>& o, const std::vector<T>& v)
|
||||
{
|
||||
o.pack_array(v.size());
|
||||
for(typename std::vector<T>::const_iterator it(v.begin()), it_end(v.end());
|
||||
it != it_end; ++it) {
|
||||
o.pack(*it);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/vector.hpp */
|
||||
|
||||
301
cpp/unpack.hpp
301
cpp/unpack.hpp
|
|
@ -1,301 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ deserializing routine
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_UNPACK_HPP__
|
||||
#define MSGPACK_UNPACK_HPP__
|
||||
|
||||
#include "msgpack/unpack.h"
|
||||
#include "msgpack/object.hpp"
|
||||
#include "msgpack/zone.hpp"
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
#ifndef MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE
|
||||
#define MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE (32*1024)
|
||||
#endif
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
struct unpack_error : public std::runtime_error {
|
||||
unpack_error(const std::string& msg) :
|
||||
std::runtime_error(msg) { }
|
||||
};
|
||||
|
||||
|
||||
class unpacker : public msgpack_unpacker {
|
||||
public:
|
||||
unpacker(size_t init_buffer_size = MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE);
|
||||
~unpacker();
|
||||
|
||||
public:
|
||||
/*! 1. reserve buffer. at least `size' bytes of capacity will be ready */
|
||||
void reserve_buffer(size_t size);
|
||||
|
||||
/*! 2. read data to the buffer() up to buffer_capacity() bytes */
|
||||
char* buffer();
|
||||
size_t buffer_capacity() const;
|
||||
|
||||
/*! 3. specify the number of bytes actually copied */
|
||||
void buffer_consumed(size_t size);
|
||||
|
||||
/*! 4. repeat execute() until it retunrs false */
|
||||
bool execute();
|
||||
|
||||
/*! 5.1. if execute() returns true, take out the parsed object */
|
||||
object data();
|
||||
|
||||
/*! 5.2. the object is valid until the zone is deleted */
|
||||
// Note that once release_zone() from unpacker, you must delete it
|
||||
// otherwise the memrory will leak.
|
||||
zone* release_zone();
|
||||
|
||||
/*! 5.2. this method is equivalence to `delete release_zone()` */
|
||||
void reset_zone();
|
||||
|
||||
/*! 5.3. after release_zone(), re-initialize unpacker */
|
||||
void reset();
|
||||
|
||||
/*! 6. check if the size of message doesn't exceed assumption. */
|
||||
size_t message_size() const;
|
||||
|
||||
|
||||
// Basic usage of the unpacker is as following:
|
||||
//
|
||||
// msgpack::unpacker pac;
|
||||
//
|
||||
// while( /* readable */ ) {
|
||||
//
|
||||
// // 1.
|
||||
// pac.reserve(1024);
|
||||
//
|
||||
// // 2.
|
||||
// ssize_t bytes =
|
||||
// read(the_source, pac.buffer(), pac.buffer_capacity());
|
||||
//
|
||||
// // error handling ...
|
||||
//
|
||||
// // 3.
|
||||
// pac.buffer_consumed(bytes);
|
||||
//
|
||||
// // 4.
|
||||
// while(pac.execute()) {
|
||||
// // 5.1
|
||||
// object o = pac.data();
|
||||
//
|
||||
// // 5.2
|
||||
// std::auto_ptr<msgpack::zone> olife( pac.release_zone() );
|
||||
//
|
||||
// // boost::shared_ptr is also usable:
|
||||
// // boost::shared_ptr<msgpack::zone> olife( pac.release_zone() );
|
||||
//
|
||||
// // 5.3
|
||||
// pac.reset();
|
||||
//
|
||||
// // do some with the object with the old zone.
|
||||
// do_something(o, olife);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
|
||||
public:
|
||||
// These functions are usable when non-MessagePack message follows after
|
||||
// MessagePack message.
|
||||
size_t parsed_size() const;
|
||||
|
||||
/*! get address of the buffer that is not parsed */
|
||||
char* nonparsed_buffer();
|
||||
size_t nonparsed_size() const;
|
||||
|
||||
/*! skip specified size of non-parsed buffer, leaving the buffer */
|
||||
// Note that the `size' argument must be smaller than nonparsed_size()
|
||||
void skip_nonparsed_buffer(size_t size);
|
||||
|
||||
/*! remove unparsed buffer from unpacker */
|
||||
// Note that reset() leaves non-parsed buffer.
|
||||
void remove_nonparsed_buffer();
|
||||
|
||||
private:
|
||||
typedef msgpack_unpacker base;
|
||||
|
||||
private:
|
||||
unpacker(const unpacker&);
|
||||
};
|
||||
|
||||
|
||||
typedef enum {
|
||||
UNPACK_SUCCESS = 2,
|
||||
UNPACK_EXTRA_BYTES = 1,
|
||||
UNPACK_CONTINUE = 0,
|
||||
UNPACK_PARSE_ERROR = -1,
|
||||
} unpack_return;
|
||||
|
||||
static unpack_return unpack(const char* data, size_t len, size_t* off,
|
||||
zone* z, object* result);
|
||||
|
||||
|
||||
// obsolete
|
||||
static object unpack(const char* data, size_t len, zone& z, size_t* off = NULL);
|
||||
|
||||
|
||||
inline unpacker::unpacker(size_t initial_buffer_size)
|
||||
{
|
||||
if(!msgpack_unpacker_init(this, initial_buffer_size)) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
inline unpacker::~unpacker()
|
||||
{
|
||||
msgpack_unpacker_destroy(this);
|
||||
}
|
||||
|
||||
|
||||
inline void unpacker::reserve_buffer(size_t size)
|
||||
{
|
||||
if(!msgpack_unpacker_reserve_buffer(this, size)) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
inline char* unpacker::buffer()
|
||||
{
|
||||
return msgpack_unpacker_buffer(this);
|
||||
}
|
||||
|
||||
inline size_t unpacker::buffer_capacity() const
|
||||
{
|
||||
return msgpack_unpacker_buffer_capacity(this);
|
||||
}
|
||||
|
||||
inline void unpacker::buffer_consumed(size_t size)
|
||||
{
|
||||
return msgpack_unpacker_buffer_consumed(this, size);
|
||||
}
|
||||
|
||||
|
||||
inline bool unpacker::execute()
|
||||
{
|
||||
int ret = msgpack_unpacker_execute(this);
|
||||
if(ret < 0) {
|
||||
throw unpack_error("parse error");
|
||||
} else if(ret == 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
inline object unpacker::data()
|
||||
{
|
||||
return msgpack_unpacker_data(this);
|
||||
}
|
||||
|
||||
inline zone* unpacker::release_zone()
|
||||
{
|
||||
if(!msgpack_unpacker_flush_zone(this)) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
zone* r = new zone();
|
||||
|
||||
msgpack_zone old = *base::z;
|
||||
*base::z = *r;
|
||||
*static_cast<msgpack_zone*>(r) = old;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline void unpacker::reset_zone()
|
||||
{
|
||||
msgpack_unpacker_reset_zone(this);
|
||||
}
|
||||
|
||||
inline void unpacker::reset()
|
||||
{
|
||||
msgpack_unpacker_reset(this);
|
||||
}
|
||||
|
||||
inline size_t unpacker::message_size() const
|
||||
{
|
||||
return msgpack_unpacker_message_size(this);
|
||||
}
|
||||
|
||||
|
||||
inline size_t unpacker::parsed_size() const
|
||||
{
|
||||
return msgpack_unpacker_parsed_size(this);
|
||||
}
|
||||
|
||||
inline char* unpacker::nonparsed_buffer()
|
||||
{
|
||||
return base::buffer + base::off;
|
||||
}
|
||||
|
||||
inline size_t unpacker::nonparsed_size() const
|
||||
{
|
||||
return base::used - base::off;
|
||||
}
|
||||
|
||||
inline void unpacker::skip_nonparsed_buffer(size_t size)
|
||||
{
|
||||
base::off += size;
|
||||
}
|
||||
|
||||
inline void unpacker::remove_nonparsed_buffer()
|
||||
{
|
||||
base::used = base::off;
|
||||
}
|
||||
|
||||
|
||||
inline unpack_return unpack(const char* data, size_t len, size_t* off,
|
||||
zone* z, object* result)
|
||||
{
|
||||
return (unpack_return)msgpack_unpack(data, len, off,
|
||||
z, reinterpret_cast<msgpack_object*>(result));
|
||||
}
|
||||
|
||||
// obsolete
|
||||
inline object unpack(const char* data, size_t len, zone& z, size_t* off)
|
||||
{
|
||||
object result;
|
||||
|
||||
switch( msgpack::unpack(data, len, off, &z, &result) ) {
|
||||
case UNPACK_SUCCESS:
|
||||
return result;
|
||||
|
||||
case UNPACK_EXTRA_BYTES:
|
||||
if(off) {
|
||||
return result;
|
||||
} else {
|
||||
throw unpack_error("extra bytes");
|
||||
}
|
||||
|
||||
case UNPACK_CONTINUE:
|
||||
throw unpack_error("insufficient bytes");
|
||||
|
||||
case UNPACK_PARSE_ERROR:
|
||||
default:
|
||||
throw unpack_error("parse error");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/unpack.hpp */
|
||||
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ zero-copy buffer implementation
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_VREFBUFFER_HPP__
|
||||
#define MSGPACK_VREFBUFFER_HPP__
|
||||
|
||||
#include "msgpack/vrefbuffer.h"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
class vrefbuffer : public msgpack_vrefbuffer {
|
||||
public:
|
||||
vrefbuffer(size_t ref_size = MSGPACK_VREFBUFFER_REF_SIZE,
|
||||
size_t chunk_size = MSGPACK_VREFBUFFER_CHUNK_SIZE)
|
||||
{
|
||||
msgpack_vrefbuffer_init(this, ref_size, chunk_size);
|
||||
}
|
||||
|
||||
~vrefbuffer()
|
||||
{
|
||||
msgpack_vrefbuffer_destroy(this);
|
||||
}
|
||||
|
||||
public:
|
||||
void write(const char* buf, unsigned int len)
|
||||
{
|
||||
if(len < base::ref_size) {
|
||||
append_copy(buf, len);
|
||||
} else {
|
||||
append_ref(buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
void append_ref(const char* buf, size_t len)
|
||||
{
|
||||
if(msgpack_vrefbuffer_append_ref(this, buf, len) < 0) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
void append_copy(const char* buf, size_t len)
|
||||
{
|
||||
if(msgpack_vrefbuffer_append_copy(this, buf, len) < 0) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
const struct iovec* vector() const
|
||||
{
|
||||
return msgpack_vrefbuffer_vec(this);
|
||||
}
|
||||
|
||||
size_t vector_size() const
|
||||
{
|
||||
return msgpack_vrefbuffer_veclen(this);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef msgpack_vrefbuffer base;
|
||||
|
||||
private:
|
||||
vrefbuffer(const vrefbuffer&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/vrefbuffer.hpp */
|
||||
|
||||
150
cpp/zone.hpp.erb
150
cpp/zone.hpp.erb
|
|
@ -1,150 +0,0 @@
|
|||
//
|
||||
// MessagePack for C++ memory pool
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_ZONE_HPP__
|
||||
#define MSGPACK_ZONE_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include "msgpack/zone.h"
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
<% GENERATION_LIMIT = 15 %>
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
class zone : public msgpack_zone {
|
||||
public:
|
||||
zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE);
|
||||
~zone();
|
||||
|
||||
public:
|
||||
void* malloc(size_t size);
|
||||
void* malloc_no_align(size_t size);
|
||||
|
||||
void push_finalizer(void (*func)(void*), void* data);
|
||||
|
||||
template <typename T>
|
||||
void push_finalizer(std::auto_ptr<T> obj);
|
||||
|
||||
void clear();
|
||||
|
||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||
template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
|
||||
T* allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>);
|
||||
<%}%>
|
||||
|
||||
private:
|
||||
void undo_malloc(size_t size);
|
||||
|
||||
template <typename T>
|
||||
static void object_destructor(void* obj);
|
||||
|
||||
typedef msgpack_zone base;
|
||||
|
||||
private:
|
||||
zone(const zone&);
|
||||
};
|
||||
|
||||
|
||||
|
||||
inline zone::zone(size_t chunk_size)
|
||||
{
|
||||
msgpack_zone_init(this, chunk_size);
|
||||
}
|
||||
|
||||
inline zone::~zone()
|
||||
{
|
||||
msgpack_zone_destroy(this);
|
||||
}
|
||||
|
||||
inline void* zone::malloc(size_t size)
|
||||
{
|
||||
void* ptr = msgpack_zone_malloc(this, size);
|
||||
if(!ptr) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
inline void* zone::malloc_no_align(size_t size)
|
||||
{
|
||||
void* ptr = msgpack_zone_malloc_no_align(this, size);
|
||||
if(!ptr) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
inline void zone::push_finalizer(void (*func)(void*), void* data)
|
||||
{
|
||||
if(!msgpack_zone_push_finalizer(this, func, data)) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void zone::push_finalizer(std::auto_ptr<T> obj)
|
||||
{
|
||||
if(!msgpack_zone_push_finalizer(this, &zone::object_destructor<T>, obj.get())) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
obj.release();
|
||||
}
|
||||
|
||||
inline void zone::clear()
|
||||
{
|
||||
msgpack_zone_clear(this);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void zone::object_destructor(void* obj)
|
||||
{
|
||||
reinterpret_cast<T*>(obj)->~T();
|
||||
}
|
||||
|
||||
inline void zone::undo_malloc(size_t size)
|
||||
{
|
||||
msgpack_zone_chunk* chunk = base::chunk_array.tail;
|
||||
chunk->ptr -= size;
|
||||
chunk->free += size;
|
||||
}
|
||||
|
||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||
template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
|
||||
T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>)
|
||||
{
|
||||
void* x = malloc(sizeof(T));
|
||||
if(!msgpack_zone_push_finalizer(this, &zone::object_destructor<T>, x)) {
|
||||
undo_malloc(sizeof(T));
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
try {
|
||||
return new (x) T(<%=(1..i).map{|j|"a#{j}"}.join(', ')%>);
|
||||
} catch (...) {
|
||||
--base::finalizer_array.tail;
|
||||
undo_malloc(sizeof(T));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
<%}%>
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/zone.hpp */
|
||||
|
||||
22
docker/buildwheel.sh
Normal file
22
docker/buildwheel.sh
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#!/bin/bash
|
||||
DOCKER_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
source "$DOCKER_DIR/shared.env"
|
||||
|
||||
set -e -x
|
||||
|
||||
ARCH=`uname -p`
|
||||
echo "arch=$ARCH"
|
||||
|
||||
ls /opt/python
|
||||
|
||||
for V in "${PYTHON_VERSIONS[@]}"; do
|
||||
PYBIN=/opt/python/$V/bin
|
||||
rm -rf build/ # Avoid lib build by narrow Python is used by wide python
|
||||
$PYBIN/python -m build -w
|
||||
done
|
||||
|
||||
cd dist
|
||||
for whl in *.whl; do
|
||||
auditwheel repair "$whl"
|
||||
rm "$whl"
|
||||
done
|
||||
17
docker/runtests.sh
Executable file
17
docker/runtests.sh
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
#!/bin/bash
|
||||
DOCKER_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
source "$DOCKER_DIR/shared.env"
|
||||
|
||||
set -e -x
|
||||
|
||||
for V in "${PYTHON_VERSIONS[@]}"; do
|
||||
PYBIN=/opt/python/$V/bin
|
||||
$PYBIN/python setup.py install
|
||||
rm -rf build/ # Avoid lib build by narrow Python is used by wide python
|
||||
$PYBIN/pip install pytest
|
||||
pushd test # prevent importing msgpack package in current directory.
|
||||
$PYBIN/python -c 'import sys; print(hex(sys.maxsize))'
|
||||
$PYBIN/python -c 'from msgpack import _cmsgpack' # Ensure extension is available
|
||||
$PYBIN/pytest -v .
|
||||
popd
|
||||
done
|
||||
7
docker/shared.env
Normal file
7
docker/shared.env
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
PYTHON_VERSIONS=(
|
||||
cp310-cp310
|
||||
cp39-cp39
|
||||
cp38-cp38
|
||||
cp37-cp37m
|
||||
cp36-cp36m
|
||||
)
|
||||
159
docs/Makefile
Normal file
159
docs/Makefile
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = _build
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -E -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
# the i18n builder cannot share the environment and doctrees with the others
|
||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " texinfo to make Texinfo files"
|
||||
@echo " info to make Texinfo files and run them through makeinfo"
|
||||
@echo " gettext to make PO message catalogs"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/msgpack.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/msgpack.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/msgpack"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/msgpack"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
texinfo:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo
|
||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||
"(use \`make info' here to do that automatically)."
|
||||
|
||||
info:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo "Running Texinfo files through makeinfo..."
|
||||
make -C $(BUILDDIR)/texinfo info
|
||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||
|
||||
gettext:
|
||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||
@echo
|
||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
||||
|
||||
serve: html
|
||||
python3 -m http.server -d _build/html
|
||||
|
||||
zip: html
|
||||
cd _build/html && zip -r ../../../msgpack-doc.zip .
|
||||
1
docs/_static/README.txt
vendored
Normal file
1
docs/_static/README.txt
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
Sphinx will copy the contents of docs/_static/ directory to the build location.
|
||||
32
docs/advanced.rst
Normal file
32
docs/advanced.rst
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
Advanced usage
|
||||
===============
|
||||
|
||||
Packer
|
||||
------
|
||||
|
||||
autoreset
|
||||
~~~~~~~~~
|
||||
|
||||
When you used ``autoreset=False`` option of :class:`~msgpack.Packer`,
|
||||
``pack()`` method doesn't return packed ``bytes``.
|
||||
|
||||
You can use :meth:`~msgpack.Packer.bytes` or :meth:`~msgpack.Packer.getbuffer` to
|
||||
get packed data.
|
||||
|
||||
``bytes()`` returns ``bytes`` object. ``getbuffer()`` returns some bytes-like
|
||||
object. It's concrete type is implement detail and it will be changed in future
|
||||
versions.
|
||||
|
||||
You can reduce temporary bytes object by using ``Unpacker.getbuffer()``.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
packer = Packer(use_bin_type=True, autoreset=False)
|
||||
|
||||
packer.pack([1, 2])
|
||||
packer.pack([3, 4])
|
||||
|
||||
with open('data.bin', 'wb') as f:
|
||||
f.write(packer.getbuffer())
|
||||
|
||||
packer.reset() # reset internal buffer
|
||||
43
docs/api.rst
Normal file
43
docs/api.rst
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
API reference
|
||||
=============
|
||||
|
||||
.. module:: msgpack
|
||||
|
||||
.. autofunction:: pack
|
||||
|
||||
``dump()`` is an alias for :func:`pack`
|
||||
|
||||
.. autofunction:: packb
|
||||
|
||||
``dumps()`` is an alias for :func:`packb`
|
||||
|
||||
.. autofunction:: unpack
|
||||
|
||||
``load()`` is an alias for :func:`unpack`
|
||||
|
||||
.. autofunction:: unpackb
|
||||
|
||||
``loads()`` is an alias for :func:`unpackb`
|
||||
|
||||
.. autoclass:: Packer
|
||||
:members:
|
||||
|
||||
.. autoclass:: Unpacker
|
||||
:members:
|
||||
|
||||
.. autoclass:: ExtType
|
||||
|
||||
.. autoclass:: Timestamp
|
||||
:members:
|
||||
:special-members: __init__
|
||||
|
||||
exceptions
|
||||
----------
|
||||
|
||||
These exceptions are accessible via `msgpack` package.
|
||||
(For example, `msgpack.OutOfData` is shortcut for `msgpack.exceptions.OutOfData`)
|
||||
|
||||
.. automodule:: msgpack.exceptions
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
283
docs/conf.py
Normal file
283
docs/conf.py
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
# msgpack documentation build configuration file, created by
|
||||
# sphinx-quickstart on Sun Feb 24 14:20:50 2013.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('..'))
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = ["sphinx.ext.autodoc", "sphinx.ext.viewcode"]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ["_templates"]
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = ".rst"
|
||||
|
||||
# The encoding of source files.
|
||||
# source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = "index"
|
||||
|
||||
# General information about the project.
|
||||
project = "msgpack"
|
||||
copyright = "Inada Naoki"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
version = release = "1.0"
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
# language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
# today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
# today_fmt = '%B %d, %Y'
|
||||
today_fmt = "%Y-%m-%d"
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ["_build"]
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
# default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
# add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
# add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
# show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = "sphinx"
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
# modindex_common_prefix = []
|
||||
|
||||
|
||||
# -- Options for HTML output ---------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
# html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
# html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
# html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
# html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
# html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ["_static"]
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
# html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
# html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
# html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
# html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
# html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
# html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
# html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
# html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
# html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
# html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
# html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
# html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = "msgpackdoc"
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
("index", "msgpack.tex", "msgpack Documentation", "Author", "manual"),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
# latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
# latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
# latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
# latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
# latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
# latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output --------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [("index", "msgpack", "msgpack Documentation", ["Author"], 1)]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
# man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output ------------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(
|
||||
"index",
|
||||
"msgpack",
|
||||
"msgpack Documentation",
|
||||
"Author",
|
||||
"msgpack",
|
||||
"One line description of project.",
|
||||
"Miscellaneous",
|
||||
),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
# texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
# texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
# texinfo_show_urls = 'footnote'
|
||||
|
||||
|
||||
# -- Options for Epub output ---------------------------------------------------
|
||||
|
||||
# Bibliographic Dublin Core info.
|
||||
epub_title = "msgpack"
|
||||
epub_author = "Author"
|
||||
epub_publisher = "Author"
|
||||
epub_copyright = "2013, Author"
|
||||
|
||||
# The language of the text. It defaults to the language option
|
||||
# or en if the language is not set.
|
||||
# epub_language = ''
|
||||
|
||||
# The scheme of the identifier. Typical schemes are ISBN or URL.
|
||||
# epub_scheme = ''
|
||||
|
||||
# The unique identifier of the text. This can be a ISBN number
|
||||
# or the project homepage.
|
||||
# epub_identifier = ''
|
||||
|
||||
# A unique identification for the text.
|
||||
# epub_uid = ''
|
||||
|
||||
# A tuple containing the cover image and cover page html template filenames.
|
||||
# epub_cover = ()
|
||||
|
||||
# HTML files that should be inserted before the pages created by sphinx.
|
||||
# The format is a list of tuples containing the path and title.
|
||||
# epub_pre_files = []
|
||||
|
||||
# HTML files shat should be inserted after the pages created by sphinx.
|
||||
# The format is a list of tuples containing the path and title.
|
||||
# epub_post_files = []
|
||||
|
||||
# A list of files that should not be packed into the epub file.
|
||||
# epub_exclude_files = []
|
||||
|
||||
# The depth of the table of contents in toc.ncx.
|
||||
# epub_tocdepth = 3
|
||||
|
||||
# Allow duplicate toc entries.
|
||||
# epub_tocdup = True
|
||||
11
docs/index.rst
Normal file
11
docs/index.rst
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
msgpack document
|
||||
================
|
||||
|
||||
`MessagePack <http://msgpack.org>`_ is a efficient format for inter
|
||||
language data exchange.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
api
|
||||
advanced
|
||||
2
docs/requirements.txt
Normal file
2
docs/requirements.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
sphinx~=7.3.7
|
||||
sphinx-rtd-theme~=2.0.0
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
#include <msgpack.hpp>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
class old_class {
|
||||
public:
|
||||
old_class() : value("default") { }
|
||||
|
||||
std::string value;
|
||||
|
||||
MSGPACK_DEFINE(value);
|
||||
};
|
||||
|
||||
class new_class {
|
||||
public:
|
||||
new_class() : value("default"), flag(-1) { }
|
||||
|
||||
std::string value;
|
||||
int flag;
|
||||
|
||||
MSGPACK_DEFINE(value, flag);
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
{
|
||||
old_class oc;
|
||||
new_class nc;
|
||||
|
||||
msgpack::sbuffer sbuf;
|
||||
msgpack::pack(sbuf, oc);
|
||||
|
||||
msgpack::zone zone;
|
||||
msgpack::object obj;
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &zone, &obj);
|
||||
|
||||
obj.convert(&nc);
|
||||
|
||||
std::cout << obj << " value=" << nc.value << " flag=" << nc.flag << std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
new_class nc;
|
||||
old_class oc;
|
||||
|
||||
msgpack::sbuffer sbuf;
|
||||
msgpack::pack(sbuf, nc);
|
||||
|
||||
msgpack::zone zone;
|
||||
msgpack::object obj;
|
||||
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &zone, &obj);
|
||||
|
||||
obj.convert(&oc);
|
||||
|
||||
std::cout << obj << " value=" << oc.value << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
#include <msgpack.hpp>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
namespace myprotocol {
|
||||
using namespace msgpack::type;
|
||||
using msgpack::define;
|
||||
|
||||
struct Get : define< tuple<uint32_t, std::string> > {
|
||||
Get() { }
|
||||
Get(uint32_t f, const std::string& k) :
|
||||
define_type(msgpack_type(f, k)) { }
|
||||
uint32_t& flags() { return get<0>(); }
|
||||
std::string& key() { return get<1>(); }
|
||||
};
|
||||
|
||||
struct Put : define< tuple<uint32_t, std::string, raw_ref> > {
|
||||
Put() { }
|
||||
Put(uint32_t f, const std::string& k, const char* valref, size_t vallen) :
|
||||
define_type(msgpack_type( f, k, raw_ref(valref,vallen) )) { }
|
||||
uint32_t& flags() { return get<0>(); }
|
||||
std::string& key() { return get<1>(); }
|
||||
raw_ref& value() { return get<2>(); }
|
||||
};
|
||||
|
||||
struct MultiGet : define< std::vector<Get> > {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// send Get request
|
||||
std::stringstream stream;
|
||||
{
|
||||
myprotocol::Get req;
|
||||
req.flags() = 0;
|
||||
req.key() = "key0";
|
||||
msgpack::pack(stream, req);
|
||||
}
|
||||
|
||||
stream.seekg(0);
|
||||
|
||||
// receive Get request
|
||||
{
|
||||
std::string buffer(stream.str());
|
||||
|
||||
msgpack::zone mempool;
|
||||
msgpack::object o =
|
||||
msgpack::unpack(buffer.data(), buffer.size(), mempool);
|
||||
|
||||
myprotocol::Get req;
|
||||
msgpack::convert(req, o);
|
||||
std::cout << "received: " << o << std::endl;
|
||||
}
|
||||
|
||||
|
||||
stream.str("");
|
||||
|
||||
|
||||
// send MultiGet request
|
||||
{
|
||||
myprotocol::MultiGet req;
|
||||
req.push_back( myprotocol::Get(1, "key1") );
|
||||
req.push_back( myprotocol::Get(2, "key2") );
|
||||
req.push_back( myprotocol::Get(3, "key3") );
|
||||
msgpack::pack(stream, req);
|
||||
}
|
||||
|
||||
stream.seekg(0);
|
||||
|
||||
// receive MultiGet request
|
||||
{
|
||||
std::string buffer(stream.str());
|
||||
|
||||
msgpack::zone mempool;
|
||||
msgpack::object o =
|
||||
msgpack::unpack(buffer.data(), buffer.size(), mempool);
|
||||
|
||||
myprotocol::MultiGet req;
|
||||
msgpack::convert(req, o);
|
||||
std::cout << "received: " << o << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
#include <msgpack.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* msgpack::sbuffer is a simple buffer implementation. */
|
||||
msgpack_sbuffer sbuf;
|
||||
msgpack_sbuffer_init(&sbuf);
|
||||
|
||||
/* 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_raw(&pk, 7);
|
||||
msgpack_pack_raw_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;
|
||||
}
|
||||
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
#include <msgpack.hpp>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
msgpack::type::tuple<int, bool, std::string> src(1, true, "example");
|
||||
|
||||
// serialize the object into the buffer.
|
||||
// any classes that implements write(const char*,size_t) can be a buffer.
|
||||
std::stringstream buffer;
|
||||
msgpack::pack(buffer, src);
|
||||
|
||||
// send the buffer ...
|
||||
buffer.seekg(0);
|
||||
|
||||
// deserialize the buffer into msgpack::object instance.
|
||||
std::string str(buffer.str());
|
||||
|
||||
// deserialized object is valid during the msgpack::zone instance alive.
|
||||
msgpack::zone mempool;
|
||||
|
||||
msgpack::object deserialized;
|
||||
msgpack::unpack(str.data(), str.size(), NULL, &mempool, &deserialized);
|
||||
|
||||
// msgpack::object supports ostream.
|
||||
std::cout << deserialized << std::endl;
|
||||
|
||||
// convert msgpack::object instance into the original type.
|
||||
// if the type is mismatched, it throws msgpack::type_error exception.
|
||||
msgpack::type::tuple<int, bool, std::string> dst;
|
||||
deserialized.convert(&dst);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
require 'msgpack'
|
||||
|
||||
serialized = [1, -1, true, false, nil, {"key" => "value"}].to_msgpack
|
||||
p MessagePack.unpack(serialized)
|
||||
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
#include <msgpack.hpp>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
class Server {
|
||||
public:
|
||||
Server(int sock) : m_sock(sock) { }
|
||||
|
||||
~Server() { }
|
||||
|
||||
typedef std::auto_ptr<msgpack::zone> auto_zone;
|
||||
|
||||
void socket_readable()
|
||||
{
|
||||
m_pac.reserve_buffer(1024);
|
||||
|
||||
ssize_t count =
|
||||
read(m_sock, m_pac.buffer(), m_pac.buffer_capacity());
|
||||
|
||||
if(count <= 0) {
|
||||
if(count == 0) {
|
||||
throw std::runtime_error("connection closed");
|
||||
}
|
||||
if(errno == EAGAIN || errno == EINTR) {
|
||||
return;
|
||||
}
|
||||
throw std::runtime_error(strerror(errno));
|
||||
}
|
||||
|
||||
m_pac.buffer_consumed(count);
|
||||
|
||||
while(m_pac.execute()) {
|
||||
msgpack::object msg = m_pac.data();
|
||||
|
||||
auto_zone life( m_pac.release_zone() );
|
||||
|
||||
m_pac.reset();
|
||||
|
||||
process_message(msg, life);
|
||||
}
|
||||
|
||||
if(m_pac.message_size() > 10*1024*1024) {
|
||||
throw std::runtime_error("message is too large");
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void process_message(msgpack::object msg, auto_zone& life)
|
||||
{
|
||||
std::cout << "message reached: " << msg << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_sock;
|
||||
msgpack::unpacker m_pac;
|
||||
};
|
||||
|
||||
|
||||
static void* run_server(void* arg)
|
||||
try {
|
||||
Server* srv = reinterpret_cast<Server*>(arg);
|
||||
|
||||
while(true) {
|
||||
srv->socket_readable();
|
||||
}
|
||||
return NULL;
|
||||
|
||||
} catch (std::exception& e) {
|
||||
std::cerr << "error while processing client packet: "
|
||||
<< e.what() << std::endl;
|
||||
return NULL;
|
||||
|
||||
} catch (...) {
|
||||
std::cerr << "error while processing client packet: "
|
||||
<< "unknown error" << std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct fwriter {
|
||||
fwriter(int fd) : m_fp( fdopen(fd, "w") ) { }
|
||||
|
||||
void write(const char* buf, size_t buflen)
|
||||
{
|
||||
size_t count = fwrite(buf, buflen, 1, m_fp);
|
||||
if(count < 1) {
|
||||
std::cout << buflen << std::endl;
|
||||
std::cout << count << std::endl;
|
||||
throw std::runtime_error(strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
void flush() { fflush(m_fp); }
|
||||
|
||||
void close() { fclose(m_fp); }
|
||||
|
||||
private:
|
||||
FILE* m_fp;
|
||||
};
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int pair[2];
|
||||
pipe(pair);
|
||||
|
||||
// run server thread
|
||||
Server srv(pair[0]);
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, NULL,
|
||||
run_server, reinterpret_cast<void*>(&srv));
|
||||
|
||||
// client thread:
|
||||
fwriter writer(pair[1]);
|
||||
msgpack::packer<fwriter> pk(writer);
|
||||
|
||||
typedef msgpack::type::tuple<std::string, std::string, std::string> put_t;
|
||||
typedef msgpack::type::tuple<std::string, std::string> get_t;
|
||||
|
||||
put_t req1("put", "apple", "red");
|
||||
put_t req2("put", "lemon", "yellow");
|
||||
get_t req3("get", "apple");
|
||||
pk.pack(req1);
|
||||
pk.pack(req2);
|
||||
pk.pack(req3);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
|
||||
pthread_join(thread, NULL);
|
||||
}
|
||||
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
require 'msgpack'
|
||||
|
||||
class Server
|
||||
def initialize(sock)
|
||||
@sock = sock
|
||||
@pk = MessagePack::Unpacker.new
|
||||
@buffer = ''
|
||||
@nread = 0
|
||||
end
|
||||
|
||||
def run
|
||||
while true
|
||||
begin
|
||||
data = @sock.sysread(1024)
|
||||
rescue
|
||||
puts "connection closed (#{$!})"
|
||||
return
|
||||
end
|
||||
receive_data(data)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def receive_data(data)
|
||||
@buffer << data
|
||||
|
||||
while true
|
||||
@nread = @pk.execute(@buffer, @nread)
|
||||
|
||||
if @pk.finished?
|
||||
msg = @pk.data
|
||||
process_message(msg)
|
||||
|
||||
@pk.reset
|
||||
@buffer.slice!(0, @nread)
|
||||
@nread = 0
|
||||
|
||||
next unless @buffer.empty?
|
||||
end
|
||||
|
||||
break
|
||||
end
|
||||
|
||||
if @buffer.length > 10*1024*1024
|
||||
raise "message is too large"
|
||||
end
|
||||
|
||||
rescue
|
||||
puts "error while processing client packet: #{$!}"
|
||||
end
|
||||
|
||||
def process_message(msg)
|
||||
puts "message reached: #{msg.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
rpipe, wpipe = IO.pipe
|
||||
|
||||
# run server thread
|
||||
thread = Thread.new(Server.new(rpipe)) {|srv|
|
||||
srv.run
|
||||
}
|
||||
|
||||
# client thread:
|
||||
wpipe.write ["put", "apple", "red"].to_msgpack
|
||||
wpipe.write ["put", "lemon", "yellow"].to_msgpack
|
||||
wpipe.write ["get", "apple"].to_msgpack
|
||||
wpipe.close
|
||||
|
||||
thread.join
|
||||
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
import java.nio.ByteBuffer;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class MessagePack {
|
||||
|
||||
static public Object unpack(InputStream source)
|
||||
{
|
||||
// FIXME not implemented yet
|
||||
return null;
|
||||
}
|
||||
|
||||
static public Object unpack(byte[] source, int len) throws IOException
|
||||
{
|
||||
// FIXME not implemented yet
|
||||
return null;
|
||||
}
|
||||
|
||||
static public Object unpack(ByteBuffer source) throws IOException
|
||||
{
|
||||
// FIXME not implemented yet
|
||||
return null;
|
||||
}
|
||||
|
||||
static public Object unpack(ByteBuffer[] source) throws IOException
|
||||
{
|
||||
// FIXME not implemented yet
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public interface MessagePackable {
|
||||
public void toMessagePack(Packer pk);
|
||||
}
|
||||
*/
|
||||
|
||||
|
|
@ -1,266 +0,0 @@
|
|||
import java.io.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class Packer {
|
||||
protected byte[] castBytes = new byte[9];
|
||||
protected ByteBuffer castBuffer = ByteBuffer.wrap(castBytes);
|
||||
protected OutputStream out;
|
||||
|
||||
public Packer(OutputStream out)
|
||||
{
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
public Packer packByte(byte d) throws IOException
|
||||
{
|
||||
if(d < -(1<<5)) {
|
||||
castBytes[0] = (byte)0xd1;
|
||||
castBytes[1] = d;
|
||||
out.write(castBytes, 0, 2);
|
||||
} else {
|
||||
out.write(d);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packShort(short d) throws IOException
|
||||
{
|
||||
if(d < -(1<<5)) {
|
||||
if(d < -(1<<7)) {
|
||||
// signed 16
|
||||
castBytes[0] = (byte)0xd1;
|
||||
castBuffer.putShort(1, d);
|
||||
out.write(castBytes, 0, 3);
|
||||
} else {
|
||||
// signed 8
|
||||
castBytes[0] = (byte)0xd0;
|
||||
castBytes[1] = (byte)d;
|
||||
out.write(castBytes, 0, 2);
|
||||
}
|
||||
} else if(d < (1<<7)) {
|
||||
// fixnum
|
||||
out.write((byte)d);
|
||||
} else {
|
||||
if(d < (1<<8)) {
|
||||
// unsigned 8
|
||||
castBytes[0] = (byte)0xcc;
|
||||
castBytes[1] = (byte)d;
|
||||
out.write(castBytes, 0, 2);
|
||||
} else {
|
||||
// unsigned 16
|
||||
castBytes[0] = (byte)0xcd;
|
||||
castBuffer.putShort(1, d);
|
||||
out.write(castBytes, 0, 3);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packInt(int d) throws IOException
|
||||
{
|
||||
if(d < -(1<<5)) {
|
||||
if(d < -(1<<15)) {
|
||||
// signed 32
|
||||
castBytes[0] = (byte)0xd2;
|
||||
castBuffer.putInt(1, d);
|
||||
out.write(castBytes, 0, 5);
|
||||
} else if(d < -(1<<7)) {
|
||||
// signed 16
|
||||
castBytes[0] = (byte)0xd1;
|
||||
castBuffer.putShort(1, (short)d);
|
||||
out.write(castBytes, 0, 3);
|
||||
} else {
|
||||
// signed 8
|
||||
castBytes[0] = (byte)0xd0;
|
||||
castBytes[1] = (byte)d;
|
||||
out.write(castBytes, 0, 2);
|
||||
}
|
||||
} else if(d < (1<<7)) {
|
||||
// fixnum
|
||||
out.write((byte)d);
|
||||
} else {
|
||||
if(d < (1<<8)) {
|
||||
// unsigned 8
|
||||
castBytes[0] = (byte)0xcc;
|
||||
castBytes[1] = (byte)d;
|
||||
out.write(castBytes, 0, 2);
|
||||
} else if(d < (1<<16)) {
|
||||
// unsigned 16
|
||||
castBytes[0] = (byte)0xcd;
|
||||
castBuffer.putShort(1, (short)d);
|
||||
out.write(castBytes, 0, 3);
|
||||
} else {
|
||||
// unsigned 32
|
||||
castBytes[0] = (byte)0xce;
|
||||
castBuffer.putInt(1, d);
|
||||
out.write(castBytes, 0, 5);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packLong(long d) throws IOException
|
||||
{
|
||||
if(d < -(1L<<5)) {
|
||||
if(d < -(1L<<15)) {
|
||||
if(d < -(1L<<31)) {
|
||||
// signed 64
|
||||
castBytes[0] = (byte)0xd3;
|
||||
castBuffer.putLong(1, d);
|
||||
out.write(castBytes, 0, 9);
|
||||
} else {
|
||||
// signed 32
|
||||
castBytes[0] = (byte)0xd2;
|
||||
castBuffer.putInt(1, (int)d);
|
||||
out.write(castBytes, 0, 5);
|
||||
}
|
||||
} else {
|
||||
if(d < -(1<<7)) {
|
||||
// signed 16
|
||||
castBytes[0] = (byte)0xd1;
|
||||
castBuffer.putShort(1, (short)d);
|
||||
out.write(castBytes, 0, 3);
|
||||
} else {
|
||||
// signed 8
|
||||
castBytes[0] = (byte)0xd0;
|
||||
castBytes[1] = (byte)d;
|
||||
out.write(castBytes, 0, 2);
|
||||
}
|
||||
}
|
||||
} else if(d < (1<<7)) {
|
||||
// fixnum
|
||||
out.write((byte)d);
|
||||
} else {
|
||||
if(d < (1L<<16)) {
|
||||
if(d < (1<<8)) {
|
||||
// unsigned 8
|
||||
castBytes[0] = (byte)0xcc;
|
||||
castBytes[1] = (byte)d;
|
||||
out.write(castBytes, 0, 2);
|
||||
} else {
|
||||
// unsigned 16
|
||||
castBytes[0] = (byte)0xcd;
|
||||
castBuffer.putShort(1, (short)d);
|
||||
out.write(castBytes, 0, 3);
|
||||
//System.out.println("pack uint 16 "+(short)d);
|
||||
}
|
||||
} else {
|
||||
if(d < (1L<<32)) {
|
||||
// unsigned 32
|
||||
castBytes[0] = (byte)0xce;
|
||||
castBuffer.putInt(1, (int)d);
|
||||
out.write(castBytes, 0, 5);
|
||||
} else {
|
||||
// unsigned 64
|
||||
castBytes[0] = (byte)0xcf;
|
||||
castBuffer.putLong(1, d);
|
||||
out.write(castBytes, 0, 9);
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packFloat(float d) throws IOException
|
||||
{
|
||||
castBytes[0] = (byte)0xca;
|
||||
castBuffer.putFloat(1, d);
|
||||
out.write(castBytes, 0, 5);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packDouble(double d) throws IOException
|
||||
{
|
||||
castBytes[0] = (byte)0xcb;
|
||||
castBuffer.putDouble(1, d);
|
||||
out.write(castBytes, 0, 9);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packNil() throws IOException
|
||||
{
|
||||
out.write((byte)0xc0);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packTrue() throws IOException
|
||||
{
|
||||
out.write((byte)0xc3);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packFalse() throws IOException
|
||||
{
|
||||
out.write((byte)0xc2);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packArray(int n) throws IOException
|
||||
{
|
||||
if(n < 16) {
|
||||
final int d = 0x90 | n;
|
||||
out.write((byte)d);
|
||||
} else if(n < 65536) {
|
||||
castBytes[0] = (byte)0xdc;
|
||||
castBuffer.putShort(1, (short)n);
|
||||
out.write(castBytes, 0, 3);
|
||||
} else {
|
||||
castBytes[0] = (byte)0xdd;
|
||||
castBuffer.putInt(1, n);
|
||||
out.write(castBytes, 0, 5);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packMap(int n) throws IOException
|
||||
{
|
||||
if(n < 16) {
|
||||
final int d = 0x80 | n;
|
||||
out.write((byte)d);
|
||||
} else if(n < 65536) {
|
||||
castBytes[0] = (byte)0xde;
|
||||
castBuffer.putShort(1, (short)n);
|
||||
out.write(castBytes, 0, 3);
|
||||
} else {
|
||||
castBytes[0] = (byte)0xdf;
|
||||
castBuffer.putInt(1, n);
|
||||
out.write(castBytes, 0, 5);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packRaw(int n) throws IOException
|
||||
{
|
||||
if(n < 32) {
|
||||
final int d = 0xa0 | n;
|
||||
out.write((byte)d);
|
||||
} else if(n < 65536) {
|
||||
castBytes[0] = (byte)0xda;
|
||||
castBuffer.putShort(1, (short)n);
|
||||
out.write(castBytes, 0, 3);
|
||||
} else {
|
||||
castBytes[0] = (byte)0xdb;
|
||||
castBuffer.putInt(1, n);
|
||||
out.write(castBytes, 0, 5);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packRawBody(byte[] b) throws IOException
|
||||
{
|
||||
out.write(b);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packRawBody(byte[] b, int off, int length) throws IOException
|
||||
{
|
||||
out.write(b, off, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
//public Packer pack(Object o) throws IOException
|
||||
}
|
||||
|
||||
|
|
@ -1,401 +0,0 @@
|
|||
import java.io.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class Unpacker {
|
||||
protected static final int CS_HEADER = 0x00;
|
||||
protected static final int CS_FLOAT = 0x0a;
|
||||
protected static final int CS_DOUBLE = 0x0b;
|
||||
protected static final int CS_UINT_8 = 0x0c;
|
||||
protected static final int CS_UINT_16 = 0x0d;
|
||||
protected static final int CS_UINT_32 = 0x0e;
|
||||
protected static final int CS_UINT_64 = 0x0f;
|
||||
protected static final int CS_INT_8 = 0x10;
|
||||
protected static final int CS_INT_16 = 0x11;
|
||||
protected static final int CS_INT_32 = 0x12;
|
||||
protected static final int CS_INT_64 = 0x13;
|
||||
protected static final int CS_RAW_16 = 0x1a;
|
||||
protected static final int CS_RAW_32 = 0x1b;
|
||||
protected static final int CS_ARRAY_16 = 0x1c;
|
||||
protected static final int CS_ARRAY_32 = 0x1d;
|
||||
protected static final int CS_MAP_16 = 0x1e;
|
||||
protected static final int CS_MAP_32 = 0x1f;
|
||||
protected static final int ACS_RAW_VALUE = 0x20;
|
||||
protected static final int CT_ARRAY_ITEM = 0x00;
|
||||
protected static final int CT_MAP_KEY = 0x01;
|
||||
protected static final int CT_MAP_VALUE = 0x02;
|
||||
|
||||
protected static final int MAX_STACK_SIZE = 16;
|
||||
|
||||
protected int cs = CS_HEADER;
|
||||
protected int trail = 0;
|
||||
protected int top = -1;
|
||||
protected boolean finished = false;
|
||||
protected int[] stack_ct = new int[MAX_STACK_SIZE];
|
||||
protected int[] stack_count = new int[MAX_STACK_SIZE];
|
||||
protected Object[] stack_obj = new Object[MAX_STACK_SIZE];
|
||||
protected Object[] stack_map_key = new Object[MAX_STACK_SIZE];
|
||||
//protected Object user;
|
||||
protected ByteBuffer castBuffer = ByteBuffer.allocate(8);
|
||||
|
||||
public Object getData()
|
||||
{
|
||||
return stack_obj[0];
|
||||
}
|
||||
|
||||
public boolean isFinished()
|
||||
{
|
||||
return finished;
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
for(int i=0; i <= top; ++top) {
|
||||
stack_ct[top] = 0;
|
||||
stack_count[top] = 0;
|
||||
stack_obj[top] = null;
|
||||
stack_map_key[top] = null;
|
||||
}
|
||||
cs = CS_HEADER;
|
||||
trail = 0;
|
||||
top = -1;
|
||||
finished = false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public int execute(byte[] src, int off, int length) throws IOException
|
||||
{
|
||||
if(off >= length) { return off; }
|
||||
|
||||
int limit = length;
|
||||
int i = off;
|
||||
int count;
|
||||
|
||||
Object obj = null;
|
||||
|
||||
_out: do {
|
||||
_header_again: {
|
||||
//System.out.println("while i:"+i+" limit:"+limit);
|
||||
|
||||
int b = src[i];
|
||||
|
||||
_push: {
|
||||
_fixed_trail_again:
|
||||
if(cs == CS_HEADER) {
|
||||
|
||||
if((b & 0x80) == 0) { // Positive Fixnum
|
||||
//System.out.println("positive fixnum "+b);
|
||||
obj = b;
|
||||
break _push;
|
||||
}
|
||||
|
||||
if((b & 0xe0) == 0xe0) { // Negative Fixnum
|
||||
//System.out.println("negative fixnum "+b);
|
||||
obj = b;
|
||||
break _push;
|
||||
}
|
||||
|
||||
if((b & 0xe0) == 0xa0) { // FixRaw
|
||||
trail = b & 0x1f;
|
||||
if(trail == 0) {
|
||||
obj = new byte[0];
|
||||
break _push;
|
||||
}
|
||||
cs = ACS_RAW_VALUE;
|
||||
break _fixed_trail_again;
|
||||
}
|
||||
|
||||
if((b & 0xf0) == 0x90) { // FixArray
|
||||
if(top >= MAX_STACK_SIZE) {
|
||||
throw new IOException("parse error");
|
||||
}
|
||||
count = b & 0x0f;
|
||||
++top;
|
||||
stack_obj[top] = new ArrayList(count);
|
||||
stack_ct[top] = CT_ARRAY_ITEM;
|
||||
stack_count[top] = count;
|
||||
//System.out.println("fixarray count:"+count);
|
||||
break _header_again;
|
||||
}
|
||||
|
||||
if((b & 0xf0) == 0x80) { // FixMap
|
||||
if(top >= MAX_STACK_SIZE) {
|
||||
throw new IOException("parse error");
|
||||
}
|
||||
count = b & 0x0f;
|
||||
++top;
|
||||
stack_obj[top] = new HashMap(count);
|
||||
stack_ct[top] = CT_MAP_KEY;
|
||||
stack_count[top] = count;
|
||||
//System.out.println("fixmap count:"+count);
|
||||
break _header_again;
|
||||
}
|
||||
|
||||
switch(b & 0xff) { // FIXME
|
||||
case 0xc0: // nil
|
||||
obj = null;
|
||||
break _push;
|
||||
case 0xc2: // false
|
||||
obj = false;
|
||||
break _push;
|
||||
case 0xc3: // true
|
||||
obj = true;
|
||||
break _push;
|
||||
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
|
||||
trail = 1 << (b & 0x03);
|
||||
cs = b & 0x1f;
|
||||
//System.out.println("a trail "+trail+" cs:"+cs);
|
||||
break _fixed_trail_again;
|
||||
case 0xda: // raw 16
|
||||
case 0xdb: // raw 32
|
||||
case 0xdc: // array 16
|
||||
case 0xdd: // array 32
|
||||
case 0xde: // map 16
|
||||
case 0xdf: // map 32
|
||||
trail = 2 << (b & 0x01);
|
||||
cs = b & 0x1f;
|
||||
//System.out.println("b trail "+trail+" cs:"+cs);
|
||||
break _fixed_trail_again;
|
||||
default:
|
||||
//System.out.println("unknown b "+(b&0xff));
|
||||
throw new IOException("parse error");
|
||||
}
|
||||
|
||||
} // _fixed_trail_again
|
||||
|
||||
do {
|
||||
_fixed_trail_again: {
|
||||
|
||||
if(limit - i <= trail) { break _out; }
|
||||
int n = i + 1;
|
||||
i += trail;
|
||||
|
||||
switch(cs) {
|
||||
case CS_FLOAT:
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 4);
|
||||
obj = castBuffer.getFloat(0);
|
||||
//System.out.println("float "+obj);
|
||||
break _push;
|
||||
case CS_DOUBLE:
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 8);
|
||||
obj = castBuffer.getDouble(0);
|
||||
//System.out.println("double "+obj);
|
||||
break _push;
|
||||
case CS_UINT_8:
|
||||
//System.out.println(n);
|
||||
//System.out.println(src[n]);
|
||||
//System.out.println(src[n+1]);
|
||||
//System.out.println(src[n-1]);
|
||||
obj = ((int)src[n]) & 0xff;
|
||||
//System.out.println("uint8 "+obj);
|
||||
break _push;
|
||||
case CS_UINT_16:
|
||||
//System.out.println(src[n]);
|
||||
//System.out.println(src[n+1]);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 2);
|
||||
obj = ((int)castBuffer.getShort(0)) & 0xffff;
|
||||
//System.out.println("uint 16 "+obj);
|
||||
break _push;
|
||||
case CS_UINT_32:
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 4);
|
||||
{
|
||||
// FIXME always long?
|
||||
int o = castBuffer.getInt(0);
|
||||
if(o < 0) {
|
||||
obj = ((long)o) & 0xffffffffL;
|
||||
} else {
|
||||
obj = o;
|
||||
}
|
||||
}
|
||||
//System.out.println("uint 32 "+obj);
|
||||
break _push;
|
||||
case CS_UINT_64:
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 8);
|
||||
{
|
||||
// FIXME always BigInteger?
|
||||
long o = castBuffer.getLong(0);
|
||||
if(o < 0) {
|
||||
obj = BigInteger.valueOf(o & 0x7fffffffL).setBit(31);
|
||||
} else {
|
||||
obj = o;
|
||||
}
|
||||
}
|
||||
throw new IOException("uint 64 is not supported");
|
||||
case CS_INT_8:
|
||||
obj = (int)src[n];
|
||||
break _push;
|
||||
case CS_INT_16:
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 2);
|
||||
obj = (int)castBuffer.getShort(0);
|
||||
break _push;
|
||||
case CS_INT_32:
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 4);
|
||||
obj = (int)castBuffer.getInt(0);
|
||||
break _push;
|
||||
case CS_INT_64:
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 8);
|
||||
{
|
||||
// FIXME always long?
|
||||
long o = castBuffer.getLong(0);
|
||||
if(o <= 0x7fffffffL && o > -0x80000000L) {
|
||||
obj = (int)o;
|
||||
} else {
|
||||
obj = o;
|
||||
}
|
||||
}
|
||||
//System.out.println("long "+obj);
|
||||
break _push;
|
||||
case CS_RAW_16:
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 2);
|
||||
trail = ((int)castBuffer.getShort(0)) & 0xffff;
|
||||
if(trail == 0) {
|
||||
obj = new byte[0];
|
||||
break _push;
|
||||
}
|
||||
cs = ACS_RAW_VALUE;
|
||||
break _fixed_trail_again;
|
||||
case CS_RAW_32:
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 4);
|
||||
// FIXME overflow check
|
||||
trail = castBuffer.getInt(0) & 0x7fffffff;
|
||||
if(trail == 0) {
|
||||
obj = new byte[0];
|
||||
break _push;
|
||||
}
|
||||
cs = ACS_RAW_VALUE;
|
||||
case ACS_RAW_VALUE:
|
||||
obj = ByteBuffer.wrap(src, n, trail); // FIXME プール? コピー
|
||||
break _push;
|
||||
case CS_ARRAY_16:
|
||||
if(top >= MAX_STACK_SIZE) {
|
||||
throw new IOException("parse error");
|
||||
}
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 2);
|
||||
count = ((int)castBuffer.getShort(0)) & 0xffff;
|
||||
++top;
|
||||
stack_obj[top] = new ArrayList(count);
|
||||
stack_ct[top] = CT_ARRAY_ITEM;
|
||||
stack_count[top] = count;
|
||||
break _header_again;
|
||||
case CS_ARRAY_32:
|
||||
if(top >= MAX_STACK_SIZE) {
|
||||
throw new IOException("parse error");
|
||||
}
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 4);
|
||||
// FIXME overflow check
|
||||
count = castBuffer.getInt(0) & 0x7fffffff;
|
||||
++top;
|
||||
stack_obj[top] = new ArrayList(count);
|
||||
stack_ct[top] = CT_ARRAY_ITEM;
|
||||
stack_count[top] = count;
|
||||
break _header_again;
|
||||
case CS_MAP_16:
|
||||
if(top >= MAX_STACK_SIZE) {
|
||||
throw new IOException("parse error");
|
||||
}
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 2);
|
||||
count = ((int)castBuffer.getShort(0)) & 0xffff;
|
||||
++top;
|
||||
stack_obj[top] = new HashMap(count);
|
||||
stack_ct[top] = CT_MAP_KEY;
|
||||
stack_count[top] = count;
|
||||
//System.out.println("fixmap count:"+count);
|
||||
break _header_again;
|
||||
case CS_MAP_32:
|
||||
if(top >= MAX_STACK_SIZE) {
|
||||
throw new IOException("parse error");
|
||||
}
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 4);
|
||||
// FIXME overflow check
|
||||
count = castBuffer.getInt(0) & 0x7fffffff;
|
||||
++top;
|
||||
stack_obj[top] = new HashMap(count);
|
||||
stack_ct[top] = CT_MAP_KEY;
|
||||
stack_count[top] = count;
|
||||
//System.out.println("fixmap count:"+count);
|
||||
break _header_again;
|
||||
default:
|
||||
throw new IOException("parse error");
|
||||
}
|
||||
|
||||
} // _fixed_trail_again
|
||||
} while(true);
|
||||
} // _push
|
||||
|
||||
do {
|
||||
_push: {
|
||||
//System.out.println("push top:"+top);
|
||||
if(top == -1) {
|
||||
stack_obj[0] = obj;
|
||||
finished = true;
|
||||
break _out;
|
||||
}
|
||||
|
||||
switch(stack_ct[top]) {
|
||||
case CT_ARRAY_ITEM:
|
||||
//System.out.println("array item "+obj);
|
||||
((ArrayList)(stack_obj[top])).add(obj);
|
||||
if(--stack_count[top] == 0) {
|
||||
obj = stack_obj[top];
|
||||
stack_obj[top] = null;
|
||||
--top;
|
||||
break _push;
|
||||
}
|
||||
break _header_again;
|
||||
case CT_MAP_KEY:
|
||||
//System.out.println("map key:"+top+" "+obj);
|
||||
stack_map_key[top] = obj;
|
||||
stack_ct[top] = CT_MAP_VALUE;
|
||||
break _header_again;
|
||||
case CT_MAP_VALUE:
|
||||
//System.out.println("map value:"+top+" "+obj);
|
||||
((HashMap)(stack_obj[top])).put(stack_map_key[top], obj);
|
||||
if(--stack_count[top] == 0) {
|
||||
obj = stack_obj[top];
|
||||
stack_map_key[top] = null;
|
||||
stack_obj[top] = null;
|
||||
--top;
|
||||
break _push;
|
||||
}
|
||||
stack_ct[top] = CT_MAP_KEY;
|
||||
break _header_again;
|
||||
default:
|
||||
throw new IOException("parse error");
|
||||
}
|
||||
} // _push
|
||||
} while(true);
|
||||
|
||||
} // _header_again
|
||||
cs = CS_HEADER;
|
||||
++i;
|
||||
} while(i < limit); // _out
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/sh
|
||||
javac MessagePack.java Packer.java Unpacker.java test.java
|
||||
java test
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
class OpenByteArrayOutputStream extends ByteArrayOutputStream {
|
||||
int getCount() { return count; }
|
||||
byte[] getBuffer() { return buf; }
|
||||
}
|
||||
|
||||
|
||||
public class test {
|
||||
|
||||
public static void main(String[] args) throws IOException
|
||||
{
|
||||
testSimple();
|
||||
testStreaming();
|
||||
}
|
||||
|
||||
|
||||
public static void testSimple() throws IOException
|
||||
{
|
||||
OpenByteArrayOutputStream out = new OpenByteArrayOutputStream();
|
||||
|
||||
Packer pk = new Packer(out);
|
||||
pk.packArray(3)
|
||||
.packInt(1)
|
||||
.packByte((byte)2)
|
||||
.packDouble(0.3);
|
||||
|
||||
Unpacker pac = new Unpacker();
|
||||
int nlen = pac.execute(out.getBuffer(), 0, out.getCount());
|
||||
|
||||
if(pac.isFinished()) {
|
||||
System.out.println("testSimple: "+pac.getData());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void testStreaming() throws IOException
|
||||
{
|
||||
OpenByteArrayOutputStream out = new OpenByteArrayOutputStream();
|
||||
|
||||
////
|
||||
// sender
|
||||
//
|
||||
// initialize the streaming serializer
|
||||
Packer pk = new Packer(out);
|
||||
|
||||
// serialize 2 objects
|
||||
pk.packArray(3)
|
||||
.packInt(0)
|
||||
.packByte((byte)1)
|
||||
.packDouble(0.2);
|
||||
pk.packArray(3)
|
||||
.packInt(3)
|
||||
.packByte((byte)4)
|
||||
.packDouble(0.5);
|
||||
|
||||
// send it through the network
|
||||
InputStream sock = new ByteArrayInputStream(out.getBuffer(), 0, out.getCount());
|
||||
|
||||
|
||||
////
|
||||
// receiver
|
||||
//
|
||||
// initialize the streaming deserializer
|
||||
Unpacker pac = new Unpacker();
|
||||
int parsed = 0;
|
||||
|
||||
byte[] buf = new byte[1024];
|
||||
int buflen = 0;
|
||||
|
||||
while(true) {
|
||||
// receive data from the network
|
||||
int c = sock.read();
|
||||
if(c < 0) { return; }
|
||||
|
||||
buf[buflen++] = (byte)c;
|
||||
|
||||
// deserialize
|
||||
parsed = pac.execute(buf, parsed, buflen);
|
||||
if(pac.isFinished()) {
|
||||
// get an object
|
||||
Object msg = pac.getData();
|
||||
System.out.println("testStreaming: "+msg);
|
||||
|
||||
// reset the streaming deserializer
|
||||
pac.reset();
|
||||
buflen = 0;
|
||||
parsed = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
<project name="MessagePack for Java">
|
||||
<target name="prepare">
|
||||
<mkdir dir="build" />
|
||||
<mkdir dir="dist" />
|
||||
</target>
|
||||
<target name="clean">
|
||||
<delete dir="build"/>
|
||||
<delete dir="dist"/>
|
||||
</target>
|
||||
<target name="compile" depends="prepare">
|
||||
<javac srcdir="src" destdir="build" classpath="lib" source="1.5" target="1.5">
|
||||
<classpath><fileset dir="lib" /> </classpath>
|
||||
</javac>
|
||||
</target>
|
||||
</project>
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
package org.msgpack;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class GenericArray extends GenericObject {
|
||||
private ArrayList<GenericObject> array;
|
||||
|
||||
public GenericArray(int length)
|
||||
{
|
||||
this.array = new ArrayList<GenericObject>(length);
|
||||
}
|
||||
|
||||
public void add(GenericObject element)
|
||||
{
|
||||
array.add(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GenericObject> asArray()
|
||||
{
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package org.msgpack;
|
||||
|
||||
public class GenericBoolean extends GenericObject {
|
||||
boolean value;
|
||||
|
||||
public GenericBoolean(boolean value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean asBoolean()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package org.msgpack;
|
||||
|
||||
public class GenericLong extends GenericObject {
|
||||
long value;
|
||||
|
||||
public GenericLong(long value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long asLong()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
package org.msgpack;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class GenericMap extends GenericObject {
|
||||
private HashMap<GenericObject,GenericObject> map;
|
||||
|
||||
public GenericMap(int length)
|
||||
{
|
||||
this.map = new HashMap<GenericObject,GenericObject>(length);
|
||||
}
|
||||
|
||||
public void put(GenericObject key, GenericObject value)
|
||||
{
|
||||
map.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<GenericObject,GenericObject> asMap()
|
||||
{
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
package org.msgpack;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class GenericObject {
|
||||
public boolean asBoolean()
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public byte asByte()
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public short asShort()
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public int asInt()
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public long asLong()
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public String asString()
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public byte[] asBytes()
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public List<GenericObject> asArray()
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public Map<GenericObject,GenericObject> asMap()
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
package org.msgpack;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public class GenericRaw extends GenericObject {
|
||||
byte[] bytes;
|
||||
String string;
|
||||
|
||||
public GenericRaw()
|
||||
{
|
||||
this.bytes = new byte[0];
|
||||
this.string = null;
|
||||
}
|
||||
|
||||
public GenericRaw(byte[] bytes)
|
||||
{
|
||||
this.bytes = bytes;
|
||||
this.string = null;
|
||||
}
|
||||
|
||||
public GenericRaw(String string)
|
||||
{
|
||||
this.bytes = null;
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
public synchronized void setString(String string)
|
||||
{
|
||||
this.string = string;
|
||||
this.bytes = null;
|
||||
}
|
||||
|
||||
public synchronized void setBytes(byte[] bytes)
|
||||
{
|
||||
this.bytes = bytes;
|
||||
this.string = null;
|
||||
}
|
||||
|
||||
private static Charset UTF8_CHARSET = Charset.forName("UTF-8");
|
||||
|
||||
@Override
|
||||
public synchronized String asString()
|
||||
{
|
||||
if(string == null) {
|
||||
return string = new String(bytes, UTF8_CHARSET);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized byte[] asBytes()
|
||||
{
|
||||
if(bytes == null) {
|
||||
return bytes = string.getBytes(UTF8_CHARSET);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
package org.msgpack;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public class GenericRawRef extends GenericRaw {
|
||||
int offset;
|
||||
int length;
|
||||
|
||||
public GenericRawRef(byte[] bytes, int offset, int length)
|
||||
{
|
||||
this.bytes = bytes;
|
||||
this.offset = offset;
|
||||
this.length = length;
|
||||
this.string = null;
|
||||
}
|
||||
|
||||
public GenericRawRef(String string)
|
||||
{
|
||||
this.bytes = null;
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
public synchronized void setString(String string)
|
||||
{
|
||||
this.string = string;
|
||||
this.bytes = null;
|
||||
}
|
||||
|
||||
public synchronized void setBytes(byte[] bytes)
|
||||
{
|
||||
this.bytes = bytes;
|
||||
this.string = null;
|
||||
}
|
||||
|
||||
private static Charset UTF8_CHARSET = Charset.forName("UTF-8");
|
||||
|
||||
@Override
|
||||
public synchronized String asString()
|
||||
{
|
||||
if(string == null) {
|
||||
return string = new String(bytes, UTF8_CHARSET);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized byte[] asBytes()
|
||||
{
|
||||
if(bytes == null) {
|
||||
return bytes = string.getBytes(UTF8_CHARSET);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
package org.msgpack;
|
||||
|
||||
public class GenericShort extends GenericObject {
|
||||
short value;
|
||||
|
||||
public GenericShort(short value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short asShort()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int asInt()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long asLong()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue